(function(global, factory) {
    "use strict";
    if (typeof module === "object" && typeof module.exports === "object") {
        module.exports = global.document ? factory(global, true) : function(w) {
            if (!w.document) {
                throw new Error("jQuery requires a window with a document");
            }
            return factory(w);
        };
    } else {
        factory(global);
    }
})(typeof window !== "undefined" ? window : this, function(window, noGlobal) {
    "use strict";
    var arr = [];
    var getProto = Object.getPrototypeOf;
    var slice = arr.slice;
    var flat = arr.flat ? function(array) {
        return arr.flat.call(array);
    } : function(array) {
        return arr.concat.apply([], array);
    };
    var push = arr.push;
    var indexOf = arr.indexOf;
    var class2type = {};
    var toString = class2type.toString;
    var hasOwn = class2type.hasOwnProperty;
    var fnToString = hasOwn.toString;
    var ObjectFunctionString = fnToString.call(Object);
    var support = {};
    var isFunction = function isFunction(obj) {
        return typeof obj === "function" && typeof obj.nodeType !== "number" && typeof obj.item !== "function";
    };
    var isWindow = function isWindow(obj) {
        return obj != null && obj === obj.window;
    };
    var document = window.document;
    var preservedScriptAttributes = {
        type: true,
        src: true,
        nonce: true,
        noModule: true
    };
    function DOMEval(code, node, doc) {
        doc = doc || document;
        var i, val, script = doc.createElement("script");
        script.text = code;
        if (node) {
            for (i in preservedScriptAttributes) {
                val = node[i] || node.getAttribute && node.getAttribute(i);
                if (val) {
                    script.setAttribute(i, val);
                }
            }
        }
        doc.head.appendChild(script).parentNode.removeChild(script);
    }
    function toType(obj) {
        if (obj == null) {
            return obj + "";
        }
        return typeof obj === "object" || typeof obj === "function" ? class2type[toString.call(obj)] || "object" : typeof obj;
    }
    var version = "3.5.1", jQuery = function(selector, context) {
        return new jQuery.fn.init(selector, context);
    };
    jQuery.fn = jQuery.prototype = {
        jquery: version,
        constructor: jQuery,
        length: 0,
        toArray: function() {
            return slice.call(this);
        },
        get: function(num) {
            if (num == null) {
                return slice.call(this);
            }
            return num < 0 ? this[num + this.length] : this[num];
        },
        pushStack: function(elems) {
            var ret = jQuery.merge(this.constructor(), elems);
            ret.prevObject = this;
            return ret;
        },
        each: function(callback) {
            return jQuery.each(this, callback);
        },
        map: function(callback) {
            return this.pushStack(jQuery.map(this, function(elem, i) {
                return callback.call(elem, i, elem);
            }));
        },
        slice: function() {
            return this.pushStack(slice.apply(this, arguments));
        },
        first: function() {
            return this.eq(0);
        },
        last: function() {
            return this.eq(-1);
        },
        even: function() {
            return this.pushStack(jQuery.grep(this, function(_elem, i) {
                return (i + 1) % 2;
            }));
        },
        odd: function() {
            return this.pushStack(jQuery.grep(this, function(_elem, i) {
                return i % 2;
            }));
        },
        eq: function(i) {
            var len = this.length, j = +i + (i < 0 ? len : 0);
            return this.pushStack(j >= 0 && j < len ? [ this[j] ] : []);
        },
        end: function() {
            return this.prevObject || this.constructor();
        },
        push: push,
        sort: arr.sort,
        splice: arr.splice
    };
    jQuery.extend = jQuery.fn.extend = function() {
        var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {}, i = 1, length = arguments.length, deep = false;
        if (typeof target === "boolean") {
            deep = target;
            target = arguments[i] || {};
            i++;
        }
        if (typeof target !== "object" && !isFunction(target)) {
            target = {};
        }
        if (i === length) {
            target = this;
            i--;
        }
        for (;i < length; i++) {
            if ((options = arguments[i]) != null) {
                for (name in options) {
                    copy = options[name];
                    if (name === "__proto__" || target === copy) {
                        continue;
                    }
                    if (deep && copy && (jQuery.isPlainObject(copy) || (copyIsArray = Array.isArray(copy)))) {
                        src = target[name];
                        if (copyIsArray && !Array.isArray(src)) {
                            clone = [];
                        } else if (!copyIsArray && !jQuery.isPlainObject(src)) {
                            clone = {};
                        } else {
                            clone = src;
                        }
                        copyIsArray = false;
                        target[name] = jQuery.extend(deep, clone, copy);
                    } else if (copy !== undefined) {
                        target[name] = copy;
                    }
                }
            }
        }
        return target;
    };
    jQuery.extend({
        expando: "jQuery" + (version + Math.random()).replace(/\D/g, ""),
        isReady: true,
        error: function(msg) {
            throw new Error(msg);
        },
        noop: function() {},
        isPlainObject: function(obj) {
            var proto, Ctor;
            if (!obj || toString.call(obj) !== "[object Object]") {
                return false;
            }
            proto = getProto(obj);
            if (!proto) {
                return true;
            }
            Ctor = hasOwn.call(proto, "constructor") && proto.constructor;
            return typeof Ctor === "function" && fnToString.call(Ctor) === ObjectFunctionString;
        },
        isEmptyObject: function(obj) {
            var name;
            for (name in obj) {
                return false;
            }
            return true;
        },
        globalEval: function(code, options, doc) {
            DOMEval(code, {
                nonce: options && options.nonce
            }, doc);
        },
        each: function(obj, callback) {
            var length, i = 0;
            if (isArrayLike(obj)) {
                length = obj.length;
                for (;i < length; i++) {
                    if (callback.call(obj[i], i, obj[i]) === false) {
                        break;
                    }
                }
            } else {
                for (i in obj) {
                    if (callback.call(obj[i], i, obj[i]) === false) {
                        break;
                    }
                }
            }
            return obj;
        },
        makeArray: function(arr, results) {
            var ret = results || [];
            if (arr != null) {
                if (isArrayLike(Object(arr))) {
                    jQuery.merge(ret, typeof arr === "string" ? [ arr ] : arr);
                } else {
                    push.call(ret, arr);
                }
            }
            return ret;
        },
        inArray: function(elem, arr, i) {
            return arr == null ? -1 : indexOf.call(arr, elem, i);
        },
        merge: function(first, second) {
            var len = +second.length, j = 0, i = first.length;
            for (;j < len; j++) {
                first[i++] = second[j];
            }
            first.length = i;
            return first;
        },
        grep: function(elems, callback, invert) {
            var callbackInverse, matches = [], i = 0, length = elems.length, callbackExpect = !invert;
            for (;i < length; i++) {
                callbackInverse = !callback(elems[i], i);
                if (callbackInverse !== callbackExpect) {
                    matches.push(elems[i]);
                }
            }
            return matches;
        },
        map: function(elems, callback, arg) {
            var length, value, i = 0, ret = [];
            if (isArrayLike(elems)) {
                length = elems.length;
                for (;i < length; i++) {
                    value = callback(elems[i], i, arg);
                    if (value != null) {
                        ret.push(value);
                    }
                }
            } else {
                for (i in elems) {
                    value = callback(elems[i], i, arg);
                    if (value != null) {
                        ret.push(value);
                    }
                }
            }
            return flat(ret);
        },
        guid: 1,
        support: support
    });
    if (typeof Symbol === "function") {
        jQuery.fn[Symbol.iterator] = arr[Symbol.iterator];
    }
    jQuery.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "), function(_i, name) {
        class2type["[object " + name + "]"] = name.toLowerCase();
    });
    function isArrayLike(obj) {
        var length = !!obj && "length" in obj && obj.length, type = toType(obj);
        if (isFunction(obj) || isWindow(obj)) {
            return false;
        }
        return type === "array" || length === 0 || typeof length === "number" && length > 0 && length - 1 in obj;
    }
    var Sizzle = function(window) {
        var i, support, Expr, getText, isXML, tokenize, compile, select, outermostContext, sortInput, hasDuplicate, setDocument, document, docElem, documentIsHTML, rbuggyQSA, rbuggyMatches, matches, contains, expando = "sizzle" + 1 * new Date(), preferredDoc = window.document, dirruns = 0, done = 0, classCache = createCache(), tokenCache = createCache(), compilerCache = createCache(), nonnativeSelectorCache = createCache(), sortOrder = function(a, b) {
            if (a === b) {
                hasDuplicate = true;
            }
            return 0;
        }, hasOwn = {}.hasOwnProperty, arr = [], pop = arr.pop, pushNative = arr.push, push = arr.push, slice = arr.slice, indexOf = function(list, elem) {
            var i = 0, len = list.length;
            for (;i < len; i++) {
                if (list[i] === elem) {
                    return i;
                }
            }
            return -1;
        }, booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + "ismap|loop|multiple|open|readonly|required|scoped", whitespace = "[\\x20\\t\\r\\n\\f]", identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + "*([*^$|!~]?=)" + whitespace + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + "*\\]", pseudos = ":(" + identifier + ")(?:\\((" + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + ".*" + ")\\)|)", rwhitespace = new RegExp(whitespace + "+", "g"), rtrim = new RegExp("^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g"), rcomma = new RegExp("^" + whitespace + "*," + whitespace + "*"), rcombinators = new RegExp("^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*"), rdescend = new RegExp(whitespace + "|>"), rpseudo = new RegExp(pseudos), ridentifier = new RegExp("^" + identifier + "$"), matchExpr = {
            ID: new RegExp("^#(" + identifier + ")"),
            CLASS: new RegExp("^\\.(" + identifier + ")"),
            TAG: new RegExp("^(" + identifier + "|[*])"),
            ATTR: new RegExp("^" + attributes),
            PSEUDO: new RegExp("^" + pseudos),
            CHILD: new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i"),
            bool: new RegExp("^(?:" + booleans + ")$", "i"),
            needsContext: new RegExp("^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i")
        }, rhtml = /HTML$/i, rinputs = /^(?:input|select|textarea|button)$/i, rheader = /^h\d$/i, rnative = /^[^{]+\{\s*\[native \w/, rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, rsibling = /[+~]/, runescape = new RegExp("\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g"), funescape = function(escape, nonHex) {
            var high = "0x" + escape.slice(1) - 65536;
            return nonHex ? nonHex : high < 0 ? String.fromCharCode(high + 65536) : String.fromCharCode(high >> 10 | 55296, high & 1023 | 56320);
        }, rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, fcssescape = function(ch, asCodePoint) {
            if (asCodePoint) {
                if (ch === "\0") {
                    return "�";
                }
                return ch.slice(0, -1) + "\\" + ch.charCodeAt(ch.length - 1).toString(16) + " ";
            }
            return "\\" + ch;
        }, unloadHandler = function() {
            setDocument();
        }, inDisabledFieldset = addCombinator(function(elem) {
            return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset";
        }, {
            dir: "parentNode",
            next: "legend"
        });
        try {
            push.apply(arr = slice.call(preferredDoc.childNodes), preferredDoc.childNodes);
            arr[preferredDoc.childNodes.length].nodeType;
        } catch (e) {
            push = {
                apply: arr.length ? function(target, els) {
                    pushNative.apply(target, slice.call(els));
                } : function(target, els) {
                    var j = target.length, i = 0;
                    while (target[j++] = els[i++]) {}
                    target.length = j - 1;
                }
            };
        }
        function Sizzle(selector, context, results, seed) {
            var m, i, elem, nid, match, groups, newSelector, newContext = context && context.ownerDocument, nodeType = context ? context.nodeType : 9;
            results = results || [];
            if (typeof selector !== "string" || !selector || nodeType !== 1 && nodeType !== 9 && nodeType !== 11) {
                return results;
            }
            if (!seed) {
                setDocument(context);
                context = context || document;
                if (documentIsHTML) {
                    if (nodeType !== 11 && (match = rquickExpr.exec(selector))) {
                        if (m = match[1]) {
                            if (nodeType === 9) {
                                if (elem = context.getElementById(m)) {
                                    if (elem.id === m) {
                                        results.push(elem);
                                        return results;
                                    }
                                } else {
                                    return results;
                                }
                            } else {
                                if (newContext && (elem = newContext.getElementById(m)) && contains(context, elem) && elem.id === m) {
                                    results.push(elem);
                                    return results;
                                }
                            }
                        } else if (match[2]) {
                            push.apply(results, context.getElementsByTagName(selector));
                            return results;
                        } else if ((m = match[3]) && support.getElementsByClassName && context.getElementsByClassName) {
                            push.apply(results, context.getElementsByClassName(m));
                            return results;
                        }
                    }
                    if (support.qsa && !nonnativeSelectorCache[selector + " "] && (!rbuggyQSA || !rbuggyQSA.test(selector)) && (nodeType !== 1 || context.nodeName.toLowerCase() !== "object")) {
                        newSelector = selector;
                        newContext = context;
                        if (nodeType === 1 && (rdescend.test(selector) || rcombinators.test(selector))) {
                            newContext = rsibling.test(selector) && testContext(context.parentNode) || context;
                            if (newContext !== context || !support.scope) {
                                if (nid = context.getAttribute("id")) {
                                    nid = nid.replace(rcssescape, fcssescape);
                                } else {
                                    context.setAttribute("id", nid = expando);
                                }
                            }
                            groups = tokenize(selector);
                            i = groups.length;
                            while (i--) {
                                groups[i] = (nid ? "#" + nid : ":scope") + " " + toSelector(groups[i]);
                            }
                            newSelector = groups.join(",");
                        }
                        try {
                            push.apply(results, newContext.querySelectorAll(newSelector));
                            return results;
                        } catch (qsaError) {
                            nonnativeSelectorCache(selector, true);
                        } finally {
                            if (nid === expando) {
                                context.removeAttribute("id");
                            }
                        }
                    }
                }
            }
            return select(selector.replace(rtrim, "$1"), context, results, seed);
        }
        function createCache() {
            var keys = [];
            function cache(key, value) {
                if (keys.push(key + " ") > Expr.cacheLength) {
                    delete cache[keys.shift()];
                }
                return cache[key + " "] = value;
            }
            return cache;
        }
        function markFunction(fn) {
            fn[expando] = true;
            return fn;
        }
        function assert(fn) {
            var el = document.createElement("fieldset");
            try {
                return !!fn(el);
            } catch (e) {
                return false;
            } finally {
                if (el.parentNode) {
                    el.parentNode.removeChild(el);
                }
                el = null;
            }
        }
        function addHandle(attrs, handler) {
            var arr = attrs.split("|"), i = arr.length;
            while (i--) {
                Expr.attrHandle[arr[i]] = handler;
            }
        }
        function siblingCheck(a, b) {
            var cur = b && a, diff = cur && a.nodeType === 1 && b.nodeType === 1 && a.sourceIndex - b.sourceIndex;
            if (diff) {
                return diff;
            }
            if (cur) {
                while (cur = cur.nextSibling) {
                    if (cur === b) {
                        return -1;
                    }
                }
            }
            return a ? 1 : -1;
        }
        function createInputPseudo(type) {
            return function(elem) {
                var name = elem.nodeName.toLowerCase();
                return name === "input" && elem.type === type;
            };
        }
        function createButtonPseudo(type) {
            return function(elem) {
                var name = elem.nodeName.toLowerCase();
                return (name === "input" || name === "button") && elem.type === type;
            };
        }
        function createDisabledPseudo(disabled) {
            return function(elem) {
                if ("form" in elem) {
                    if (elem.parentNode && elem.disabled === false) {
                        if ("label" in elem) {
                            if ("label" in elem.parentNode) {
                                return elem.parentNode.disabled === disabled;
                            } else {
                                return elem.disabled === disabled;
                            }
                        }
                        return elem.isDisabled === disabled || elem.isDisabled !== !disabled && inDisabledFieldset(elem) === disabled;
                    }
                    return elem.disabled === disabled;
                } else if ("label" in elem) {
                    return elem.disabled === disabled;
                }
                return false;
            };
        }
        function createPositionalPseudo(fn) {
            return markFunction(function(argument) {
                argument = +argument;
                return markFunction(function(seed, matches) {
                    var j, matchIndexes = fn([], seed.length, argument), i = matchIndexes.length;
                    while (i--) {
                        if (seed[j = matchIndexes[i]]) {
                            seed[j] = !(matches[j] = seed[j]);
                        }
                    }
                });
            });
        }
        function testContext(context) {
            return context && typeof context.getElementsByTagName !== "undefined" && context;
        }
        support = Sizzle.support = {};
        isXML = Sizzle.isXML = function(elem) {
            var namespace = elem.namespaceURI, docElem = (elem.ownerDocument || elem).documentElement;
            return !rhtml.test(namespace || docElem && docElem.nodeName || "HTML");
        };
        setDocument = Sizzle.setDocument = function(node) {
            var hasCompare, subWindow, doc = node ? node.ownerDocument || node : preferredDoc;
            if (doc == document || doc.nodeType !== 9 || !doc.documentElement) {
                return document;
            }
            document = doc;
            docElem = document.documentElement;
            documentIsHTML = !isXML(document);
            if (preferredDoc != document && (subWindow = document.defaultView) && subWindow.top !== subWindow) {
                if (subWindow.addEventListener) {
                    subWindow.addEventListener("unload", unloadHandler, false);
                } else if (subWindow.attachEvent) {
                    subWindow.attachEvent("onunload", unloadHandler);
                }
            }
            support.scope = assert(function(el) {
                docElem.appendChild(el).appendChild(document.createElement("div"));
                return typeof el.querySelectorAll !== "undefined" && !el.querySelectorAll(":scope fieldset div").length;
            });
            support.attributes = assert(function(el) {
                el.className = "i";
                return !el.getAttribute("className");
            });
            support.getElementsByTagName = assert(function(el) {
                el.appendChild(document.createComment(""));
                return !el.getElementsByTagName("*").length;
            });
            support.getElementsByClassName = rnative.test(document.getElementsByClassName);
            support.getById = assert(function(el) {
                docElem.appendChild(el).id = expando;
                return !document.getElementsByName || !document.getElementsByName(expando).length;
            });
            if (support.getById) {
                Expr.filter["ID"] = function(id) {
                    var attrId = id.replace(runescape, funescape);
                    return function(elem) {
                        return elem.getAttribute("id") === attrId;
                    };
                };
                Expr.find["ID"] = function(id, context) {
                    if (typeof context.getElementById !== "undefined" && documentIsHTML) {
                        var elem = context.getElementById(id);
                        return elem ? [ elem ] : [];
                    }
                };
            } else {
                Expr.filter["ID"] = function(id) {
                    var attrId = id.replace(runescape, funescape);
                    return function(elem) {
                        var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
                        return node && node.value === attrId;
                    };
                };
                Expr.find["ID"] = function(id, context) {
                    if (typeof context.getElementById !== "undefined" && documentIsHTML) {
                        var node, i, elems, elem = context.getElementById(id);
                        if (elem) {
                            node = elem.getAttributeNode("id");
                            if (node && node.value === id) {
                                return [ elem ];
                            }
                            elems = context.getElementsByName(id);
                            i = 0;
                            while (elem = elems[i++]) {
                                node = elem.getAttributeNode("id");
                                if (node && node.value === id) {
                                    return [ elem ];
                                }
                            }
                        }
                        return [];
                    }
                };
            }
            Expr.find["TAG"] = support.getElementsByTagName ? function(tag, context) {
                if (typeof context.getElementsByTagName !== "undefined") {
                    return context.getElementsByTagName(tag);
                } else if (support.qsa) {
                    return context.querySelectorAll(tag);
                }
            } : function(tag, context) {
                var elem, tmp = [], i = 0, results = context.getElementsByTagName(tag);
                if (tag === "*") {
                    while (elem = results[i++]) {
                        if (elem.nodeType === 1) {
                            tmp.push(elem);
                        }
                    }
                    return tmp;
                }
                return results;
            };
            Expr.find["CLASS"] = support.getElementsByClassName && function(className, context) {
                if (typeof context.getElementsByClassName !== "undefined" && documentIsHTML) {
                    return context.getElementsByClassName(className);
                }
            };
            rbuggyMatches = [];
            rbuggyQSA = [];
            if (support.qsa = rnative.test(document.querySelectorAll)) {
                assert(function(el) {
                    var input;
                    docElem.appendChild(el).innerHTML = "<a id='" + expando + "'></a>" + "<select id='" + expando + "-\r\\' msallowcapture=''>" + "<option selected=''></option></select>";
                    if (el.querySelectorAll("[msallowcapture^='']").length) {
                        rbuggyQSA.push("[*^$]=" + whitespace + "*(?:''|\"\")");
                    }
                    if (!el.querySelectorAll("[selected]").length) {
                        rbuggyQSA.push("\\[" + whitespace + "*(?:value|" + booleans + ")");
                    }
                    if (!el.querySelectorAll("[id~=" + expando + "-]").length) {
                        rbuggyQSA.push("~=");
                    }
                    input = document.createElement("input");
                    input.setAttribute("name", "");
                    el.appendChild(input);
                    if (!el.querySelectorAll("[name='']").length) {
                        rbuggyQSA.push("\\[" + whitespace + "*name" + whitespace + "*=" + whitespace + "*(?:''|\"\")");
                    }
                    if (!el.querySelectorAll(":checked").length) {
                        rbuggyQSA.push(":checked");
                    }
                    if (!el.querySelectorAll("a#" + expando + "+*").length) {
                        rbuggyQSA.push(".#.+[+~]");
                    }
                    el.querySelectorAll("\\\f");
                    rbuggyQSA.push("[\\r\\n\\f]");
                });
                assert(function(el) {
                    el.innerHTML = "<a href='' disabled='disabled'></a>" + "<select disabled='disabled'><option/></select>";
                    var input = document.createElement("input");
                    input.setAttribute("type", "hidden");
                    el.appendChild(input).setAttribute("name", "D");
                    if (el.querySelectorAll("[name=d]").length) {
                        rbuggyQSA.push("name" + whitespace + "*[*^$|!~]?=");
                    }
                    if (el.querySelectorAll(":enabled").length !== 2) {
                        rbuggyQSA.push(":enabled", ":disabled");
                    }
                    docElem.appendChild(el).disabled = true;
                    if (el.querySelectorAll(":disabled").length !== 2) {
                        rbuggyQSA.push(":enabled", ":disabled");
                    }
                    el.querySelectorAll("*,:x");
                    rbuggyQSA.push(",.*:");
                });
            }
            if (support.matchesSelector = rnative.test(matches = docElem.matches || docElem.webkitMatchesSelector || docElem.mozMatchesSelector || docElem.oMatchesSelector || docElem.msMatchesSelector)) {
                assert(function(el) {
                    support.disconnectedMatch = matches.call(el, "*");
                    matches.call(el, "[s!='']:x");
                    rbuggyMatches.push("!=", pseudos);
                });
            }
            rbuggyQSA = rbuggyQSA.length && new RegExp(rbuggyQSA.join("|"));
            rbuggyMatches = rbuggyMatches.length && new RegExp(rbuggyMatches.join("|"));
            hasCompare = rnative.test(docElem.compareDocumentPosition);
            contains = hasCompare || rnative.test(docElem.contains) ? function(a, b) {
                var adown = a.nodeType === 9 ? a.documentElement : a, bup = b && b.parentNode;
                return a === bup || !!(bup && bup.nodeType === 1 && (adown.contains ? adown.contains(bup) : a.compareDocumentPosition && a.compareDocumentPosition(bup) & 16));
            } : function(a, b) {
                if (b) {
                    while (b = b.parentNode) {
                        if (b === a) {
                            return true;
                        }
                    }
                }
                return false;
            };
            sortOrder = hasCompare ? function(a, b) {
                if (a === b) {
                    hasDuplicate = true;
                    return 0;
                }
                var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
                if (compare) {
                    return compare;
                }
                compare = (a.ownerDocument || a) == (b.ownerDocument || b) ? a.compareDocumentPosition(b) : 1;
                if (compare & 1 || !support.sortDetached && b.compareDocumentPosition(a) === compare) {
                    if (a == document || a.ownerDocument == preferredDoc && contains(preferredDoc, a)) {
                        return -1;
                    }
                    if (b == document || b.ownerDocument == preferredDoc && contains(preferredDoc, b)) {
                        return 1;
                    }
                    return sortInput ? indexOf(sortInput, a) - indexOf(sortInput, b) : 0;
                }
                return compare & 4 ? -1 : 1;
            } : function(a, b) {
                if (a === b) {
                    hasDuplicate = true;
                    return 0;
                }
                var cur, i = 0, aup = a.parentNode, bup = b.parentNode, ap = [ a ], bp = [ b ];
                if (!aup || !bup) {
                    return a == document ? -1 : b == document ? 1 : aup ? -1 : bup ? 1 : sortInput ? indexOf(sortInput, a) - indexOf(sortInput, b) : 0;
                } else if (aup === bup) {
                    return siblingCheck(a, b);
                }
                cur = a;
                while (cur = cur.parentNode) {
                    ap.unshift(cur);
                }
                cur = b;
                while (cur = cur.parentNode) {
                    bp.unshift(cur);
                }
                while (ap[i] === bp[i]) {
                    i++;
                }
                return i ? siblingCheck(ap[i], bp[i]) : ap[i] == preferredDoc ? -1 : bp[i] == preferredDoc ? 1 : 0;
            };
            return document;
        };
        Sizzle.matches = function(expr, elements) {
            return Sizzle(expr, null, null, elements);
        };
        Sizzle.matchesSelector = function(elem, expr) {
            setDocument(elem);
            if (support.matchesSelector && documentIsHTML && !nonnativeSelectorCache[expr + " "] && (!rbuggyMatches || !rbuggyMatches.test(expr)) && (!rbuggyQSA || !rbuggyQSA.test(expr))) {
                try {
                    var ret = matches.call(elem, expr);
                    if (ret || support.disconnectedMatch || elem.document && elem.document.nodeType !== 11) {
                        return ret;
                    }
                } catch (e) {
                    nonnativeSelectorCache(expr, true);
                }
            }
            return Sizzle(expr, document, null, [ elem ]).length > 0;
        };
        Sizzle.contains = function(context, elem) {
            if ((context.ownerDocument || context) != document) {
                setDocument(context);
            }
            return contains(context, elem);
        };
        Sizzle.attr = function(elem, name) {
            if ((elem.ownerDocument || elem) != document) {
                setDocument(elem);
            }
            var fn = Expr.attrHandle[name.toLowerCase()], val = fn && hasOwn.call(Expr.attrHandle, name.toLowerCase()) ? fn(elem, name, !documentIsHTML) : undefined;
            return val !== undefined ? val : support.attributes || !documentIsHTML ? elem.getAttribute(name) : (val = elem.getAttributeNode(name)) && val.specified ? val.value : null;
        };
        Sizzle.escape = function(sel) {
            return (sel + "").replace(rcssescape, fcssescape);
        };
        Sizzle.error = function(msg) {
            throw new Error("Syntax error, unrecognized expression: " + msg);
        };
        Sizzle.uniqueSort = function(results) {
            var elem, duplicates = [], j = 0, i = 0;
            hasDuplicate = !support.detectDuplicates;
            sortInput = !support.sortStable && results.slice(0);
            results.sort(sortOrder);
            if (hasDuplicate) {
                while (elem = results[i++]) {
                    if (elem === results[i]) {
                        j = duplicates.push(i);
                    }
                }
                while (j--) {
                    results.splice(duplicates[j], 1);
                }
            }
            sortInput = null;
            return results;
        };
        getText = Sizzle.getText = function(elem) {
            var node, ret = "", i = 0, nodeType = elem.nodeType;
            if (!nodeType) {
                while (node = elem[i++]) {
                    ret += getText(node);
                }
            } else if (nodeType === 1 || nodeType === 9 || nodeType === 11) {
                if (typeof elem.textContent === "string") {
                    return elem.textContent;
                } else {
                    for (elem = elem.firstChild; elem; elem = elem.nextSibling) {
                        ret += getText(elem);
                    }
                }
            } else if (nodeType === 3 || nodeType === 4) {
                return elem.nodeValue;
            }
            return ret;
        };
        Expr = Sizzle.selectors = {
            cacheLength: 50,
            createPseudo: markFunction,
            match: matchExpr,
            attrHandle: {},
            find: {},
            relative: {
                ">": {
                    dir: "parentNode",
                    first: true
                },
                " ": {
                    dir: "parentNode"
                },
                "+": {
                    dir: "previousSibling",
                    first: true
                },
                "~": {
                    dir: "previousSibling"
                }
            },
            preFilter: {
                ATTR: function(match) {
                    match[1] = match[1].replace(runescape, funescape);
                    match[3] = (match[3] || match[4] || match[5] || "").replace(runescape, funescape);
                    if (match[2] === "~=") {
                        match[3] = " " + match[3] + " ";
                    }
                    return match.slice(0, 4);
                },
                CHILD: function(match) {
                    match[1] = match[1].toLowerCase();
                    if (match[1].slice(0, 3) === "nth") {
                        if (!match[3]) {
                            Sizzle.error(match[0]);
                        }
                        match[4] = +(match[4] ? match[5] + (match[6] || 1) : 2 * (match[3] === "even" || match[3] === "odd"));
                        match[5] = +(match[7] + match[8] || match[3] === "odd");
                    } else if (match[3]) {
                        Sizzle.error(match[0]);
                    }
                    return match;
                },
                PSEUDO: function(match) {
                    var excess, unquoted = !match[6] && match[2];
                    if (matchExpr["CHILD"].test(match[0])) {
                        return null;
                    }
                    if (match[3]) {
                        match[2] = match[4] || match[5] || "";
                    } else if (unquoted && rpseudo.test(unquoted) && (excess = tokenize(unquoted, true)) && (excess = unquoted.indexOf(")", unquoted.length - excess) - unquoted.length)) {
                        match[0] = match[0].slice(0, excess);
                        match[2] = unquoted.slice(0, excess);
                    }
                    return match.slice(0, 3);
                }
            },
            filter: {
                TAG: function(nodeNameSelector) {
                    var nodeName = nodeNameSelector.replace(runescape, funescape).toLowerCase();
                    return nodeNameSelector === "*" ? function() {
                        return true;
                    } : function(elem) {
                        return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
                    };
                },
                CLASS: function(className) {
                    var pattern = classCache[className + " "];
                    return pattern || (pattern = new RegExp("(^|" + whitespace + ")" + className + "(" + whitespace + "|$)")) && classCache(className, function(elem) {
                        return pattern.test(typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "");
                    });
                },
                ATTR: function(name, operator, check) {
                    return function(elem) {
                        var result = Sizzle.attr(elem, name);
                        if (result == null) {
                            return operator === "!=";
                        }
                        if (!operator) {
                            return true;
                        }
                        result += "";
                        return operator === "=" ? result === check : operator === "!=" ? result !== check : operator === "^=" ? check && result.indexOf(check) === 0 : operator === "*=" ? check && result.indexOf(check) > -1 : operator === "$=" ? check && result.slice(-check.length) === check : operator === "~=" ? (" " + result.replace(rwhitespace, " ") + " ").indexOf(check) > -1 : operator === "|=" ? result === check || result.slice(0, check.length + 1) === check + "-" : false;
                    };
                },
                CHILD: function(type, what, _argument, first, last) {
                    var simple = type.slice(0, 3) !== "nth", forward = type.slice(-4) !== "last", ofType = what === "of-type";
                    return first === 1 && last === 0 ? function(elem) {
                        return !!elem.parentNode;
                    } : function(elem, _context, xml) {
                        var cache, uniqueCache, outerCache, node, nodeIndex, start, dir = simple !== forward ? "nextSibling" : "previousSibling", parent = elem.parentNode, name = ofType && elem.nodeName.toLowerCase(), useCache = !xml && !ofType, diff = false;
                        if (parent) {
                            if (simple) {
                                while (dir) {
                                    node = elem;
                                    while (node = node[dir]) {
                                        if (ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1) {
                                            return false;
                                        }
                                    }
                                    start = dir = type === "only" && !start && "nextSibling";
                                }
                                return true;
                            }
                            start = [ forward ? parent.firstChild : parent.lastChild ];
                            if (forward && useCache) {
                                node = parent;
                                outerCache = node[expando] || (node[expando] = {});
                                uniqueCache = outerCache[node.uniqueID] || (outerCache[node.uniqueID] = {});
                                cache = uniqueCache[type] || [];
                                nodeIndex = cache[0] === dirruns && cache[1];
                                diff = nodeIndex && cache[2];
                                node = nodeIndex && parent.childNodes[nodeIndex];
                                while (node = ++nodeIndex && node && node[dir] || (diff = nodeIndex = 0) || start.pop()) {
                                    if (node.nodeType === 1 && ++diff && node === elem) {
                                        uniqueCache[type] = [ dirruns, nodeIndex, diff ];
                                        break;
                                    }
                                }
                            } else {
                                if (useCache) {
                                    node = elem;
                                    outerCache = node[expando] || (node[expando] = {});
                                    uniqueCache = outerCache[node.uniqueID] || (outerCache[node.uniqueID] = {});
                                    cache = uniqueCache[type] || [];
                                    nodeIndex = cache[0] === dirruns && cache[1];
                                    diff = nodeIndex;
                                }
                                if (diff === false) {
                                    while (node = ++nodeIndex && node && node[dir] || (diff = nodeIndex = 0) || start.pop()) {
                                        if ((ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1) && ++diff) {
                                            if (useCache) {
                                                outerCache = node[expando] || (node[expando] = {});
                                                uniqueCache = outerCache[node.uniqueID] || (outerCache[node.uniqueID] = {});
                                                uniqueCache[type] = [ dirruns, diff ];
                                            }
                                            if (node === elem) {
                                                break;
                                            }
                                        }
                                    }
                                }
                            }
                            diff -= last;
                            return diff === first || diff % first === 0 && diff / first >= 0;
                        }
                    };
                },
                PSEUDO: function(pseudo, argument) {
                    var args, fn = Expr.pseudos[pseudo] || Expr.setFilters[pseudo.toLowerCase()] || Sizzle.error("unsupported pseudo: " + pseudo);
                    if (fn[expando]) {
                        return fn(argument);
                    }
                    if (fn.length > 1) {
                        args = [ pseudo, pseudo, "", argument ];
                        return Expr.setFilters.hasOwnProperty(pseudo.toLowerCase()) ? markFunction(function(seed, matches) {
                            var idx, matched = fn(seed, argument), i = matched.length;
                            while (i--) {
                                idx = indexOf(seed, matched[i]);
                                seed[idx] = !(matches[idx] = matched[i]);
                            }
                        }) : function(elem) {
                            return fn(elem, 0, args);
                        };
                    }
                    return fn;
                }
            },
            pseudos: {
                not: markFunction(function(selector) {
                    var input = [], results = [], matcher = compile(selector.replace(rtrim, "$1"));
                    return matcher[expando] ? markFunction(function(seed, matches, _context, xml) {
                        var elem, unmatched = matcher(seed, null, xml, []), i = seed.length;
                        while (i--) {
                            if (elem = unmatched[i]) {
                                seed[i] = !(matches[i] = elem);
                            }
                        }
                    }) : function(elem, _context, xml) {
                        input[0] = elem;
                        matcher(input, null, xml, results);
                        input[0] = null;
                        return !results.pop();
                    };
                }),
                has: markFunction(function(selector) {
                    return function(elem) {
                        return Sizzle(selector, elem).length > 0;
                    };
                }),
                contains: markFunction(function(text) {
                    text = text.replace(runescape, funescape);
                    return function(elem) {
                        return (elem.textContent || getText(elem)).indexOf(text) > -1;
                    };
                }),
                lang: markFunction(function(lang) {
                    if (!ridentifier.test(lang || "")) {
                        Sizzle.error("unsupported lang: " + lang);
                    }
                    lang = lang.replace(runescape, funescape).toLowerCase();
                    return function(elem) {
                        var elemLang;
                        do {
                            if (elemLang = documentIsHTML ? elem.lang : elem.getAttribute("xml:lang") || elem.getAttribute("lang")) {
                                elemLang = elemLang.toLowerCase();
                                return elemLang === lang || elemLang.indexOf(lang + "-") === 0;
                            }
                        } while ((elem = elem.parentNode) && elem.nodeType === 1);
                        return false;
                    };
                }),
                target: function(elem) {
                    var hash = window.location && window.location.hash;
                    return hash && hash.slice(1) === elem.id;
                },
                root: function(elem) {
                    return elem === docElem;
                },
                focus: function(elem) {
                    return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
                },
                enabled: createDisabledPseudo(false),
                disabled: createDisabledPseudo(true),
                checked: function(elem) {
                    var nodeName = elem.nodeName.toLowerCase();
                    return nodeName === "input" && !!elem.checked || nodeName === "option" && !!elem.selected;
                },
                selected: function(elem) {
                    if (elem.parentNode) {
                        elem.parentNode.selectedIndex;
                    }
                    return elem.selected === true;
                },
                empty: function(elem) {
                    for (elem = elem.firstChild; elem; elem = elem.nextSibling) {
                        if (elem.nodeType < 6) {
                            return false;
                        }
                    }
                    return true;
                },
                parent: function(elem) {
                    return !Expr.pseudos["empty"](elem);
                },
                header: function(elem) {
                    return rheader.test(elem.nodeName);
                },
                input: function(elem) {
                    return rinputs.test(elem.nodeName);
                },
                button: function(elem) {
                    var name = elem.nodeName.toLowerCase();
                    return name === "input" && elem.type === "button" || name === "button";
                },
                text: function(elem) {
                    var attr;
                    return elem.nodeName.toLowerCase() === "input" && elem.type === "text" && ((attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text");
                },
                first: createPositionalPseudo(function() {
                    return [ 0 ];
                }),
                last: createPositionalPseudo(function(_matchIndexes, length) {
                    return [ length - 1 ];
                }),
                eq: createPositionalPseudo(function(_matchIndexes, length, argument) {
                    return [ argument < 0 ? argument + length : argument ];
                }),
                even: createPositionalPseudo(function(matchIndexes, length) {
                    var i = 0;
                    for (;i < length; i += 2) {
                        matchIndexes.push(i);
                    }
                    return matchIndexes;
                }),
                odd: createPositionalPseudo(function(matchIndexes, length) {
                    var i = 1;
                    for (;i < length; i += 2) {
                        matchIndexes.push(i);
                    }
                    return matchIndexes;
                }),
                lt: createPositionalPseudo(function(matchIndexes, length, argument) {
                    var i = argument < 0 ? argument + length : argument > length ? length : argument;
                    for (;--i >= 0; ) {
                        matchIndexes.push(i);
                    }
                    return matchIndexes;
                }),
                gt: createPositionalPseudo(function(matchIndexes, length, argument) {
                    var i = argument < 0 ? argument + length : argument;
                    for (;++i < length; ) {
                        matchIndexes.push(i);
                    }
                    return matchIndexes;
                })
            }
        };
        Expr.pseudos["nth"] = Expr.pseudos["eq"];
        for (i in {
            radio: true,
            checkbox: true,
            file: true,
            password: true,
            image: true
        }) {
            Expr.pseudos[i] = createInputPseudo(i);
        }
        for (i in {
            submit: true,
            reset: true
        }) {
            Expr.pseudos[i] = createButtonPseudo(i);
        }
        function setFilters() {}
        setFilters.prototype = Expr.filters = Expr.pseudos;
        Expr.setFilters = new setFilters();
        tokenize = Sizzle.tokenize = function(selector, parseOnly) {
            var matched, match, tokens, type, soFar, groups, preFilters, cached = tokenCache[selector + " "];
            if (cached) {
                return parseOnly ? 0 : cached.slice(0);
            }
            soFar = selector;
            groups = [];
            preFilters = Expr.preFilter;
            while (soFar) {
                if (!matched || (match = rcomma.exec(soFar))) {
                    if (match) {
                        soFar = soFar.slice(match[0].length) || soFar;
                    }
                    groups.push(tokens = []);
                }
                matched = false;
                if (match = rcombinators.exec(soFar)) {
                    matched = match.shift();
                    tokens.push({
                        value: matched,
                        type: match[0].replace(rtrim, " ")
                    });
                    soFar = soFar.slice(matched.length);
                }
                for (type in Expr.filter) {
                    if ((match = matchExpr[type].exec(soFar)) && (!preFilters[type] || (match = preFilters[type](match)))) {
                        matched = match.shift();
                        tokens.push({
                            value: matched,
                            type: type,
                            matches: match
                        });
                        soFar = soFar.slice(matched.length);
                    }
                }
                if (!matched) {
                    break;
                }
            }
            return parseOnly ? soFar.length : soFar ? Sizzle.error(selector) : tokenCache(selector, groups).slice(0);
        };
        function toSelector(tokens) {
            var i = 0, len = tokens.length, selector = "";
            for (;i < len; i++) {
                selector += tokens[i].value;
            }
            return selector;
        }
        function addCombinator(matcher, combinator, base) {
            var dir = combinator.dir, skip = combinator.next, key = skip || dir, checkNonElements = base && key === "parentNode", doneName = done++;
            return combinator.first ? function(elem, context, xml) {
                while (elem = elem[dir]) {
                    if (elem.nodeType === 1 || checkNonElements) {
                        return matcher(elem, context, xml);
                    }
                }
                return false;
            } : function(elem, context, xml) {
                var oldCache, uniqueCache, outerCache, newCache = [ dirruns, doneName ];
                if (xml) {
                    while (elem = elem[dir]) {
                        if (elem.nodeType === 1 || checkNonElements) {
                            if (matcher(elem, context, xml)) {
                                return true;
                            }
                        }
                    }
                } else {
                    while (elem = elem[dir]) {
                        if (elem.nodeType === 1 || checkNonElements) {
                            outerCache = elem[expando] || (elem[expando] = {});
                            uniqueCache = outerCache[elem.uniqueID] || (outerCache[elem.uniqueID] = {});
                            if (skip && skip === elem.nodeName.toLowerCase()) {
                                elem = elem[dir] || elem;
                            } else if ((oldCache = uniqueCache[key]) && oldCache[0] === dirruns && oldCache[1] === doneName) {
                                return newCache[2] = oldCache[2];
                            } else {
                                uniqueCache[key] = newCache;
                                if (newCache[2] = matcher(elem, context, xml)) {
                                    return true;
                                }
                            }
                        }
                    }
                }
                return false;
            };
        }
        function elementMatcher(matchers) {
            return matchers.length > 1 ? function(elem, context, xml) {
                var i = matchers.length;
                while (i--) {
                    if (!matchers[i](elem, context, xml)) {
                        return false;
                    }
                }
                return true;
            } : matchers[0];
        }
        function multipleContexts(selector, contexts, results) {
            var i = 0, len = contexts.length;
            for (;i < len; i++) {
                Sizzle(selector, contexts[i], results);
            }
            return results;
        }
        function condense(unmatched, map, filter, context, xml) {
            var elem, newUnmatched = [], i = 0, len = unmatched.length, mapped = map != null;
            for (;i < len; i++) {
                if (elem = unmatched[i]) {
                    if (!filter || filter(elem, context, xml)) {
                        newUnmatched.push(elem);
                        if (mapped) {
                            map.push(i);
                        }
                    }
                }
            }
            return newUnmatched;
        }
        function setMatcher(preFilter, selector, matcher, postFilter, postFinder, postSelector) {
            if (postFilter && !postFilter[expando]) {
                postFilter = setMatcher(postFilter);
            }
            if (postFinder && !postFinder[expando]) {
                postFinder = setMatcher(postFinder, postSelector);
            }
            return markFunction(function(seed, results, context, xml) {
                var temp, i, elem, preMap = [], postMap = [], preexisting = results.length, elems = seed || multipleContexts(selector || "*", context.nodeType ? [ context ] : context, []), matcherIn = preFilter && (seed || !selector) ? condense(elems, preMap, preFilter, context, xml) : elems, matcherOut = matcher ? postFinder || (seed ? preFilter : preexisting || postFilter) ? [] : results : matcherIn;
                if (matcher) {
                    matcher(matcherIn, matcherOut, context, xml);
                }
                if (postFilter) {
                    temp = condense(matcherOut, postMap);
                    postFilter(temp, [], context, xml);
                    i = temp.length;
                    while (i--) {
                        if (elem = temp[i]) {
                            matcherOut[postMap[i]] = !(matcherIn[postMap[i]] = elem);
                        }
                    }
                }
                if (seed) {
                    if (postFinder || preFilter) {
                        if (postFinder) {
                            temp = [];
                            i = matcherOut.length;
                            while (i--) {
                                if (elem = matcherOut[i]) {
                                    temp.push(matcherIn[i] = elem);
                                }
                            }
                            postFinder(null, matcherOut = [], temp, xml);
                        }
                        i = matcherOut.length;
                        while (i--) {
                            if ((elem = matcherOut[i]) && (temp = postFinder ? indexOf(seed, elem) : preMap[i]) > -1) {
                                seed[temp] = !(results[temp] = elem);
                            }
                        }
                    }
                } else {
                    matcherOut = condense(matcherOut === results ? matcherOut.splice(preexisting, matcherOut.length) : matcherOut);
                    if (postFinder) {
                        postFinder(null, results, matcherOut, xml);
                    } else {
                        push.apply(results, matcherOut);
                    }
                }
            });
        }
        function matcherFromTokens(tokens) {
            var checkContext, matcher, j, len = tokens.length, leadingRelative = Expr.relative[tokens[0].type], implicitRelative = leadingRelative || Expr.relative[" "], i = leadingRelative ? 1 : 0, matchContext = addCombinator(function(elem) {
                return elem === checkContext;
            }, implicitRelative, true), matchAnyContext = addCombinator(function(elem) {
                return indexOf(checkContext, elem) > -1;
            }, implicitRelative, true), matchers = [ function(elem, context, xml) {
                var ret = !leadingRelative && (xml || context !== outermostContext) || ((checkContext = context).nodeType ? matchContext(elem, context, xml) : matchAnyContext(elem, context, xml));
                checkContext = null;
                return ret;
            } ];
            for (;i < len; i++) {
                if (matcher = Expr.relative[tokens[i].type]) {
                    matchers = [ addCombinator(elementMatcher(matchers), matcher) ];
                } else {
                    matcher = Expr.filter[tokens[i].type].apply(null, tokens[i].matches);
                    if (matcher[expando]) {
                        j = ++i;
                        for (;j < len; j++) {
                            if (Expr.relative[tokens[j].type]) {
                                break;
                            }
                        }
                        return setMatcher(i > 1 && elementMatcher(matchers), i > 1 && toSelector(tokens.slice(0, i - 1).concat({
                            value: tokens[i - 2].type === " " ? "*" : ""
                        })).replace(rtrim, "$1"), matcher, i < j && matcherFromTokens(tokens.slice(i, j)), j < len && matcherFromTokens(tokens = tokens.slice(j)), j < len && toSelector(tokens));
                    }
                    matchers.push(matcher);
                }
            }
            return elementMatcher(matchers);
        }
        function matcherFromGroupMatchers(elementMatchers, setMatchers) {
            var bySet = setMatchers.length > 0, byElement = elementMatchers.length > 0, superMatcher = function(seed, context, xml, results, outermost) {
                var elem, j, matcher, matchedCount = 0, i = "0", unmatched = seed && [], setMatched = [], contextBackup = outermostContext, elems = seed || byElement && Expr.find["TAG"]("*", outermost), dirrunsUnique = dirruns += contextBackup == null ? 1 : Math.random() || .1, len = elems.length;
                if (outermost) {
                    outermostContext = context == document || context || outermost;
                }
                for (;i !== len && (elem = elems[i]) != null; i++) {
                    if (byElement && elem) {
                        j = 0;
                        if (!context && elem.ownerDocument != document) {
                            setDocument(elem);
                            xml = !documentIsHTML;
                        }
                        while (matcher = elementMatchers[j++]) {
                            if (matcher(elem, context || document, xml)) {
                                results.push(elem);
                                break;
                            }
                        }
                        if (outermost) {
                            dirruns = dirrunsUnique;
                        }
                    }
                    if (bySet) {
                        if (elem = !matcher && elem) {
                            matchedCount--;
                        }
                        if (seed) {
                            unmatched.push(elem);
                        }
                    }
                }
                matchedCount += i;
                if (bySet && i !== matchedCount) {
                    j = 0;
                    while (matcher = setMatchers[j++]) {
                        matcher(unmatched, setMatched, context, xml);
                    }
                    if (seed) {
                        if (matchedCount > 0) {
                            while (i--) {
                                if (!(unmatched[i] || setMatched[i])) {
                                    setMatched[i] = pop.call(results);
                                }
                            }
                        }
                        setMatched = condense(setMatched);
                    }
                    push.apply(results, setMatched);
                    if (outermost && !seed && setMatched.length > 0 && matchedCount + setMatchers.length > 1) {
                        Sizzle.uniqueSort(results);
                    }
                }
                if (outermost) {
                    dirruns = dirrunsUnique;
                    outermostContext = contextBackup;
                }
                return unmatched;
            };
            return bySet ? markFunction(superMatcher) : superMatcher;
        }
        compile = Sizzle.compile = function(selector, match) {
            var i, setMatchers = [], elementMatchers = [], cached = compilerCache[selector + " "];
            if (!cached) {
                if (!match) {
                    match = tokenize(selector);
                }
                i = match.length;
                while (i--) {
                    cached = matcherFromTokens(match[i]);
                    if (cached[expando]) {
                        setMatchers.push(cached);
                    } else {
                        elementMatchers.push(cached);
                    }
                }
                cached = compilerCache(selector, matcherFromGroupMatchers(elementMatchers, setMatchers));
                cached.selector = selector;
            }
            return cached;
        };
        select = Sizzle.select = function(selector, context, results, seed) {
            var i, tokens, token, type, find, compiled = typeof selector === "function" && selector, match = !seed && tokenize(selector = compiled.selector || selector);
            results = results || [];
            if (match.length === 1) {
                tokens = match[0] = match[0].slice(0);
                if (tokens.length > 2 && (token = tokens[0]).type === "ID" && context.nodeType === 9 && documentIsHTML && Expr.relative[tokens[1].type]) {
                    context = (Expr.find["ID"](token.matches[0].replace(runescape, funescape), context) || [])[0];
                    if (!context) {
                        return results;
                    } else if (compiled) {
                        context = context.parentNode;
                    }
                    selector = selector.slice(tokens.shift().value.length);
                }
                i = matchExpr["needsContext"].test(selector) ? 0 : tokens.length;
                while (i--) {
                    token = tokens[i];
                    if (Expr.relative[type = token.type]) {
                        break;
                    }
                    if (find = Expr.find[type]) {
                        if (seed = find(token.matches[0].replace(runescape, funescape), rsibling.test(tokens[0].type) && testContext(context.parentNode) || context)) {
                            tokens.splice(i, 1);
                            selector = seed.length && toSelector(tokens);
                            if (!selector) {
                                push.apply(results, seed);
                                return results;
                            }
                            break;
                        }
                    }
                }
            }
            (compiled || compile(selector, match))(seed, context, !documentIsHTML, results, !context || rsibling.test(selector) && testContext(context.parentNode) || context);
            return results;
        };
        support.sortStable = expando.split("").sort(sortOrder).join("") === expando;
        support.detectDuplicates = !!hasDuplicate;
        setDocument();
        support.sortDetached = assert(function(el) {
            return el.compareDocumentPosition(document.createElement("fieldset")) & 1;
        });
        if (!assert(function(el) {
            el.innerHTML = "<a href='#'></a>";
            return el.firstChild.getAttribute("href") === "#";
        })) {
            addHandle("type|href|height|width", function(elem, name, isXML) {
                if (!isXML) {
                    return elem.getAttribute(name, name.toLowerCase() === "type" ? 1 : 2);
                }
            });
        }
        if (!support.attributes || !assert(function(el) {
            el.innerHTML = "<input/>";
            el.firstChild.setAttribute("value", "");
            return el.firstChild.getAttribute("value") === "";
        })) {
            addHandle("value", function(elem, _name, isXML) {
                if (!isXML && elem.nodeName.toLowerCase() === "input") {
                    return elem.defaultValue;
                }
            });
        }
        if (!assert(function(el) {
            return el.getAttribute("disabled") == null;
        })) {
            addHandle(booleans, function(elem, name, isXML) {
                var val;
                if (!isXML) {
                    return elem[name] === true ? name.toLowerCase() : (val = elem.getAttributeNode(name)) && val.specified ? val.value : null;
                }
            });
        }
        return Sizzle;
    }(window);
    jQuery.find = Sizzle;
    jQuery.expr = Sizzle.selectors;
    jQuery.expr[":"] = jQuery.expr.pseudos;
    jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;
    jQuery.text = Sizzle.getText;
    jQuery.isXMLDoc = Sizzle.isXML;
    jQuery.contains = Sizzle.contains;
    jQuery.escapeSelector = Sizzle.escape;
    var dir = function(elem, dir, until) {
        var matched = [], truncate = until !== undefined;
        while ((elem = elem[dir]) && elem.nodeType !== 9) {
            if (elem.nodeType === 1) {
                if (truncate && jQuery(elem).is(until)) {
                    break;
                }
                matched.push(elem);
            }
        }
        return matched;
    };
    var siblings = function(n, elem) {
        var matched = [];
        for (;n; n = n.nextSibling) {
            if (n.nodeType === 1 && n !== elem) {
                matched.push(n);
            }
        }
        return matched;
    };
    var rneedsContext = jQuery.expr.match.needsContext;
    function nodeName(elem, name) {
        return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
    }
    var rsingleTag = /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;
    function winnow(elements, qualifier, not) {
        if (isFunction(qualifier)) {
            return jQuery.grep(elements, function(elem, i) {
                return !!qualifier.call(elem, i, elem) !== not;
            });
        }
        if (qualifier.nodeType) {
            return jQuery.grep(elements, function(elem) {
                return elem === qualifier !== not;
            });
        }
        if (typeof qualifier !== "string") {
            return jQuery.grep(elements, function(elem) {
                return indexOf.call(qualifier, elem) > -1 !== not;
            });
        }
        return jQuery.filter(qualifier, elements, not);
    }
    jQuery.filter = function(expr, elems, not) {
        var elem = elems[0];
        if (not) {
            expr = ":not(" + expr + ")";
        }
        if (elems.length === 1 && elem.nodeType === 1) {
            return jQuery.find.matchesSelector(elem, expr) ? [ elem ] : [];
        }
        return jQuery.find.matches(expr, jQuery.grep(elems, function(elem) {
            return elem.nodeType === 1;
        }));
    };
    jQuery.fn.extend({
        find: function(selector) {
            var i, ret, len = this.length, self = this;
            if (typeof selector !== "string") {
                return this.pushStack(jQuery(selector).filter(function() {
                    for (i = 0; i < len; i++) {
                        if (jQuery.contains(self[i], this)) {
                            return true;
                        }
                    }
                }));
            }
            ret = this.pushStack([]);
            for (i = 0; i < len; i++) {
                jQuery.find(selector, self[i], ret);
            }
            return len > 1 ? jQuery.uniqueSort(ret) : ret;
        },
        filter: function(selector) {
            return this.pushStack(winnow(this, selector || [], false));
        },
        not: function(selector) {
            return this.pushStack(winnow(this, selector || [], true));
        },
        is: function(selector) {
            return !!winnow(this, typeof selector === "string" && rneedsContext.test(selector) ? jQuery(selector) : selector || [], false).length;
        }
    });
    var rootjQuery, rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, init = jQuery.fn.init = function(selector, context, root) {
        var match, elem;
        if (!selector) {
            return this;
        }
        root = root || rootjQuery;
        if (typeof selector === "string") {
            if (selector[0] === "<" && selector[selector.length - 1] === ">" && selector.length >= 3) {
                match = [ null, selector, null ];
            } else {
                match = rquickExpr.exec(selector);
            }
            if (match && (match[1] || !context)) {
                if (match[1]) {
                    context = context instanceof jQuery ? context[0] : context;
                    jQuery.merge(this, jQuery.parseHTML(match[1], context && context.nodeType ? context.ownerDocument || context : document, true));
                    if (rsingleTag.test(match[1]) && jQuery.isPlainObject(context)) {
                        for (match in context) {
                            if (isFunction(this[match])) {
                                this[match](context[match]);
                            } else {
                                this.attr(match, context[match]);
                            }
                        }
                    }
                    return this;
                } else {
                    elem = document.getElementById(match[2]);
                    if (elem) {
                        this[0] = elem;
                        this.length = 1;
                    }
                    return this;
                }
            } else if (!context || context.jquery) {
                return (context || root).find(selector);
            } else {
                return this.constructor(context).find(selector);
            }
        } else if (selector.nodeType) {
            this[0] = selector;
            this.length = 1;
            return this;
        } else if (isFunction(selector)) {
            return root.ready !== undefined ? root.ready(selector) : selector(jQuery);
        }
        return jQuery.makeArray(selector, this);
    };
    init.prototype = jQuery.fn;
    rootjQuery = jQuery(document);
    var rparentsprev = /^(?:parents|prev(?:Until|All))/, guaranteedUnique = {
        children: true,
        contents: true,
        next: true,
        prev: true
    };
    jQuery.fn.extend({
        has: function(target) {
            var targets = jQuery(target, this), l = targets.length;
            return this.filter(function() {
                var i = 0;
                for (;i < l; i++) {
                    if (jQuery.contains(this, targets[i])) {
                        return true;
                    }
                }
            });
        },
        closest: function(selectors, context) {
            var cur, i = 0, l = this.length, matched = [], targets = typeof selectors !== "string" && jQuery(selectors);
            if (!rneedsContext.test(selectors)) {
                for (;i < l; i++) {
                    for (cur = this[i]; cur && cur !== context; cur = cur.parentNode) {
                        if (cur.nodeType < 11 && (targets ? targets.index(cur) > -1 : cur.nodeType === 1 && jQuery.find.matchesSelector(cur, selectors))) {
                            matched.push(cur);
                            break;
                        }
                    }
                }
            }
            return this.pushStack(matched.length > 1 ? jQuery.uniqueSort(matched) : matched);
        },
        index: function(elem) {
            if (!elem) {
                return this[0] && this[0].parentNode ? this.first().prevAll().length : -1;
            }
            if (typeof elem === "string") {
                return indexOf.call(jQuery(elem), this[0]);
            }
            return indexOf.call(this, elem.jquery ? elem[0] : elem);
        },
        add: function(selector, context) {
            return this.pushStack(jQuery.uniqueSort(jQuery.merge(this.get(), jQuery(selector, context))));
        },
        addBack: function(selector) {
            return this.add(selector == null ? this.prevObject : this.prevObject.filter(selector));
        }
    });
    function sibling(cur, dir) {
        while ((cur = cur[dir]) && cur.nodeType !== 1) {}
        return cur;
    }
    jQuery.each({
        parent: function(elem) {
            var parent = elem.parentNode;
            return parent && parent.nodeType !== 11 ? parent : null;
        },
        parents: function(elem) {
            return dir(elem, "parentNode");
        },
        parentsUntil: function(elem, _i, until) {
            return dir(elem, "parentNode", until);
        },
        next: function(elem) {
            return sibling(elem, "nextSibling");
        },
        prev: function(elem) {
            return sibling(elem, "previousSibling");
        },
        nextAll: function(elem) {
            return dir(elem, "nextSibling");
        },
        prevAll: function(elem) {
            return dir(elem, "previousSibling");
        },
        nextUntil: function(elem, _i, until) {
            return dir(elem, "nextSibling", until);
        },
        prevUntil: function(elem, _i, until) {
            return dir(elem, "previousSibling", until);
        },
        siblings: function(elem) {
            return siblings((elem.parentNode || {}).firstChild, elem);
        },
        children: function(elem) {
            return siblings(elem.firstChild);
        },
        contents: function(elem) {
            if (elem.contentDocument != null && getProto(elem.contentDocument)) {
                return elem.contentDocument;
            }
            if (nodeName(elem, "template")) {
                elem = elem.content || elem;
            }
            return jQuery.merge([], elem.childNodes);
        }
    }, function(name, fn) {
        jQuery.fn[name] = function(until, selector) {
            var matched = jQuery.map(this, fn, until);
            if (name.slice(-5) !== "Until") {
                selector = until;
            }
            if (selector && typeof selector === "string") {
                matched = jQuery.filter(selector, matched);
            }
            if (this.length > 1) {
                if (!guaranteedUnique[name]) {
                    jQuery.uniqueSort(matched);
                }
                if (rparentsprev.test(name)) {
                    matched.reverse();
                }
            }
            return this.pushStack(matched);
        };
    });
    var rnothtmlwhite = /[^\x20\t\r\n\f]+/g;
    function createOptions(options) {
        var object = {};
        jQuery.each(options.match(rnothtmlwhite) || [], function(_, flag) {
            object[flag] = true;
        });
        return object;
    }
    jQuery.Callbacks = function(options) {
        options = typeof options === "string" ? createOptions(options) : jQuery.extend({}, options);
        var firing, memory, fired, locked, list = [], queue = [], firingIndex = -1, fire = function() {
            locked = locked || options.once;
            fired = firing = true;
            for (;queue.length; firingIndex = -1) {
                memory = queue.shift();
                while (++firingIndex < list.length) {
                    if (list[firingIndex].apply(memory[0], memory[1]) === false && options.stopOnFalse) {
                        firingIndex = list.length;
                        memory = false;
                    }
                }
            }
            if (!options.memory) {
                memory = false;
            }
            firing = false;
            if (locked) {
                if (memory) {
                    list = [];
                } else {
                    list = "";
                }
            }
        }, self = {
            add: function() {
                if (list) {
                    if (memory && !firing) {
                        firingIndex = list.length - 1;
                        queue.push(memory);
                    }
                    (function add(args) {
                        jQuery.each(args, function(_, arg) {
                            if (isFunction(arg)) {
                                if (!options.unique || !self.has(arg)) {
                                    list.push(arg);
                                }
                            } else if (arg && arg.length && toType(arg) !== "string") {
                                add(arg);
                            }
                        });
                    })(arguments);
                    if (memory && !firing) {
                        fire();
                    }
                }
                return this;
            },
            remove: function() {
                jQuery.each(arguments, function(_, arg) {
                    var index;
                    while ((index = jQuery.inArray(arg, list, index)) > -1) {
                        list.splice(index, 1);
                        if (index <= firingIndex) {
                            firingIndex--;
                        }
                    }
                });
                return this;
            },
            has: function(fn) {
                return fn ? jQuery.inArray(fn, list) > -1 : list.length > 0;
            },
            empty: function() {
                if (list) {
                    list = [];
                }
                return this;
            },
            disable: function() {
                locked = queue = [];
                list = memory = "";
                return this;
            },
            disabled: function() {
                return !list;
            },
            lock: function() {
                locked = queue = [];
                if (!memory && !firing) {
                    list = memory = "";
                }
                return this;
            },
            locked: function() {
                return !!locked;
            },
            fireWith: function(context, args) {
                if (!locked) {
                    args = args || [];
                    args = [ context, args.slice ? args.slice() : args ];
                    queue.push(args);
                    if (!firing) {
                        fire();
                    }
                }
                return this;
            },
            fire: function() {
                self.fireWith(this, arguments);
                return this;
            },
            fired: function() {
                return !!fired;
            }
        };
        return self;
    };
    function Identity(v) {
        return v;
    }
    function Thrower(ex) {
        throw ex;
    }
    function adoptValue(value, resolve, reject, noValue) {
        var method;
        try {
            if (value && isFunction(method = value.promise)) {
                method.call(value).done(resolve).fail(reject);
            } else if (value && isFunction(method = value.then)) {
                method.call(value, resolve, reject);
            } else {
                resolve.apply(undefined, [ value ].slice(noValue));
            }
        } catch (value) {
            reject.apply(undefined, [ value ]);
        }
    }
    jQuery.extend({
        Deferred: function(func) {
            var tuples = [ [ "notify", "progress", jQuery.Callbacks("memory"), jQuery.Callbacks("memory"), 2 ], [ "resolve", "done", jQuery.Callbacks("once memory"), jQuery.Callbacks("once memory"), 0, "resolved" ], [ "reject", "fail", jQuery.Callbacks("once memory"), jQuery.Callbacks("once memory"), 1, "rejected" ] ], state = "pending", promise = {
                state: function() {
                    return state;
                },
                always: function() {
                    deferred.done(arguments).fail(arguments);
                    return this;
                },
                catch: function(fn) {
                    return promise.then(null, fn);
                },
                pipe: function() {
                    var fns = arguments;
                    return jQuery.Deferred(function(newDefer) {
                        jQuery.each(tuples, function(_i, tuple) {
                            var fn = isFunction(fns[tuple[4]]) && fns[tuple[4]];
                            deferred[tuple[1]](function() {
                                var returned = fn && fn.apply(this, arguments);
                                if (returned && isFunction(returned.promise)) {
                                    returned.promise().progress(newDefer.notify).done(newDefer.resolve).fail(newDefer.reject);
                                } else {
                                    newDefer[tuple[0] + "With"](this, fn ? [ returned ] : arguments);
                                }
                            });
                        });
                        fns = null;
                    }).promise();
                },
                then: function(onFulfilled, onRejected, onProgress) {
                    var maxDepth = 0;
                    function resolve(depth, deferred, handler, special) {
                        return function() {
                            var that = this, args = arguments, mightThrow = function() {
                                var returned, then;
                                if (depth < maxDepth) {
                                    return;
                                }
                                returned = handler.apply(that, args);
                                if (returned === deferred.promise()) {
                                    throw new TypeError("Thenable self-resolution");
                                }
                                then = returned && (typeof returned === "object" || typeof returned === "function") && returned.then;
                                if (isFunction(then)) {
                                    if (special) {
                                        then.call(returned, resolve(maxDepth, deferred, Identity, special), resolve(maxDepth, deferred, Thrower, special));
                                    } else {
                                        maxDepth++;
                                        then.call(returned, resolve(maxDepth, deferred, Identity, special), resolve(maxDepth, deferred, Thrower, special), resolve(maxDepth, deferred, Identity, deferred.notifyWith));
                                    }
                                } else {
                                    if (handler !== Identity) {
                                        that = undefined;
                                        args = [ returned ];
                                    }
                                    (special || deferred.resolveWith)(that, args);
                                }
                            }, process = special ? mightThrow : function() {
                                try {
                                    mightThrow();
                                } catch (e) {
                                    if (jQuery.Deferred.exceptionHook) {
                                        jQuery.Deferred.exceptionHook(e, process.stackTrace);
                                    }
                                    if (depth + 1 >= maxDepth) {
                                        if (handler !== Thrower) {
                                            that = undefined;
                                            args = [ e ];
                                        }
                                        deferred.rejectWith(that, args);
                                    }
                                }
                            };
                            if (depth) {
                                process();
                            } else {
                                if (jQuery.Deferred.getStackHook) {
                                    process.stackTrace = jQuery.Deferred.getStackHook();
                                }
                                window.setTimeout(process);
                            }
                        };
                    }
                    return jQuery.Deferred(function(newDefer) {
                        tuples[0][3].add(resolve(0, newDefer, isFunction(onProgress) ? onProgress : Identity, newDefer.notifyWith));
                        tuples[1][3].add(resolve(0, newDefer, isFunction(onFulfilled) ? onFulfilled : Identity));
                        tuples[2][3].add(resolve(0, newDefer, isFunction(onRejected) ? onRejected : Thrower));
                    }).promise();
                },
                promise: function(obj) {
                    return obj != null ? jQuery.extend(obj, promise) : promise;
                }
            }, deferred = {};
            jQuery.each(tuples, function(i, tuple) {
                var list = tuple[2], stateString = tuple[5];
                promise[tuple[1]] = list.add;
                if (stateString) {
                    list.add(function() {
                        state = stateString;
                    }, tuples[3 - i][2].disable, tuples[3 - i][3].disable, tuples[0][2].lock, tuples[0][3].lock);
                }
                list.add(tuple[3].fire);
                deferred[tuple[0]] = function() {
                    deferred[tuple[0] + "With"](this === deferred ? undefined : this, arguments);
                    return this;
                };
                deferred[tuple[0] + "With"] = list.fireWith;
            });
            promise.promise(deferred);
            if (func) {
                func.call(deferred, deferred);
            }
            return deferred;
        },
        when: function(singleValue) {
            var remaining = arguments.length, i = remaining, resolveContexts = Array(i), resolveValues = slice.call(arguments), master = jQuery.Deferred(), updateFunc = function(i) {
                return function(value) {
                    resolveContexts[i] = this;
                    resolveValues[i] = arguments.length > 1 ? slice.call(arguments) : value;
                    if (!--remaining) {
                        master.resolveWith(resolveContexts, resolveValues);
                    }
                };
            };
            if (remaining <= 1) {
                adoptValue(singleValue, master.done(updateFunc(i)).resolve, master.reject, !remaining);
                if (master.state() === "pending" || isFunction(resolveValues[i] && resolveValues[i].then)) {
                    return master.then();
                }
            }
            while (i--) {
                adoptValue(resolveValues[i], updateFunc(i), master.reject);
            }
            return master.promise();
        }
    });
    var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;
    jQuery.Deferred.exceptionHook = function(error, stack) {
        if (window.console && window.console.warn && error && rerrorNames.test(error.name)) {
            window.console.warn("jQuery.Deferred exception: " + error.message, error.stack, stack);
        }
    };
    jQuery.readyException = function(error) {
        window.setTimeout(function() {
            throw error;
        });
    };
    var readyList = jQuery.Deferred();
    jQuery.fn.ready = function(fn) {
        readyList.then(fn).catch(function(error) {
            jQuery.readyException(error);
        });
        return this;
    };
    jQuery.extend({
        isReady: false,
        readyWait: 1,
        ready: function(wait) {
            if (wait === true ? --jQuery.readyWait : jQuery.isReady) {
                return;
            }
            jQuery.isReady = true;
            if (wait !== true && --jQuery.readyWait > 0) {
                return;
            }
            readyList.resolveWith(document, [ jQuery ]);
        }
    });
    jQuery.ready.then = readyList.then;
    function completed() {
        document.removeEventListener("DOMContentLoaded", completed);
        window.removeEventListener("load", completed);
        jQuery.ready();
    }
    if (document.readyState === "complete" || document.readyState !== "loading" && !document.documentElement.doScroll) {
        window.setTimeout(jQuery.ready);
    } else {
        document.addEventListener("DOMContentLoaded", completed);
        window.addEventListener("load", completed);
    }
    var access = function(elems, fn, key, value, chainable, emptyGet, raw) {
        var i = 0, len = elems.length, bulk = key == null;
        if (toType(key) === "object") {
            chainable = true;
            for (i in key) {
                access(elems, fn, i, key[i], true, emptyGet, raw);
            }
        } else if (value !== undefined) {
            chainable = true;
            if (!isFunction(value)) {
                raw = true;
            }
            if (bulk) {
                if (raw) {
                    fn.call(elems, value);
                    fn = null;
                } else {
                    bulk = fn;
                    fn = function(elem, _key, value) {
                        return bulk.call(jQuery(elem), value);
                    };
                }
            }
            if (fn) {
                for (;i < len; i++) {
                    fn(elems[i], key, raw ? value : value.call(elems[i], i, fn(elems[i], key)));
                }
            }
        }
        if (chainable) {
            return elems;
        }
        if (bulk) {
            return fn.call(elems);
        }
        return len ? fn(elems[0], key) : emptyGet;
    };
    var rmsPrefix = /^-ms-/, rdashAlpha = /-([a-z])/g;
    function fcamelCase(_all, letter) {
        return letter.toUpperCase();
    }
    function camelCase(string) {
        return string.replace(rmsPrefix, "ms-").replace(rdashAlpha, fcamelCase);
    }
    var acceptData = function(owner) {
        return owner.nodeType === 1 || owner.nodeType === 9 || !+owner.nodeType;
    };
    function Data() {
        this.expando = jQuery.expando + Data.uid++;
    }
    Data.uid = 1;
    Data.prototype = {
        cache: function(owner) {
            var value = owner[this.expando];
            if (!value) {
                value = {};
                if (acceptData(owner)) {
                    if (owner.nodeType) {
                        owner[this.expando] = value;
                    } else {
                        Object.defineProperty(owner, this.expando, {
                            value: value,
                            configurable: true
                        });
                    }
                }
            }
            return value;
        },
        set: function(owner, data, value) {
            var prop, cache = this.cache(owner);
            if (typeof data === "string") {
                cache[camelCase(data)] = value;
            } else {
                for (prop in data) {
                    cache[camelCase(prop)] = data[prop];
                }
            }
            return cache;
        },
        get: function(owner, key) {
            return key === undefined ? this.cache(owner) : owner[this.expando] && owner[this.expando][camelCase(key)];
        },
        access: function(owner, key, value) {
            if (key === undefined || key && typeof key === "string" && value === undefined) {
                return this.get(owner, key);
            }
            this.set(owner, key, value);
            return value !== undefined ? value : key;
        },
        remove: function(owner, key) {
            var i, cache = owner[this.expando];
            if (cache === undefined) {
                return;
            }
            if (key !== undefined) {
                if (Array.isArray(key)) {
                    key = key.map(camelCase);
                } else {
                    key = camelCase(key);
                    key = key in cache ? [ key ] : key.match(rnothtmlwhite) || [];
                }
                i = key.length;
                while (i--) {
                    delete cache[key[i]];
                }
            }
            if (key === undefined || jQuery.isEmptyObject(cache)) {
                if (owner.nodeType) {
                    owner[this.expando] = undefined;
                } else {
                    delete owner[this.expando];
                }
            }
        },
        hasData: function(owner) {
            var cache = owner[this.expando];
            return cache !== undefined && !jQuery.isEmptyObject(cache);
        }
    };
    var dataPriv = new Data();
    var dataUser = new Data();
    var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/, rmultiDash = /[A-Z]/g;
    function getData(data) {
        if (data === "true") {
            return true;
        }
        if (data === "false") {
            return false;
        }
        if (data === "null") {
            return null;
        }
        if (data === +data + "") {
            return +data;
        }
        if (rbrace.test(data)) {
            return JSON.parse(data);
        }
        return data;
    }
    function dataAttr(elem, key, data) {
        var name;
        if (data === undefined && elem.nodeType === 1) {
            name = "data-" + key.replace(rmultiDash, "-$&").toLowerCase();
            data = elem.getAttribute(name);
            if (typeof data === "string") {
                try {
                    data = getData(data);
                } catch (e) {}
                dataUser.set(elem, key, data);
            } else {
                data = undefined;
            }
        }
        return data;
    }
    jQuery.extend({
        hasData: function(elem) {
            return dataUser.hasData(elem) || dataPriv.hasData(elem);
        },
        data: function(elem, name, data) {
            return dataUser.access(elem, name, data);
        },
        removeData: function(elem, name) {
            dataUser.remove(elem, name);
        },
        _data: function(elem, name, data) {
            return dataPriv.access(elem, name, data);
        },
        _removeData: function(elem, name) {
            dataPriv.remove(elem, name);
        }
    });
    jQuery.fn.extend({
        data: function(key, value) {
            var i, name, data, elem = this[0], attrs = elem && elem.attributes;
            if (key === undefined) {
                if (this.length) {
                    data = dataUser.get(elem);
                    if (elem.nodeType === 1 && !dataPriv.get(elem, "hasDataAttrs")) {
                        i = attrs.length;
                        while (i--) {
                            if (attrs[i]) {
                                name = attrs[i].name;
                                if (name.indexOf("data-") === 0) {
                                    name = camelCase(name.slice(5));
                                    dataAttr(elem, name, data[name]);
                                }
                            }
                        }
                        dataPriv.set(elem, "hasDataAttrs", true);
                    }
                }
                return data;
            }
            if (typeof key === "object") {
                return this.each(function() {
                    dataUser.set(this, key);
                });
            }
            return access(this, function(value) {
                var data;
                if (elem && value === undefined) {
                    data = dataUser.get(elem, key);
                    if (data !== undefined) {
                        return data;
                    }
                    data = dataAttr(elem, key);
                    if (data !== undefined) {
                        return data;
                    }
                    return;
                }
                this.each(function() {
                    dataUser.set(this, key, value);
                });
            }, null, value, arguments.length > 1, null, true);
        },
        removeData: function(key) {
            return this.each(function() {
                dataUser.remove(this, key);
            });
        }
    });
    jQuery.extend({
        queue: function(elem, type, data) {
            var queue;
            if (elem) {
                type = (type || "fx") + "queue";
                queue = dataPriv.get(elem, type);
                if (data) {
                    if (!queue || Array.isArray(data)) {
                        queue = dataPriv.access(elem, type, jQuery.makeArray(data));
                    } else {
                        queue.push(data);
                    }
                }
                return queue || [];
            }
        },
        dequeue: function(elem, type) {
            type = type || "fx";
            var queue = jQuery.queue(elem, type), startLength = queue.length, fn = queue.shift(), hooks = jQuery._queueHooks(elem, type), next = function() {
                jQuery.dequeue(elem, type);
            };
            if (fn === "inprogress") {
                fn = queue.shift();
                startLength--;
            }
            if (fn) {
                if (type === "fx") {
                    queue.unshift("inprogress");
                }
                delete hooks.stop;
                fn.call(elem, next, hooks);
            }
            if (!startLength && hooks) {
                hooks.empty.fire();
            }
        },
        _queueHooks: function(elem, type) {
            var key = type + "queueHooks";
            return dataPriv.get(elem, key) || dataPriv.access(elem, key, {
                empty: jQuery.Callbacks("once memory").add(function() {
                    dataPriv.remove(elem, [ type + "queue", key ]);
                })
            });
        }
    });
    jQuery.fn.extend({
        queue: function(type, data) {
            var setter = 2;
            if (typeof type !== "string") {
                data = type;
                type = "fx";
                setter--;
            }
            if (arguments.length < setter) {
                return jQuery.queue(this[0], type);
            }
            return data === undefined ? this : this.each(function() {
                var queue = jQuery.queue(this, type, data);
                jQuery._queueHooks(this, type);
                if (type === "fx" && queue[0] !== "inprogress") {
                    jQuery.dequeue(this, type);
                }
            });
        },
        dequeue: function(type) {
            return this.each(function() {
                jQuery.dequeue(this, type);
            });
        },
        clearQueue: function(type) {
            return this.queue(type || "fx", []);
        },
        promise: function(type, obj) {
            var tmp, count = 1, defer = jQuery.Deferred(), elements = this, i = this.length, resolve = function() {
                if (!--count) {
                    defer.resolveWith(elements, [ elements ]);
                }
            };
            if (typeof type !== "string") {
                obj = type;
                type = undefined;
            }
            type = type || "fx";
            while (i--) {
                tmp = dataPriv.get(elements[i], type + "queueHooks");
                if (tmp && tmp.empty) {
                    count++;
                    tmp.empty.add(resolve);
                }
            }
            resolve();
            return defer.promise(obj);
        }
    });
    var pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source;
    var rcssNum = new RegExp("^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i");
    var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
    var documentElement = document.documentElement;
    var isAttached = function(elem) {
        return jQuery.contains(elem.ownerDocument, elem);
    }, composed = {
        composed: true
    };
    if (documentElement.getRootNode) {
        isAttached = function(elem) {
            return jQuery.contains(elem.ownerDocument, elem) || elem.getRootNode(composed) === elem.ownerDocument;
        };
    }
    var isHiddenWithinTree = function(elem, el) {
        elem = el || elem;
        return elem.style.display === "none" || elem.style.display === "" && isAttached(elem) && jQuery.css(elem, "display") === "none";
    };
    function adjustCSS(elem, prop, valueParts, tween) {
        var adjusted, scale, maxIterations = 20, currentValue = tween ? function() {
            return tween.cur();
        } : function() {
            return jQuery.css(elem, prop, "");
        }, initial = currentValue(), unit = valueParts && valueParts[3] || (jQuery.cssNumber[prop] ? "" : "px"), initialInUnit = elem.nodeType && (jQuery.cssNumber[prop] || unit !== "px" && +initial) && rcssNum.exec(jQuery.css(elem, prop));
        if (initialInUnit && initialInUnit[3] !== unit) {
            initial = initial / 2;
            unit = unit || initialInUnit[3];
            initialInUnit = +initial || 1;
            while (maxIterations--) {
                jQuery.style(elem, prop, initialInUnit + unit);
                if ((1 - scale) * (1 - (scale = currentValue() / initial || .5)) <= 0) {
                    maxIterations = 0;
                }
                initialInUnit = initialInUnit / scale;
            }
            initialInUnit = initialInUnit * 2;
            jQuery.style(elem, prop, initialInUnit + unit);
            valueParts = valueParts || [];
        }
        if (valueParts) {
            initialInUnit = +initialInUnit || +initial || 0;
            adjusted = valueParts[1] ? initialInUnit + (valueParts[1] + 1) * valueParts[2] : +valueParts[2];
            if (tween) {
                tween.unit = unit;
                tween.start = initialInUnit;
                tween.end = adjusted;
            }
        }
        return adjusted;
    }
    var defaultDisplayMap = {};
    function getDefaultDisplay(elem) {
        var temp, doc = elem.ownerDocument, nodeName = elem.nodeName, display = defaultDisplayMap[nodeName];
        if (display) {
            return display;
        }
        temp = doc.body.appendChild(doc.createElement(nodeName));
        display = jQuery.css(temp, "display");
        temp.parentNode.removeChild(temp);
        if (display === "none") {
            display = "block";
        }
        defaultDisplayMap[nodeName] = display;
        return display;
    }
    function showHide(elements, show) {
        var display, elem, values = [], index = 0, length = elements.length;
        for (;index < length; index++) {
            elem = elements[index];
            if (!elem.style) {
                continue;
            }
            display = elem.style.display;
            if (show) {
                if (display === "none") {
                    values[index] = dataPriv.get(elem, "display") || null;
                    if (!values[index]) {
                        elem.style.display = "";
                    }
                }
                if (elem.style.display === "" && isHiddenWithinTree(elem)) {
                    values[index] = getDefaultDisplay(elem);
                }
            } else {
                if (display !== "none") {
                    values[index] = "none";
                    dataPriv.set(elem, "display", display);
                }
            }
        }
        for (index = 0; index < length; index++) {
            if (values[index] != null) {
                elements[index].style.display = values[index];
            }
        }
        return elements;
    }
    jQuery.fn.extend({
        show: function() {
            return showHide(this, true);
        },
        hide: function() {
            return showHide(this);
        },
        toggle: function(state) {
            if (typeof state === "boolean") {
                return state ? this.show() : this.hide();
            }
            return this.each(function() {
                if (isHiddenWithinTree(this)) {
                    jQuery(this).show();
                } else {
                    jQuery(this).hide();
                }
            });
        }
    });
    var rcheckableType = /^(?:checkbox|radio)$/i;
    var rtagName = /<([a-z][^\/\0>\x20\t\r\n\f]*)/i;
    var rscriptType = /^$|^module$|\/(?:java|ecma)script/i;
    (function() {
        var fragment = document.createDocumentFragment(), div = fragment.appendChild(document.createElement("div")), input = document.createElement("input");
        input.setAttribute("type", "radio");
        input.setAttribute("checked", "checked");
        input.setAttribute("name", "t");
        div.appendChild(input);
        support.checkClone = div.cloneNode(true).cloneNode(true).lastChild.checked;
        div.innerHTML = "<textarea>x</textarea>";
        support.noCloneChecked = !!div.cloneNode(true).lastChild.defaultValue;
        div.innerHTML = "<option></option>";
        support.option = !!div.lastChild;
    })();
    var wrapMap = {
        thead: [ 1, "<table>", "</table>" ],
        col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
        tr: [ 2, "<table><tbody>", "</tbody></table>" ],
        td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
        _default: [ 0, "", "" ]
    };
    wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
    wrapMap.th = wrapMap.td;
    if (!support.option) {
        wrapMap.optgroup = wrapMap.option = [ 1, "<select multiple='multiple'>", "</select>" ];
    }
    function getAll(context, tag) {
        var ret;
        if (typeof context.getElementsByTagName !== "undefined") {
            ret = context.getElementsByTagName(tag || "*");
        } else if (typeof context.querySelectorAll !== "undefined") {
            ret = context.querySelectorAll(tag || "*");
        } else {
            ret = [];
        }
        if (tag === undefined || tag && nodeName(context, tag)) {
            return jQuery.merge([ context ], ret);
        }
        return ret;
    }
    function setGlobalEval(elems, refElements) {
        var i = 0, l = elems.length;
        for (;i < l; i++) {
            dataPriv.set(elems[i], "globalEval", !refElements || dataPriv.get(refElements[i], "globalEval"));
        }
    }
    var rhtml = /<|&#?\w+;/;
    function buildFragment(elems, context, scripts, selection, ignored) {
        var elem, tmp, tag, wrap, attached, j, fragment = context.createDocumentFragment(), nodes = [], i = 0, l = elems.length;
        for (;i < l; i++) {
            elem = elems[i];
            if (elem || elem === 0) {
                if (toType(elem) === "object") {
                    jQuery.merge(nodes, elem.nodeType ? [ elem ] : elem);
                } else if (!rhtml.test(elem)) {
                    nodes.push(context.createTextNode(elem));
                } else {
                    tmp = tmp || fragment.appendChild(context.createElement("div"));
                    tag = (rtagName.exec(elem) || [ "", "" ])[1].toLowerCase();
                    wrap = wrapMap[tag] || wrapMap._default;
                    tmp.innerHTML = wrap[1] + jQuery.htmlPrefilter(elem) + wrap[2];
                    j = wrap[0];
                    while (j--) {
                        tmp = tmp.lastChild;
                    }
                    jQuery.merge(nodes, tmp.childNodes);
                    tmp = fragment.firstChild;
                    tmp.textContent = "";
                }
            }
        }
        fragment.textContent = "";
        i = 0;
        while (elem = nodes[i++]) {
            if (selection && jQuery.inArray(elem, selection) > -1) {
                if (ignored) {
                    ignored.push(elem);
                }
                continue;
            }
            attached = isAttached(elem);
            tmp = getAll(fragment.appendChild(elem), "script");
            if (attached) {
                setGlobalEval(tmp);
            }
            if (scripts) {
                j = 0;
                while (elem = tmp[j++]) {
                    if (rscriptType.test(elem.type || "")) {
                        scripts.push(elem);
                    }
                }
            }
        }
        return fragment;
    }
    var rkeyEvent = /^key/, rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/, rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
    function returnTrue() {
        return true;
    }
    function returnFalse() {
        return false;
    }
    function expectSync(elem, type) {
        return elem === safeActiveElement() === (type === "focus");
    }
    function safeActiveElement() {
        try {
            return document.activeElement;
        } catch (err) {}
    }
    function on(elem, types, selector, data, fn, one) {
        var origFn, type;
        if (typeof types === "object") {
            if (typeof selector !== "string") {
                data = data || selector;
                selector = undefined;
            }
            for (type in types) {
                on(elem, type, selector, data, types[type], one);
            }
            return elem;
        }
        if (data == null && fn == null) {
            fn = selector;
            data = selector = undefined;
        } else if (fn == null) {
            if (typeof selector === "string") {
                fn = data;
                data = undefined;
            } else {
                fn = data;
                data = selector;
                selector = undefined;
            }
        }
        if (fn === false) {
            fn = returnFalse;
        } else if (!fn) {
            return elem;
        }
        if (one === 1) {
            origFn = fn;
            fn = function(event) {
                jQuery().off(event);
                return origFn.apply(this, arguments);
            };
            fn.guid = origFn.guid || (origFn.guid = jQuery.guid++);
        }
        return elem.each(function() {
            jQuery.event.add(this, types, fn, data, selector);
        });
    }
    jQuery.event = {
        global: {},
        add: function(elem, types, handler, data, selector) {
            var handleObjIn, eventHandle, tmp, events, t, handleObj, special, handlers, type, namespaces, origType, elemData = dataPriv.get(elem);
            if (!acceptData(elem)) {
                return;
            }
            if (handler.handler) {
                handleObjIn = handler;
                handler = handleObjIn.handler;
                selector = handleObjIn.selector;
            }
            if (selector) {
                jQuery.find.matchesSelector(documentElement, selector);
            }
            if (!handler.guid) {
                handler.guid = jQuery.guid++;
            }
            if (!(events = elemData.events)) {
                events = elemData.events = Object.create(null);
            }
            if (!(eventHandle = elemData.handle)) {
                eventHandle = elemData.handle = function(e) {
                    return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? jQuery.event.dispatch.apply(elem, arguments) : undefined;
                };
            }
            types = (types || "").match(rnothtmlwhite) || [ "" ];
            t = types.length;
            while (t--) {
                tmp = rtypenamespace.exec(types[t]) || [];
                type = origType = tmp[1];
                namespaces = (tmp[2] || "").split(".").sort();
                if (!type) {
                    continue;
                }
                special = jQuery.event.special[type] || {};
                type = (selector ? special.delegateType : special.bindType) || type;
                special = jQuery.event.special[type] || {};
                handleObj = jQuery.extend({
                    type: type,
                    origType: origType,
                    data: data,
                    handler: handler,
                    guid: handler.guid,
                    selector: selector,
                    needsContext: selector && jQuery.expr.match.needsContext.test(selector),
                    namespace: namespaces.join(".")
                }, handleObjIn);
                if (!(handlers = events[type])) {
                    handlers = events[type] = [];
                    handlers.delegateCount = 0;
                    if (!special.setup || special.setup.call(elem, data, namespaces, eventHandle) === false) {
                        if (elem.addEventListener) {
                            elem.addEventListener(type, eventHandle);
                        }
                    }
                }
                if (special.add) {
                    special.add.call(elem, handleObj);
                    if (!handleObj.handler.guid) {
                        handleObj.handler.guid = handler.guid;
                    }
                }
                if (selector) {
                    handlers.splice(handlers.delegateCount++, 0, handleObj);
                } else {
                    handlers.push(handleObj);
                }
                jQuery.event.global[type] = true;
            }
        },
        remove: function(elem, types, handler, selector, mappedTypes) {
            var j, origCount, tmp, events, t, handleObj, special, handlers, type, namespaces, origType, elemData = dataPriv.hasData(elem) && dataPriv.get(elem);
            if (!elemData || !(events = elemData.events)) {
                return;
            }
            types = (types || "").match(rnothtmlwhite) || [ "" ];
            t = types.length;
            while (t--) {
                tmp = rtypenamespace.exec(types[t]) || [];
                type = origType = tmp[1];
                namespaces = (tmp[2] || "").split(".").sort();
                if (!type) {
                    for (type in events) {
                        jQuery.event.remove(elem, type + types[t], handler, selector, true);
                    }
                    continue;
                }
                special = jQuery.event.special[type] || {};
                type = (selector ? special.delegateType : special.bindType) || type;
                handlers = events[type] || [];
                tmp = tmp[2] && new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)");
                origCount = j = handlers.length;
                while (j--) {
                    handleObj = handlers[j];
                    if ((mappedTypes || origType === handleObj.origType) && (!handler || handler.guid === handleObj.guid) && (!tmp || tmp.test(handleObj.namespace)) && (!selector || selector === handleObj.selector || selector === "**" && handleObj.selector)) {
                        handlers.splice(j, 1);
                        if (handleObj.selector) {
                            handlers.delegateCount--;
                        }
                        if (special.remove) {
                            special.remove.call(elem, handleObj);
                        }
                    }
                }
                if (origCount && !handlers.length) {
                    if (!special.teardown || special.teardown.call(elem, namespaces, elemData.handle) === false) {
                        jQuery.removeEvent(elem, type, elemData.handle);
                    }
                    delete events[type];
                }
            }
            if (jQuery.isEmptyObject(events)) {
                dataPriv.remove(elem, "handle events");
            }
        },
        dispatch: function(nativeEvent) {
            var i, j, ret, matched, handleObj, handlerQueue, args = new Array(arguments.length), event = jQuery.event.fix(nativeEvent), handlers = (dataPriv.get(this, "events") || Object.create(null))[event.type] || [], special = jQuery.event.special[event.type] || {};
            args[0] = event;
            for (i = 1; i < arguments.length; i++) {
                args[i] = arguments[i];
            }
            event.delegateTarget = this;
            if (special.preDispatch && special.preDispatch.call(this, event) === false) {
                return;
            }
            handlerQueue = jQuery.event.handlers.call(this, event, handlers);
            i = 0;
            while ((matched = handlerQueue[i++]) && !event.isPropagationStopped()) {
                event.currentTarget = matched.elem;
                j = 0;
                while ((handleObj = matched.handlers[j++]) && !event.isImmediatePropagationStopped()) {
                    if (!event.rnamespace || handleObj.namespace === false || event.rnamespace.test(handleObj.namespace)) {
                        event.handleObj = handleObj;
                        event.data = handleObj.data;
                        ret = ((jQuery.event.special[handleObj.origType] || {}).handle || handleObj.handler).apply(matched.elem, args);
                        if (ret !== undefined) {
                            if ((event.result = ret) === false) {
                                event.preventDefault();
                                event.stopPropagation();
                            }
                        }
                    }
                }
            }
            if (special.postDispatch) {
                special.postDispatch.call(this, event);
            }
            return event.result;
        },
        handlers: function(event, handlers) {
            var i, handleObj, sel, matchedHandlers, matchedSelectors, handlerQueue = [], delegateCount = handlers.delegateCount, cur = event.target;
            if (delegateCount && cur.nodeType && !(event.type === "click" && event.button >= 1)) {
                for (;cur !== this; cur = cur.parentNode || this) {
                    if (cur.nodeType === 1 && !(event.type === "click" && cur.disabled === true)) {
                        matchedHandlers = [];
                        matchedSelectors = {};
                        for (i = 0; i < delegateCount; i++) {
                            handleObj = handlers[i];
                            sel = handleObj.selector + " ";
                            if (matchedSelectors[sel] === undefined) {
                                matchedSelectors[sel] = handleObj.needsContext ? jQuery(sel, this).index(cur) > -1 : jQuery.find(sel, this, null, [ cur ]).length;
                            }
                            if (matchedSelectors[sel]) {
                                matchedHandlers.push(handleObj);
                            }
                        }
                        if (matchedHandlers.length) {
                            handlerQueue.push({
                                elem: cur,
                                handlers: matchedHandlers
                            });
                        }
                    }
                }
            }
            cur = this;
            if (delegateCount < handlers.length) {
                handlerQueue.push({
                    elem: cur,
                    handlers: handlers.slice(delegateCount)
                });
            }
            return handlerQueue;
        },
        addProp: function(name, hook) {
            Object.defineProperty(jQuery.Event.prototype, name, {
                enumerable: true,
                configurable: true,
                get: isFunction(hook) ? function() {
                    if (this.originalEvent) {
                        return hook(this.originalEvent);
                    }
                } : function() {
                    if (this.originalEvent) {
                        return this.originalEvent[name];
                    }
                },
                set: function(value) {
                    Object.defineProperty(this, name, {
                        enumerable: true,
                        configurable: true,
                        writable: true,
                        value: value
                    });
                }
            });
        },
        fix: function(originalEvent) {
            return originalEvent[jQuery.expando] ? originalEvent : new jQuery.Event(originalEvent);
        },
        special: {
            load: {
                noBubble: true
            },
            click: {
                setup: function(data) {
                    var el = this || data;
                    if (rcheckableType.test(el.type) && el.click && nodeName(el, "input")) {
                        leverageNative(el, "click", returnTrue);
                    }
                    return false;
                },
                trigger: function(data) {
                    var el = this || data;
                    if (rcheckableType.test(el.type) && el.click && nodeName(el, "input")) {
                        leverageNative(el, "click");
                    }
                    return true;
                },
                _default: function(event) {
                    var target = event.target;
                    return rcheckableType.test(target.type) && target.click && nodeName(target, "input") && dataPriv.get(target, "click") || nodeName(target, "a");
                }
            },
            beforeunload: {
                postDispatch: function(event) {
                    if (event.result !== undefined && event.originalEvent) {
                        event.originalEvent.returnValue = event.result;
                    }
                }
            }
        }
    };
    function leverageNative(el, type, expectSync) {
        if (!expectSync) {
            if (dataPriv.get(el, type) === undefined) {
                jQuery.event.add(el, type, returnTrue);
            }
            return;
        }
        dataPriv.set(el, type, false);
        jQuery.event.add(el, type, {
            namespace: false,
            handler: function(event) {
                var notAsync, result, saved = dataPriv.get(this, type);
                if (event.isTrigger & 1 && this[type]) {
                    if (!saved.length) {
                        saved = slice.call(arguments);
                        dataPriv.set(this, type, saved);
                        notAsync = expectSync(this, type);
                        this[type]();
                        result = dataPriv.get(this, type);
                        if (saved !== result || notAsync) {
                            dataPriv.set(this, type, false);
                        } else {
                            result = {};
                        }
                        if (saved !== result) {
                            event.stopImmediatePropagation();
                            event.preventDefault();
                            return result.value;
                        }
                    } else if ((jQuery.event.special[type] || {}).delegateType) {
                        event.stopPropagation();
                    }
                } else if (saved.length) {
                    dataPriv.set(this, type, {
                        value: jQuery.event.trigger(jQuery.extend(saved[0], jQuery.Event.prototype), saved.slice(1), this)
                    });
                    event.stopImmediatePropagation();
                }
            }
        });
    }
    jQuery.removeEvent = function(elem, type, handle) {
        if (elem.removeEventListener) {
            elem.removeEventListener(type, handle);
        }
    };
    jQuery.Event = function(src, props) {
        if (!(this instanceof jQuery.Event)) {
            return new jQuery.Event(src, props);
        }
        if (src && src.type) {
            this.originalEvent = src;
            this.type = src.type;
            this.isDefaultPrevented = src.defaultPrevented || src.defaultPrevented === undefined && src.returnValue === false ? returnTrue : returnFalse;
            this.target = src.target && src.target.nodeType === 3 ? src.target.parentNode : src.target;
            this.currentTarget = src.currentTarget;
            this.relatedTarget = src.relatedTarget;
        } else {
            this.type = src;
        }
        if (props) {
            jQuery.extend(this, props);
        }
        this.timeStamp = src && src.timeStamp || Date.now();
        this[jQuery.expando] = true;
    };
    jQuery.Event.prototype = {
        constructor: jQuery.Event,
        isDefaultPrevented: returnFalse,
        isPropagationStopped: returnFalse,
        isImmediatePropagationStopped: returnFalse,
        isSimulated: false,
        preventDefault: function() {
            var e = this.originalEvent;
            this.isDefaultPrevented = returnTrue;
            if (e && !this.isSimulated) {
                e.preventDefault();
            }
        },
        stopPropagation: function() {
            var e = this.originalEvent;
            this.isPropagationStopped = returnTrue;
            if (e && !this.isSimulated) {
                e.stopPropagation();
            }
        },
        stopImmediatePropagation: function() {
            var e = this.originalEvent;
            this.isImmediatePropagationStopped = returnTrue;
            if (e && !this.isSimulated) {
                e.stopImmediatePropagation();
            }
            this.stopPropagation();
        }
    };
    jQuery.each({
        altKey: true,
        bubbles: true,
        cancelable: true,
        changedTouches: true,
        ctrlKey: true,
        detail: true,
        eventPhase: true,
        metaKey: true,
        pageX: true,
        pageY: true,
        shiftKey: true,
        view: true,
        char: true,
        code: true,
        charCode: true,
        key: true,
        keyCode: true,
        button: true,
        buttons: true,
        clientX: true,
        clientY: true,
        offsetX: true,
        offsetY: true,
        pointerId: true,
        pointerType: true,
        screenX: true,
        screenY: true,
        targetTouches: true,
        toElement: true,
        touches: true,
        which: function(event) {
            var button = event.button;
            if (event.which == null && rkeyEvent.test(event.type)) {
                return event.charCode != null ? event.charCode : event.keyCode;
            }
            if (!event.which && button !== undefined && rmouseEvent.test(event.type)) {
                if (button & 1) {
                    return 1;
                }
                if (button & 2) {
                    return 3;
                }
                if (button & 4) {
                    return 2;
                }
                return 0;
            }
            return event.which;
        }
    }, jQuery.event.addProp);
    jQuery.each({
        focus: "focusin",
        blur: "focusout"
    }, function(type, delegateType) {
        jQuery.event.special[type] = {
            setup: function() {
                leverageNative(this, type, expectSync);
                return false;
            },
            trigger: function() {
                leverageNative(this, type);
                return true;
            },
            delegateType: delegateType
        };
    });
    jQuery.each({
        mouseenter: "mouseover",
        mouseleave: "mouseout",
        pointerenter: "pointerover",
        pointerleave: "pointerout"
    }, function(orig, fix) {
        jQuery.event.special[orig] = {
            delegateType: fix,
            bindType: fix,
            handle: function(event) {
                var ret, target = this, related = event.relatedTarget, handleObj = event.handleObj;
                if (!related || related !== target && !jQuery.contains(target, related)) {
                    event.type = handleObj.origType;
                    ret = handleObj.handler.apply(this, arguments);
                    event.type = fix;
                }
                return ret;
            }
        };
    });
    jQuery.fn.extend({
        on: function(types, selector, data, fn) {
            return on(this, types, selector, data, fn);
        },
        one: function(types, selector, data, fn) {
            return on(this, types, selector, data, fn, 1);
        },
        off: function(types, selector, fn) {
            var handleObj, type;
            if (types && types.preventDefault && types.handleObj) {
                handleObj = types.handleObj;
                jQuery(types.delegateTarget).off(handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, handleObj.selector, handleObj.handler);
                return this;
            }
            if (typeof types === "object") {
                for (type in types) {
                    this.off(type, selector, types[type]);
                }
                return this;
            }
            if (selector === false || typeof selector === "function") {
                fn = selector;
                selector = undefined;
            }
            if (fn === false) {
                fn = returnFalse;
            }
            return this.each(function() {
                jQuery.event.remove(this, types, fn, selector);
            });
        }
    });
    var rnoInnerhtml = /<script|<style|<link/i, rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;
    function manipulationTarget(elem, content) {
        if (nodeName(elem, "table") && nodeName(content.nodeType !== 11 ? content : content.firstChild, "tr")) {
            return jQuery(elem).children("tbody")[0] || elem;
        }
        return elem;
    }
    function disableScript(elem) {
        elem.type = (elem.getAttribute("type") !== null) + "/" + elem.type;
        return elem;
    }
    function restoreScript(elem) {
        if ((elem.type || "").slice(0, 5) === "true/") {
            elem.type = elem.type.slice(5);
        } else {
            elem.removeAttribute("type");
        }
        return elem;
    }
    function cloneCopyEvent(src, dest) {
        var i, l, type, pdataOld, udataOld, udataCur, events;
        if (dest.nodeType !== 1) {
            return;
        }
        if (dataPriv.hasData(src)) {
            pdataOld = dataPriv.get(src);
            events = pdataOld.events;
            if (events) {
                dataPriv.remove(dest, "handle events");
                for (type in events) {
                    for (i = 0, l = events[type].length; i < l; i++) {
                        jQuery.event.add(dest, type, events[type][i]);
                    }
                }
            }
        }
        if (dataUser.hasData(src)) {
            udataOld = dataUser.access(src);
            udataCur = jQuery.extend({}, udataOld);
            dataUser.set(dest, udataCur);
        }
    }
    function fixInput(src, dest) {
        var nodeName = dest.nodeName.toLowerCase();
        if (nodeName === "input" && rcheckableType.test(src.type)) {
            dest.checked = src.checked;
        } else if (nodeName === "input" || nodeName === "textarea") {
            dest.defaultValue = src.defaultValue;
        }
    }
    function domManip(collection, args, callback, ignored) {
        args = flat(args);
        var fragment, first, scripts, hasScripts, node, doc, i = 0, l = collection.length, iNoClone = l - 1, value = args[0], valueIsFunction = isFunction(value);
        if (valueIsFunction || l > 1 && typeof value === "string" && !support.checkClone && rchecked.test(value)) {
            return collection.each(function(index) {
                var self = collection.eq(index);
                if (valueIsFunction) {
                    args[0] = value.call(this, index, self.html());
                }
                domManip(self, args, callback, ignored);
            });
        }
        if (l) {
            fragment = buildFragment(args, collection[0].ownerDocument, false, collection, ignored);
            first = fragment.firstChild;
            if (fragment.childNodes.length === 1) {
                fragment = first;
            }
            if (first || ignored) {
                scripts = jQuery.map(getAll(fragment, "script"), disableScript);
                hasScripts = scripts.length;
                for (;i < l; i++) {
                    node = fragment;
                    if (i !== iNoClone) {
                        node = jQuery.clone(node, true, true);
                        if (hasScripts) {
                            jQuery.merge(scripts, getAll(node, "script"));
                        }
                    }
                    callback.call(collection[i], node, i);
                }
                if (hasScripts) {
                    doc = scripts[scripts.length - 1].ownerDocument;
                    jQuery.map(scripts, restoreScript);
                    for (i = 0; i < hasScripts; i++) {
                        node = scripts[i];
                        if (rscriptType.test(node.type || "") && !dataPriv.access(node, "globalEval") && jQuery.contains(doc, node)) {
                            if (node.src && (node.type || "").toLowerCase() !== "module") {
                                if (jQuery._evalUrl && !node.noModule) {
                                    jQuery._evalUrl(node.src, {
                                        nonce: node.nonce || node.getAttribute("nonce")
                                    }, doc);
                                }
                            } else {
                                DOMEval(node.textContent.replace(rcleanScript, ""), node, doc);
                            }
                        }
                    }
                }
            }
        }
        return collection;
    }
    function remove(elem, selector, keepData) {
        var node, nodes = selector ? jQuery.filter(selector, elem) : elem, i = 0;
        for (;(node = nodes[i]) != null; i++) {
            if (!keepData && node.nodeType === 1) {
                jQuery.cleanData(getAll(node));
            }
            if (node.parentNode) {
                if (keepData && isAttached(node)) {
                    setGlobalEval(getAll(node, "script"));
                }
                node.parentNode.removeChild(node);
            }
        }
        return elem;
    }
    jQuery.extend({
        htmlPrefilter: function(html) {
            return html;
        },
        clone: function(elem, dataAndEvents, deepDataAndEvents) {
            var i, l, srcElements, destElements, clone = elem.cloneNode(true), inPage = isAttached(elem);
            if (!support.noCloneChecked && (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem)) {
                destElements = getAll(clone);
                srcElements = getAll(elem);
                for (i = 0, l = srcElements.length; i < l; i++) {
                    fixInput(srcElements[i], destElements[i]);
                }
            }
            if (dataAndEvents) {
                if (deepDataAndEvents) {
                    srcElements = srcElements || getAll(elem);
                    destElements = destElements || getAll(clone);
                    for (i = 0, l = srcElements.length; i < l; i++) {
                        cloneCopyEvent(srcElements[i], destElements[i]);
                    }
                } else {
                    cloneCopyEvent(elem, clone);
                }
            }
            destElements = getAll(clone, "script");
            if (destElements.length > 0) {
                setGlobalEval(destElements, !inPage && getAll(elem, "script"));
            }
            return clone;
        },
        cleanData: function(elems) {
            var data, elem, type, special = jQuery.event.special, i = 0;
            for (;(elem = elems[i]) !== undefined; i++) {
                if (acceptData(elem)) {
                    if (data = elem[dataPriv.expando]) {
                        if (data.events) {
                            for (type in data.events) {
                                if (special[type]) {
                                    jQuery.event.remove(elem, type);
                                } else {
                                    jQuery.removeEvent(elem, type, data.handle);
                                }
                            }
                        }
                        elem[dataPriv.expando] = undefined;
                    }
                    if (elem[dataUser.expando]) {
                        elem[dataUser.expando] = undefined;
                    }
                }
            }
        }
    });
    jQuery.fn.extend({
        detach: function(selector) {
            return remove(this, selector, true);
        },
        remove: function(selector) {
            return remove(this, selector);
        },
        text: function(value) {
            return access(this, function(value) {
                return value === undefined ? jQuery.text(this) : this.empty().each(function() {
                    if (this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9) {
                        this.textContent = value;
                    }
                });
            }, null, value, arguments.length);
        },
        append: function() {
            return domManip(this, arguments, function(elem) {
                if (this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9) {
                    var target = manipulationTarget(this, elem);
                    target.appendChild(elem);
                }
            });
        },
        prepend: function() {
            return domManip(this, arguments, function(elem) {
                if (this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9) {
                    var target = manipulationTarget(this, elem);
                    target.insertBefore(elem, target.firstChild);
                }
            });
        },
        before: function() {
            return domManip(this, arguments, function(elem) {
                if (this.parentNode) {
                    this.parentNode.insertBefore(elem, this);
                }
            });
        },
        after: function() {
            return domManip(this, arguments, function(elem) {
                if (this.parentNode) {
                    this.parentNode.insertBefore(elem, this.nextSibling);
                }
            });
        },
        empty: function() {
            var elem, i = 0;
            for (;(elem = this[i]) != null; i++) {
                if (elem.nodeType === 1) {
                    jQuery.cleanData(getAll(elem, false));
                    elem.textContent = "";
                }
            }
            return this;
        },
        clone: function(dataAndEvents, deepDataAndEvents) {
            dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
            deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
            return this.map(function() {
                return jQuery.clone(this, dataAndEvents, deepDataAndEvents);
            });
        },
        html: function(value) {
            return access(this, function(value) {
                var elem = this[0] || {}, i = 0, l = this.length;
                if (value === undefined && elem.nodeType === 1) {
                    return elem.innerHTML;
                }
                if (typeof value === "string" && !rnoInnerhtml.test(value) && !wrapMap[(rtagName.exec(value) || [ "", "" ])[1].toLowerCase()]) {
                    value = jQuery.htmlPrefilter(value);
                    try {
                        for (;i < l; i++) {
                            elem = this[i] || {};
                            if (elem.nodeType === 1) {
                                jQuery.cleanData(getAll(elem, false));
                                elem.innerHTML = value;
                            }
                        }
                        elem = 0;
                    } catch (e) {}
                }
                if (elem) {
                    this.empty().append(value);
                }
            }, null, value, arguments.length);
        },
        replaceWith: function() {
            var ignored = [];
            return domManip(this, arguments, function(elem) {
                var parent = this.parentNode;
                if (jQuery.inArray(this, ignored) < 0) {
                    jQuery.cleanData(getAll(this));
                    if (parent) {
                        parent.replaceChild(elem, this);
                    }
                }
            }, ignored);
        }
    });
    jQuery.each({
        appendTo: "append",
        prependTo: "prepend",
        insertBefore: "before",
        insertAfter: "after",
        replaceAll: "replaceWith"
    }, function(name, original) {
        jQuery.fn[name] = function(selector) {
            var elems, ret = [], insert = jQuery(selector), last = insert.length - 1, i = 0;
            for (;i <= last; i++) {
                elems = i === last ? this : this.clone(true);
                jQuery(insert[i])[original](elems);
                push.apply(ret, elems.get());
            }
            return this.pushStack(ret);
        };
    });
    var rnumnonpx = new RegExp("^(" + pnum + ")(?!px)[a-z%]+$", "i");
    var getStyles = function(elem) {
        var view = elem.ownerDocument.defaultView;
        if (!view || !view.opener) {
            view = window;
        }
        return view.getComputedStyle(elem);
    };
    var swap = function(elem, options, callback) {
        var ret, name, old = {};
        for (name in options) {
            old[name] = elem.style[name];
            elem.style[name] = options[name];
        }
        ret = callback.call(elem);
        for (name in options) {
            elem.style[name] = old[name];
        }
        return ret;
    };
    var rboxStyle = new RegExp(cssExpand.join("|"), "i");
    (function() {
        function computeStyleTests() {
            if (!div) {
                return;
            }
            container.style.cssText = "position:absolute;left:-11111px;width:60px;" + "margin-top:1px;padding:0;border:0";
            div.style.cssText = "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + "margin:auto;border:1px;padding:1px;" + "width:60%;top:1%";
            documentElement.appendChild(container).appendChild(div);
            var divStyle = window.getComputedStyle(div);
            pixelPositionVal = divStyle.top !== "1%";
            reliableMarginLeftVal = roundPixelMeasures(divStyle.marginLeft) === 12;
            div.style.right = "60%";
            pixelBoxStylesVal = roundPixelMeasures(divStyle.right) === 36;
            boxSizingReliableVal = roundPixelMeasures(divStyle.width) === 36;
            div.style.position = "absolute";
            scrollboxSizeVal = roundPixelMeasures(div.offsetWidth / 3) === 12;
            documentElement.removeChild(container);
            div = null;
        }
        function roundPixelMeasures(measure) {
            return Math.round(parseFloat(measure));
        }
        var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, reliableTrDimensionsVal, reliableMarginLeftVal, container = document.createElement("div"), div = document.createElement("div");
        if (!div.style) {
            return;
        }
        div.style.backgroundClip = "content-box";
        div.cloneNode(true).style.backgroundClip = "";
        support.clearCloneStyle = div.style.backgroundClip === "content-box";
        jQuery.extend(support, {
            boxSizingReliable: function() {
                computeStyleTests();
                return boxSizingReliableVal;
            },
            pixelBoxStyles: function() {
                computeStyleTests();
                return pixelBoxStylesVal;
            },
            pixelPosition: function() {
                computeStyleTests();
                return pixelPositionVal;
            },
            reliableMarginLeft: function() {
                computeStyleTests();
                return reliableMarginLeftVal;
            },
            scrollboxSize: function() {
                computeStyleTests();
                return scrollboxSizeVal;
            },
            reliableTrDimensions: function() {
                var table, tr, trChild, trStyle;
                if (reliableTrDimensionsVal == null) {
                    table = document.createElement("table");
                    tr = document.createElement("tr");
                    trChild = document.createElement("div");
                    table.style.cssText = "position:absolute;left:-11111px";
                    tr.style.height = "1px";
                    trChild.style.height = "9px";
                    documentElement.appendChild(table).appendChild(tr).appendChild(trChild);
                    trStyle = window.getComputedStyle(tr);
                    reliableTrDimensionsVal = parseInt(trStyle.height) > 3;
                    documentElement.removeChild(table);
                }
                return reliableTrDimensionsVal;
            }
        });
    })();
    function curCSS(elem, name, computed) {
        var width, minWidth, maxWidth, ret, style = elem.style;
        computed = computed || getStyles(elem);
        if (computed) {
            ret = computed.getPropertyValue(name) || computed[name];
            if (ret === "" && !isAttached(elem)) {
                ret = jQuery.style(elem, name);
            }
            if (!support.pixelBoxStyles() && rnumnonpx.test(ret) && rboxStyle.test(name)) {
                width = style.width;
                minWidth = style.minWidth;
                maxWidth = style.maxWidth;
                style.minWidth = style.maxWidth = style.width = ret;
                ret = computed.width;
                style.width = width;
                style.minWidth = minWidth;
                style.maxWidth = maxWidth;
            }
        }
        return ret !== undefined ? ret + "" : ret;
    }
    function addGetHookIf(conditionFn, hookFn) {
        return {
            get: function() {
                if (conditionFn()) {
                    delete this.get;
                    return;
                }
                return (this.get = hookFn).apply(this, arguments);
            }
        };
    }
    var cssPrefixes = [ "Webkit", "Moz", "ms" ], emptyStyle = document.createElement("div").style, vendorProps = {};
    function vendorPropName(name) {
        var capName = name[0].toUpperCase() + name.slice(1), i = cssPrefixes.length;
        while (i--) {
            name = cssPrefixes[i] + capName;
            if (name in emptyStyle) {
                return name;
            }
        }
    }
    function finalPropName(name) {
        var final = jQuery.cssProps[name] || vendorProps[name];
        if (final) {
            return final;
        }
        if (name in emptyStyle) {
            return name;
        }
        return vendorProps[name] = vendorPropName(name) || name;
    }
    var rdisplayswap = /^(none|table(?!-c[ea]).+)/, rcustomProp = /^--/, cssShow = {
        position: "absolute",
        visibility: "hidden",
        display: "block"
    }, cssNormalTransform = {
        letterSpacing: "0",
        fontWeight: "400"
    };
    function setPositiveNumber(_elem, value, subtract) {
        var matches = rcssNum.exec(value);
        return matches ? Math.max(0, matches[2] - (subtract || 0)) + (matches[3] || "px") : value;
    }
    function boxModelAdjustment(elem, dimension, box, isBorderBox, styles, computedVal) {
        var i = dimension === "width" ? 1 : 0, extra = 0, delta = 0;
        if (box === (isBorderBox ? "border" : "content")) {
            return 0;
        }
        for (;i < 4; i += 2) {
            if (box === "margin") {
                delta += jQuery.css(elem, box + cssExpand[i], true, styles);
            }
            if (!isBorderBox) {
                delta += jQuery.css(elem, "padding" + cssExpand[i], true, styles);
                if (box !== "padding") {
                    delta += jQuery.css(elem, "border" + cssExpand[i] + "Width", true, styles);
                } else {
                    extra += jQuery.css(elem, "border" + cssExpand[i] + "Width", true, styles);
                }
            } else {
                if (box === "content") {
                    delta -= jQuery.css(elem, "padding" + cssExpand[i], true, styles);
                }
                if (box !== "margin") {
                    delta -= jQuery.css(elem, "border" + cssExpand[i] + "Width", true, styles);
                }
            }
        }
        if (!isBorderBox && computedVal >= 0) {
            delta += Math.max(0, Math.ceil(elem["offset" + dimension[0].toUpperCase() + dimension.slice(1)] - computedVal - delta - extra - .5)) || 0;
        }
        return delta;
    }
    function getWidthOrHeight(elem, dimension, extra) {
        var styles = getStyles(elem), boxSizingNeeded = !support.boxSizingReliable() || extra, isBorderBox = boxSizingNeeded && jQuery.css(elem, "boxSizing", false, styles) === "border-box", valueIsBorderBox = isBorderBox, val = curCSS(elem, dimension, styles), offsetProp = "offset" + dimension[0].toUpperCase() + dimension.slice(1);
        if (rnumnonpx.test(val)) {
            if (!extra) {
                return val;
            }
            val = "auto";
        }
        if ((!support.boxSizingReliable() && isBorderBox || !support.reliableTrDimensions() && nodeName(elem, "tr") || val === "auto" || !parseFloat(val) && jQuery.css(elem, "display", false, styles) === "inline") && elem.getClientRects().length) {
            isBorderBox = jQuery.css(elem, "boxSizing", false, styles) === "border-box";
            valueIsBorderBox = offsetProp in elem;
            if (valueIsBorderBox) {
                val = elem[offsetProp];
            }
        }
        val = parseFloat(val) || 0;
        return val + boxModelAdjustment(elem, dimension, extra || (isBorderBox ? "border" : "content"), valueIsBorderBox, styles, val) + "px";
    }
    jQuery.extend({
        cssHooks: {
            opacity: {
                get: function(elem, computed) {
                    if (computed) {
                        var ret = curCSS(elem, "opacity");
                        return ret === "" ? "1" : ret;
                    }
                }
            }
        },
        cssNumber: {
            animationIterationCount: true,
            columnCount: true,
            fillOpacity: true,
            flexGrow: true,
            flexShrink: true,
            fontWeight: true,
            gridArea: true,
            gridColumn: true,
            gridColumnEnd: true,
            gridColumnStart: true,
            gridRow: true,
            gridRowEnd: true,
            gridRowStart: true,
            lineHeight: true,
            opacity: true,
            order: true,
            orphans: true,
            widows: true,
            zIndex: true,
            zoom: true
        },
        cssProps: {},
        style: function(elem, name, value, extra) {
            if (!elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style) {
                return;
            }
            var ret, type, hooks, origName = camelCase(name), isCustomProp = rcustomProp.test(name), style = elem.style;
            if (!isCustomProp) {
                name = finalPropName(origName);
            }
            hooks = jQuery.cssHooks[name] || jQuery.cssHooks[origName];
            if (value !== undefined) {
                type = typeof value;
                if (type === "string" && (ret = rcssNum.exec(value)) && ret[1]) {
                    value = adjustCSS(elem, name, ret);
                    type = "number";
                }
                if (value == null || value !== value) {
                    return;
                }
                if (type === "number" && !isCustomProp) {
                    value += ret && ret[3] || (jQuery.cssNumber[origName] ? "" : "px");
                }
                if (!support.clearCloneStyle && value === "" && name.indexOf("background") === 0) {
                    style[name] = "inherit";
                }
                if (!hooks || !("set" in hooks) || (value = hooks.set(elem, value, extra)) !== undefined) {
                    if (isCustomProp) {
                        style.setProperty(name, value);
                    } else {
                        style[name] = value;
                    }
                }
            } else {
                if (hooks && "get" in hooks && (ret = hooks.get(elem, false, extra)) !== undefined) {
                    return ret;
                }
                return style[name];
            }
        },
        css: function(elem, name, extra, styles) {
            var val, num, hooks, origName = camelCase(name), isCustomProp = rcustomProp.test(name);
            if (!isCustomProp) {
                name = finalPropName(origName);
            }
            hooks = jQuery.cssHooks[name] || jQuery.cssHooks[origName];
            if (hooks && "get" in hooks) {
                val = hooks.get(elem, true, extra);
            }
            if (val === undefined) {
                val = curCSS(elem, name, styles);
            }
            if (val === "normal" && name in cssNormalTransform) {
                val = cssNormalTransform[name];
            }
            if (extra === "" || extra) {
                num = parseFloat(val);
                return extra === true || isFinite(num) ? num || 0 : val;
            }
            return val;
        }
    });
    jQuery.each([ "height", "width" ], function(_i, dimension) {
        jQuery.cssHooks[dimension] = {
            get: function(elem, computed, extra) {
                if (computed) {
                    return rdisplayswap.test(jQuery.css(elem, "display")) && (!elem.getClientRects().length || !elem.getBoundingClientRect().width) ? swap(elem, cssShow, function() {
                        return getWidthOrHeight(elem, dimension, extra);
                    }) : getWidthOrHeight(elem, dimension, extra);
                }
            },
            set: function(elem, value, extra) {
                var matches, styles = getStyles(elem), scrollboxSizeBuggy = !support.scrollboxSize() && styles.position === "absolute", boxSizingNeeded = scrollboxSizeBuggy || extra, isBorderBox = boxSizingNeeded && jQuery.css(elem, "boxSizing", false, styles) === "border-box", subtract = extra ? boxModelAdjustment(elem, dimension, extra, isBorderBox, styles) : 0;
                if (isBorderBox && scrollboxSizeBuggy) {
                    subtract -= Math.ceil(elem["offset" + dimension[0].toUpperCase() + dimension.slice(1)] - parseFloat(styles[dimension]) - boxModelAdjustment(elem, dimension, "border", false, styles) - .5);
                }
                if (subtract && (matches = rcssNum.exec(value)) && (matches[3] || "px") !== "px") {
                    elem.style[dimension] = value;
                    value = jQuery.css(elem, dimension);
                }
                return setPositiveNumber(elem, value, subtract);
            }
        };
    });
    jQuery.cssHooks.marginLeft = addGetHookIf(support.reliableMarginLeft, function(elem, computed) {
        if (computed) {
            return (parseFloat(curCSS(elem, "marginLeft")) || elem.getBoundingClientRect().left - swap(elem, {
                marginLeft: 0
            }, function() {
                return elem.getBoundingClientRect().left;
            })) + "px";
        }
    });
    jQuery.each({
        margin: "",
        padding: "",
        border: "Width"
    }, function(prefix, suffix) {
        jQuery.cssHooks[prefix + suffix] = {
            expand: function(value) {
                var i = 0, expanded = {}, parts = typeof value === "string" ? value.split(" ") : [ value ];
                for (;i < 4; i++) {
                    expanded[prefix + cssExpand[i] + suffix] = parts[i] || parts[i - 2] || parts[0];
                }
                return expanded;
            }
        };
        if (prefix !== "margin") {
            jQuery.cssHooks[prefix + suffix].set = setPositiveNumber;
        }
    });
    jQuery.fn.extend({
        css: function(name, value) {
            return access(this, function(elem, name, value) {
                var styles, len, map = {}, i = 0;
                if (Array.isArray(name)) {
                    styles = getStyles(elem);
                    len = name.length;
                    for (;i < len; i++) {
                        map[name[i]] = jQuery.css(elem, name[i], false, styles);
                    }
                    return map;
                }
                return value !== undefined ? jQuery.style(elem, name, value) : jQuery.css(elem, name);
            }, name, value, arguments.length > 1);
        }
    });
    function Tween(elem, options, prop, end, easing) {
        return new Tween.prototype.init(elem, options, prop, end, easing);
    }
    jQuery.Tween = Tween;
    Tween.prototype = {
        constructor: Tween,
        init: function(elem, options, prop, end, easing, unit) {
            this.elem = elem;
            this.prop = prop;
            this.easing = easing || jQuery.easing._default;
            this.options = options;
            this.start = this.now = this.cur();
            this.end = end;
            this.unit = unit || (jQuery.cssNumber[prop] ? "" : "px");
        },
        cur: function() {
            var hooks = Tween.propHooks[this.prop];
            return hooks && hooks.get ? hooks.get(this) : Tween.propHooks._default.get(this);
        },
        run: function(percent) {
            var eased, hooks = Tween.propHooks[this.prop];
            if (this.options.duration) {
                this.pos = eased = jQuery.easing[this.easing](percent, this.options.duration * percent, 0, 1, this.options.duration);
            } else {
                this.pos = eased = percent;
            }
            this.now = (this.end - this.start) * eased + this.start;
            if (this.options.step) {
                this.options.step.call(this.elem, this.now, this);
            }
            if (hooks && hooks.set) {
                hooks.set(this);
            } else {
                Tween.propHooks._default.set(this);
            }
            return this;
        }
    };
    Tween.prototype.init.prototype = Tween.prototype;
    Tween.propHooks = {
        _default: {
            get: function(tween) {
                var result;
                if (tween.elem.nodeType !== 1 || tween.elem[tween.prop] != null && tween.elem.style[tween.prop] == null) {
                    return tween.elem[tween.prop];
                }
                result = jQuery.css(tween.elem, tween.prop, "");
                return !result || result === "auto" ? 0 : result;
            },
            set: function(tween) {
                if (jQuery.fx.step[tween.prop]) {
                    jQuery.fx.step[tween.prop](tween);
                } else if (tween.elem.nodeType === 1 && (jQuery.cssHooks[tween.prop] || tween.elem.style[finalPropName(tween.prop)] != null)) {
                    jQuery.style(tween.elem, tween.prop, tween.now + tween.unit);
                } else {
                    tween.elem[tween.prop] = tween.now;
                }
            }
        }
    };
    Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
        set: function(tween) {
            if (tween.elem.nodeType && tween.elem.parentNode) {
                tween.elem[tween.prop] = tween.now;
            }
        }
    };
    jQuery.easing = {
        linear: function(p) {
            return p;
        },
        swing: function(p) {
            return .5 - Math.cos(p * Math.PI) / 2;
        },
        _default: "swing"
    };
    jQuery.fx = Tween.prototype.init;
    jQuery.fx.step = {};
    var fxNow, inProgress, rfxtypes = /^(?:toggle|show|hide)$/, rrun = /queueHooks$/;
    function schedule() {
        if (inProgress) {
            if (document.hidden === false && window.requestAnimationFrame) {
                window.requestAnimationFrame(schedule);
            } else {
                window.setTimeout(schedule, jQuery.fx.interval);
            }
            jQuery.fx.tick();
        }
    }
    function createFxNow() {
        window.setTimeout(function() {
            fxNow = undefined;
        });
        return fxNow = Date.now();
    }
    function genFx(type, includeWidth) {
        var which, i = 0, attrs = {
            height: type
        };
        includeWidth = includeWidth ? 1 : 0;
        for (;i < 4; i += 2 - includeWidth) {
            which = cssExpand[i];
            attrs["margin" + which] = attrs["padding" + which] = type;
        }
        if (includeWidth) {
            attrs.opacity = attrs.width = type;
        }
        return attrs;
    }
    function createTween(value, prop, animation) {
        var tween, collection = (Animation.tweeners[prop] || []).concat(Animation.tweeners["*"]), index = 0, length = collection.length;
        for (;index < length; index++) {
            if (tween = collection[index].call(animation, prop, value)) {
                return tween;
            }
        }
    }
    function defaultPrefilter(elem, props, opts) {
        var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display, isBox = "width" in props || "height" in props, anim = this, orig = {}, style = elem.style, hidden = elem.nodeType && isHiddenWithinTree(elem), dataShow = dataPriv.get(elem, "fxshow");
        if (!opts.queue) {
            hooks = jQuery._queueHooks(elem, "fx");
            if (hooks.unqueued == null) {
                hooks.unqueued = 0;
                oldfire = hooks.empty.fire;
                hooks.empty.fire = function() {
                    if (!hooks.unqueued) {
                        oldfire();
                    }
                };
            }
            hooks.unqueued++;
            anim.always(function() {
                anim.always(function() {
                    hooks.unqueued--;
                    if (!jQuery.queue(elem, "fx").length) {
                        hooks.empty.fire();
                    }
                });
            });
        }
        for (prop in props) {
            value = props[prop];
            if (rfxtypes.test(value)) {
                delete props[prop];
                toggle = toggle || value === "toggle";
                if (value === (hidden ? "hide" : "show")) {
                    if (value === "show" && dataShow && dataShow[prop] !== undefined) {
                        hidden = true;
                    } else {
                        continue;
                    }
                }
                orig[prop] = dataShow && dataShow[prop] || jQuery.style(elem, prop);
            }
        }
        propTween = !jQuery.isEmptyObject(props);
        if (!propTween && jQuery.isEmptyObject(orig)) {
            return;
        }
        if (isBox && elem.nodeType === 1) {
            opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
            restoreDisplay = dataShow && dataShow.display;
            if (restoreDisplay == null) {
                restoreDisplay = dataPriv.get(elem, "display");
            }
            display = jQuery.css(elem, "display");
            if (display === "none") {
                if (restoreDisplay) {
                    display = restoreDisplay;
                } else {
                    showHide([ elem ], true);
                    restoreDisplay = elem.style.display || restoreDisplay;
                    display = jQuery.css(elem, "display");
                    showHide([ elem ]);
                }
            }
            if (display === "inline" || display === "inline-block" && restoreDisplay != null) {
                if (jQuery.css(elem, "float") === "none") {
                    if (!propTween) {
                        anim.done(function() {
                            style.display = restoreDisplay;
                        });
                        if (restoreDisplay == null) {
                            display = style.display;
                            restoreDisplay = display === "none" ? "" : display;
                        }
                    }
                    style.display = "inline-block";
                }
            }
        }
        if (opts.overflow) {
            style.overflow = "hidden";
            anim.always(function() {
                style.overflow = opts.overflow[0];
                style.overflowX = opts.overflow[1];
                style.overflowY = opts.overflow[2];
            });
        }
        propTween = false;
        for (prop in orig) {
            if (!propTween) {
                if (dataShow) {
                    if ("hidden" in dataShow) {
                        hidden = dataShow.hidden;
                    }
                } else {
                    dataShow = dataPriv.access(elem, "fxshow", {
                        display: restoreDisplay
                    });
                }
                if (toggle) {
                    dataShow.hidden = !hidden;
                }
                if (hidden) {
                    showHide([ elem ], true);
                }
                anim.done(function() {
                    if (!hidden) {
                        showHide([ elem ]);
                    }
                    dataPriv.remove(elem, "fxshow");
                    for (prop in orig) {
                        jQuery.style(elem, prop, orig[prop]);
                    }
                });
            }
            propTween = createTween(hidden ? dataShow[prop] : 0, prop, anim);
            if (!(prop in dataShow)) {
                dataShow[prop] = propTween.start;
                if (hidden) {
                    propTween.end = propTween.start;
                    propTween.start = 0;
                }
            }
        }
    }
    function propFilter(props, specialEasing) {
        var index, name, easing, value, hooks;
        for (index in props) {
            name = camelCase(index);
            easing = specialEasing[name];
            value = props[index];
            if (Array.isArray(value)) {
                easing = value[1];
                value = props[index] = value[0];
            }
            if (index !== name) {
                props[name] = value;
                delete props[index];
            }
            hooks = jQuery.cssHooks[name];
            if (hooks && "expand" in hooks) {
                value = hooks.expand(value);
                delete props[name];
                for (index in value) {
                    if (!(index in props)) {
                        props[index] = value[index];
                        specialEasing[index] = easing;
                    }
                }
            } else {
                specialEasing[name] = easing;
            }
        }
    }
    function Animation(elem, properties, options) {
        var result, stopped, index = 0, length = Animation.prefilters.length, deferred = jQuery.Deferred().always(function() {
            delete tick.elem;
        }), tick = function() {
            if (stopped) {
                return false;
            }
            var currentTime = fxNow || createFxNow(), remaining = Math.max(0, animation.startTime + animation.duration - currentTime), temp = remaining / animation.duration || 0, percent = 1 - temp, index = 0, length = animation.tweens.length;
            for (;index < length; index++) {
                animation.tweens[index].run(percent);
            }
            deferred.notifyWith(elem, [ animation, percent, remaining ]);
            if (percent < 1 && length) {
                return remaining;
            }
            if (!length) {
                deferred.notifyWith(elem, [ animation, 1, 0 ]);
            }
            deferred.resolveWith(elem, [ animation ]);
            return false;
        }, animation = deferred.promise({
            elem: elem,
            props: jQuery.extend({}, properties),
            opts: jQuery.extend(true, {
                specialEasing: {},
                easing: jQuery.easing._default
            }, options),
            originalProperties: properties,
            originalOptions: options,
            startTime: fxNow || createFxNow(),
            duration: options.duration,
            tweens: [],
            createTween: function(prop, end) {
                var tween = jQuery.Tween(elem, animation.opts, prop, end, animation.opts.specialEasing[prop] || animation.opts.easing);
                animation.tweens.push(tween);
                return tween;
            },
            stop: function(gotoEnd) {
                var index = 0, length = gotoEnd ? animation.tweens.length : 0;
                if (stopped) {
                    return this;
                }
                stopped = true;
                for (;index < length; index++) {
                    animation.tweens[index].run(1);
                }
                if (gotoEnd) {
                    deferred.notifyWith(elem, [ animation, 1, 0 ]);
                    deferred.resolveWith(elem, [ animation, gotoEnd ]);
                } else {
                    deferred.rejectWith(elem, [ animation, gotoEnd ]);
                }
                return this;
            }
        }), props = animation.props;
        propFilter(props, animation.opts.specialEasing);
        for (;index < length; index++) {
            result = Animation.prefilters[index].call(animation, elem, props, animation.opts);
            if (result) {
                if (isFunction(result.stop)) {
                    jQuery._queueHooks(animation.elem, animation.opts.queue).stop = result.stop.bind(result);
                }
                return result;
            }
        }
        jQuery.map(props, createTween, animation);
        if (isFunction(animation.opts.start)) {
            animation.opts.start.call(elem, animation);
        }
        animation.progress(animation.opts.progress).done(animation.opts.done, animation.opts.complete).fail(animation.opts.fail).always(animation.opts.always);
        jQuery.fx.timer(jQuery.extend(tick, {
            elem: elem,
            anim: animation,
            queue: animation.opts.queue
        }));
        return animation;
    }
    jQuery.Animation = jQuery.extend(Animation, {
        tweeners: {
            "*": [ function(prop, value) {
                var tween = this.createTween(prop, value);
                adjustCSS(tween.elem, prop, rcssNum.exec(value), tween);
                return tween;
            } ]
        },
        tweener: function(props, callback) {
            if (isFunction(props)) {
                callback = props;
                props = [ "*" ];
            } else {
                props = props.match(rnothtmlwhite);
            }
            var prop, index = 0, length = props.length;
            for (;index < length; index++) {
                prop = props[index];
                Animation.tweeners[prop] = Animation.tweeners[prop] || [];
                Animation.tweeners[prop].unshift(callback);
            }
        },
        prefilters: [ defaultPrefilter ],
        prefilter: function(callback, prepend) {
            if (prepend) {
                Animation.prefilters.unshift(callback);
            } else {
                Animation.prefilters.push(callback);
            }
        }
    });
    jQuery.speed = function(speed, easing, fn) {
        var opt = speed && typeof speed === "object" ? jQuery.extend({}, speed) : {
            complete: fn || !fn && easing || isFunction(speed) && speed,
            duration: speed,
            easing: fn && easing || easing && !isFunction(easing) && easing
        };
        if (jQuery.fx.off) {
            opt.duration = 0;
        } else {
            if (typeof opt.duration !== "number") {
                if (opt.duration in jQuery.fx.speeds) {
                    opt.duration = jQuery.fx.speeds[opt.duration];
                } else {
                    opt.duration = jQuery.fx.speeds._default;
                }
            }
        }
        if (opt.queue == null || opt.queue === true) {
            opt.queue = "fx";
        }
        opt.old = opt.complete;
        opt.complete = function() {
            if (isFunction(opt.old)) {
                opt.old.call(this);
            }
            if (opt.queue) {
                jQuery.dequeue(this, opt.queue);
            }
        };
        return opt;
    };
    jQuery.fn.extend({
        fadeTo: function(speed, to, easing, callback) {
            return this.filter(isHiddenWithinTree).css("opacity", 0).show().end().animate({
                opacity: to
            }, speed, easing, callback);
        },
        animate: function(prop, speed, easing, callback) {
            var empty = jQuery.isEmptyObject(prop), optall = jQuery.speed(speed, easing, callback), doAnimation = function() {
                var anim = Animation(this, jQuery.extend({}, prop), optall);
                if (empty || dataPriv.get(this, "finish")) {
                    anim.stop(true);
                }
            };
            doAnimation.finish = doAnimation;
            return empty || optall.queue === false ? this.each(doAnimation) : this.queue(optall.queue, doAnimation);
        },
        stop: function(type, clearQueue, gotoEnd) {
            var stopQueue = function(hooks) {
                var stop = hooks.stop;
                delete hooks.stop;
                stop(gotoEnd);
            };
            if (typeof type !== "string") {
                gotoEnd = clearQueue;
                clearQueue = type;
                type = undefined;
            }
            if (clearQueue) {
                this.queue(type || "fx", []);
            }
            return this.each(function() {
                var dequeue = true, index = type != null && type + "queueHooks", timers = jQuery.timers, data = dataPriv.get(this);
                if (index) {
                    if (data[index] && data[index].stop) {
                        stopQueue(data[index]);
                    }
                } else {
                    for (index in data) {
                        if (data[index] && data[index].stop && rrun.test(index)) {
                            stopQueue(data[index]);
                        }
                    }
                }
                for (index = timers.length; index--; ) {
                    if (timers[index].elem === this && (type == null || timers[index].queue === type)) {
                        timers[index].anim.stop(gotoEnd);
                        dequeue = false;
                        timers.splice(index, 1);
                    }
                }
                if (dequeue || !gotoEnd) {
                    jQuery.dequeue(this, type);
                }
            });
        },
        finish: function(type) {
            if (type !== false) {
                type = type || "fx";
            }
            return this.each(function() {
                var index, data = dataPriv.get(this), queue = data[type + "queue"], hooks = data[type + "queueHooks"], timers = jQuery.timers, length = queue ? queue.length : 0;
                data.finish = true;
                jQuery.queue(this, type, []);
                if (hooks && hooks.stop) {
                    hooks.stop.call(this, true);
                }
                for (index = timers.length; index--; ) {
                    if (timers[index].elem === this && timers[index].queue === type) {
                        timers[index].anim.stop(true);
                        timers.splice(index, 1);
                    }
                }
                for (index = 0; index < length; index++) {
                    if (queue[index] && queue[index].finish) {
                        queue[index].finish.call(this);
                    }
                }
                delete data.finish;
            });
        }
    });
    jQuery.each([ "toggle", "show", "hide" ], function(_i, name) {
        var cssFn = jQuery.fn[name];
        jQuery.fn[name] = function(speed, easing, callback) {
            return speed == null || typeof speed === "boolean" ? cssFn.apply(this, arguments) : this.animate(genFx(name, true), speed, easing, callback);
        };
    });
    jQuery.each({
        slideDown: genFx("show"),
        slideUp: genFx("hide"),
        slideToggle: genFx("toggle"),
        fadeIn: {
            opacity: "show"
        },
        fadeOut: {
            opacity: "hide"
        },
        fadeToggle: {
            opacity: "toggle"
        }
    }, function(name, props) {
        jQuery.fn[name] = function(speed, easing, callback) {
            return this.animate(props, speed, easing, callback);
        };
    });
    jQuery.timers = [];
    jQuery.fx.tick = function() {
        var timer, i = 0, timers = jQuery.timers;
        fxNow = Date.now();
        for (;i < timers.length; i++) {
            timer = timers[i];
            if (!timer() && timers[i] === timer) {
                timers.splice(i--, 1);
            }
        }
        if (!timers.length) {
            jQuery.fx.stop();
        }
        fxNow = undefined;
    };
    jQuery.fx.timer = function(timer) {
        jQuery.timers.push(timer);
        jQuery.fx.start();
    };
    jQuery.fx.interval = 13;
    jQuery.fx.start = function() {
        if (inProgress) {
            return;
        }
        inProgress = true;
        schedule();
    };
    jQuery.fx.stop = function() {
        inProgress = null;
    };
    jQuery.fx.speeds = {
        slow: 600,
        fast: 200,
        _default: 400
    };
    jQuery.fn.delay = function(time, type) {
        time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
        type = type || "fx";
        return this.queue(type, function(next, hooks) {
            var timeout = window.setTimeout(next, time);
            hooks.stop = function() {
                window.clearTimeout(timeout);
            };
        });
    };
    (function() {
        var input = document.createElement("input"), select = document.createElement("select"), opt = select.appendChild(document.createElement("option"));
        input.type = "checkbox";
        support.checkOn = input.value !== "";
        support.optSelected = opt.selected;
        input = document.createElement("input");
        input.value = "t";
        input.type = "radio";
        support.radioValue = input.value === "t";
    })();
    var boolHook, attrHandle = jQuery.expr.attrHandle;
    jQuery.fn.extend({
        attr: function(name, value) {
            return access(this, jQuery.attr, name, value, arguments.length > 1);
        },
        removeAttr: function(name) {
            return this.each(function() {
                jQuery.removeAttr(this, name);
            });
        }
    });
    jQuery.extend({
        attr: function(elem, name, value) {
            var ret, hooks, nType = elem.nodeType;
            if (nType === 3 || nType === 8 || nType === 2) {
                return;
            }
            if (typeof elem.getAttribute === "undefined") {
                return jQuery.prop(elem, name, value);
            }
            if (nType !== 1 || !jQuery.isXMLDoc(elem)) {
                hooks = jQuery.attrHooks[name.toLowerCase()] || (jQuery.expr.match.bool.test(name) ? boolHook : undefined);
            }
            if (value !== undefined) {
                if (value === null) {
                    jQuery.removeAttr(elem, name);
                    return;
                }
                if (hooks && "set" in hooks && (ret = hooks.set(elem, value, name)) !== undefined) {
                    return ret;
                }
                elem.setAttribute(name, value + "");
                return value;
            }
            if (hooks && "get" in hooks && (ret = hooks.get(elem, name)) !== null) {
                return ret;
            }
            ret = jQuery.find.attr(elem, name);
            return ret == null ? undefined : ret;
        },
        attrHooks: {
            type: {
                set: function(elem, value) {
                    if (!support.radioValue && value === "radio" && nodeName(elem, "input")) {
                        var val = elem.value;
                        elem.setAttribute("type", value);
                        if (val) {
                            elem.value = val;
                        }
                        return value;
                    }
                }
            }
        },
        removeAttr: function(elem, value) {
            var name, i = 0, attrNames = value && value.match(rnothtmlwhite);
            if (attrNames && elem.nodeType === 1) {
                while (name = attrNames[i++]) {
                    elem.removeAttribute(name);
                }
            }
        }
    });
    boolHook = {
        set: function(elem, value, name) {
            if (value === false) {
                jQuery.removeAttr(elem, name);
            } else {
                elem.setAttribute(name, name);
            }
            return name;
        }
    };
    jQuery.each(jQuery.expr.match.bool.source.match(/\w+/g), function(_i, name) {
        var getter = attrHandle[name] || jQuery.find.attr;
        attrHandle[name] = function(elem, name, isXML) {
            var ret, handle, lowercaseName = name.toLowerCase();
            if (!isXML) {
                handle = attrHandle[lowercaseName];
                attrHandle[lowercaseName] = ret;
                ret = getter(elem, name, isXML) != null ? lowercaseName : null;
                attrHandle[lowercaseName] = handle;
            }
            return ret;
        };
    });
    var rfocusable = /^(?:input|select|textarea|button)$/i, rclickable = /^(?:a|area)$/i;
    jQuery.fn.extend({
        prop: function(name, value) {
            return access(this, jQuery.prop, name, value, arguments.length > 1);
        },
        removeProp: function(name) {
            return this.each(function() {
                delete this[jQuery.propFix[name] || name];
            });
        }
    });
    jQuery.extend({
        prop: function(elem, name, value) {
            var ret, hooks, nType = elem.nodeType;
            if (nType === 3 || nType === 8 || nType === 2) {
                return;
            }
            if (nType !== 1 || !jQuery.isXMLDoc(elem)) {
                name = jQuery.propFix[name] || name;
                hooks = jQuery.propHooks[name];
            }
            if (value !== undefined) {
                if (hooks && "set" in hooks && (ret = hooks.set(elem, value, name)) !== undefined) {
                    return ret;
                }
                return elem[name] = value;
            }
            if (hooks && "get" in hooks && (ret = hooks.get(elem, name)) !== null) {
                return ret;
            }
            return elem[name];
        },
        propHooks: {
            tabIndex: {
                get: function(elem) {
                    var tabindex = jQuery.find.attr(elem, "tabindex");
                    if (tabindex) {
                        return parseInt(tabindex, 10);
                    }
                    if (rfocusable.test(elem.nodeName) || rclickable.test(elem.nodeName) && elem.href) {
                        return 0;
                    }
                    return -1;
                }
            }
        },
        propFix: {
            for: "htmlFor",
            class: "className"
        }
    });
    if (!support.optSelected) {
        jQuery.propHooks.selected = {
            get: function(elem) {
                var parent = elem.parentNode;
                if (parent && parent.parentNode) {
                    parent.parentNode.selectedIndex;
                }
                return null;
            },
            set: function(elem) {
                var parent = elem.parentNode;
                if (parent) {
                    parent.selectedIndex;
                    if (parent.parentNode) {
                        parent.parentNode.selectedIndex;
                    }
                }
            }
        };
    }
    jQuery.each([ "tabIndex", "readOnly", "maxLength", "cellSpacing", "cellPadding", "rowSpan", "colSpan", "useMap", "frameBorder", "contentEditable" ], function() {
        jQuery.propFix[this.toLowerCase()] = this;
    });
    function stripAndCollapse(value) {
        var tokens = value.match(rnothtmlwhite) || [];
        return tokens.join(" ");
    }
    function getClass(elem) {
        return elem.getAttribute && elem.getAttribute("class") || "";
    }
    function classesToArray(value) {
        if (Array.isArray(value)) {
            return value;
        }
        if (typeof value === "string") {
            return value.match(rnothtmlwhite) || [];
        }
        return [];
    }
    jQuery.fn.extend({
        addClass: function(value) {
            var classes, elem, cur, curValue, clazz, j, finalValue, i = 0;
            if (isFunction(value)) {
                return this.each(function(j) {
                    jQuery(this).addClass(value.call(this, j, getClass(this)));
                });
            }
            classes = classesToArray(value);
            if (classes.length) {
                while (elem = this[i++]) {
                    curValue = getClass(elem);
                    cur = elem.nodeType === 1 && " " + stripAndCollapse(curValue) + " ";
                    if (cur) {
                        j = 0;
                        while (clazz = classes[j++]) {
                            if (cur.indexOf(" " + clazz + " ") < 0) {
                                cur += clazz + " ";
                            }
                        }
                        finalValue = stripAndCollapse(cur);
                        if (curValue !== finalValue) {
                            elem.setAttribute("class", finalValue);
                        }
                    }
                }
            }
            return this;
        },
        removeClass: function(value) {
            var classes, elem, cur, curValue, clazz, j, finalValue, i = 0;
            if (isFunction(value)) {
                return this.each(function(j) {
                    jQuery(this).removeClass(value.call(this, j, getClass(this)));
                });
            }
            if (!arguments.length) {
                return this.attr("class", "");
            }
            classes = classesToArray(value);
            if (classes.length) {
                while (elem = this[i++]) {
                    curValue = getClass(elem);
                    cur = elem.nodeType === 1 && " " + stripAndCollapse(curValue) + " ";
                    if (cur) {
                        j = 0;
                        while (clazz = classes[j++]) {
                            while (cur.indexOf(" " + clazz + " ") > -1) {
                                cur = cur.replace(" " + clazz + " ", " ");
                            }
                        }
                        finalValue = stripAndCollapse(cur);
                        if (curValue !== finalValue) {
                            elem.setAttribute("class", finalValue);
                        }
                    }
                }
            }
            return this;
        },
        toggleClass: function(value, stateVal) {
            var type = typeof value, isValidValue = type === "string" || Array.isArray(value);
            if (typeof stateVal === "boolean" && isValidValue) {
                return stateVal ? this.addClass(value) : this.removeClass(value);
            }
            if (isFunction(value)) {
                return this.each(function(i) {
                    jQuery(this).toggleClass(value.call(this, i, getClass(this), stateVal), stateVal);
                });
            }
            return this.each(function() {
                var className, i, self, classNames;
                if (isValidValue) {
                    i = 0;
                    self = jQuery(this);
                    classNames = classesToArray(value);
                    while (className = classNames[i++]) {
                        if (self.hasClass(className)) {
                            self.removeClass(className);
                        } else {
                            self.addClass(className);
                        }
                    }
                } else if (value === undefined || type === "boolean") {
                    className = getClass(this);
                    if (className) {
                        dataPriv.set(this, "__className__", className);
                    }
                    if (this.setAttribute) {
                        this.setAttribute("class", className || value === false ? "" : dataPriv.get(this, "__className__") || "");
                    }
                }
            });
        },
        hasClass: function(selector) {
            var className, elem, i = 0;
            className = " " + selector + " ";
            while (elem = this[i++]) {
                if (elem.nodeType === 1 && (" " + stripAndCollapse(getClass(elem)) + " ").indexOf(className) > -1) {
                    return true;
                }
            }
            return false;
        }
    });
    var rreturn = /\r/g;
    jQuery.fn.extend({
        val: function(value) {
            var hooks, ret, valueIsFunction, elem = this[0];
            if (!arguments.length) {
                if (elem) {
                    hooks = jQuery.valHooks[elem.type] || jQuery.valHooks[elem.nodeName.toLowerCase()];
                    if (hooks && "get" in hooks && (ret = hooks.get(elem, "value")) !== undefined) {
                        return ret;
                    }
                    ret = elem.value;
                    if (typeof ret === "string") {
                        return ret.replace(rreturn, "");
                    }
                    return ret == null ? "" : ret;
                }
                return;
            }
            valueIsFunction = isFunction(value);
            return this.each(function(i) {
                var val;
                if (this.nodeType !== 1) {
                    return;
                }
                if (valueIsFunction) {
                    val = value.call(this, i, jQuery(this).val());
                } else {
                    val = value;
                }
                if (val == null) {
                    val = "";
                } else if (typeof val === "number") {
                    val += "";
                } else if (Array.isArray(val)) {
                    val = jQuery.map(val, function(value) {
                        return value == null ? "" : value + "";
                    });
                }
                hooks = jQuery.valHooks[this.type] || jQuery.valHooks[this.nodeName.toLowerCase()];
                if (!hooks || !("set" in hooks) || hooks.set(this, val, "value") === undefined) {
                    this.value = val;
                }
            });
        }
    });
    jQuery.extend({
        valHooks: {
            option: {
                get: function(elem) {
                    var val = jQuery.find.attr(elem, "value");
                    return val != null ? val : stripAndCollapse(jQuery.text(elem));
                }
            },
            select: {
                get: function(elem) {
                    var value, option, i, options = elem.options, index = elem.selectedIndex, one = elem.type === "select-one", values = one ? null : [], max = one ? index + 1 : options.length;
                    if (index < 0) {
                        i = max;
                    } else {
                        i = one ? index : 0;
                    }
                    for (;i < max; i++) {
                        option = options[i];
                        if ((option.selected || i === index) && !option.disabled && (!option.parentNode.disabled || !nodeName(option.parentNode, "optgroup"))) {
                            value = jQuery(option).val();
                            if (one) {
                                return value;
                            }
                            values.push(value);
                        }
                    }
                    return values;
                },
                set: function(elem, value) {
                    var optionSet, option, options = elem.options, values = jQuery.makeArray(value), i = options.length;
                    while (i--) {
                        option = options[i];
                        if (option.selected = jQuery.inArray(jQuery.valHooks.option.get(option), values) > -1) {
                            optionSet = true;
                        }
                    }
                    if (!optionSet) {
                        elem.selectedIndex = -1;
                    }
                    return values;
                }
            }
        }
    });
    jQuery.each([ "radio", "checkbox" ], function() {
        jQuery.valHooks[this] = {
            set: function(elem, value) {
                if (Array.isArray(value)) {
                    return elem.checked = jQuery.inArray(jQuery(elem).val(), value) > -1;
                }
            }
        };
        if (!support.checkOn) {
            jQuery.valHooks[this].get = function(elem) {
                return elem.getAttribute("value") === null ? "on" : elem.value;
            };
        }
    });
    support.focusin = "onfocusin" in window;
    var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, stopPropagationCallback = function(e) {
        e.stopPropagation();
    };
    jQuery.extend(jQuery.event, {
        trigger: function(event, data, elem, onlyHandlers) {
            var i, cur, tmp, bubbleType, ontype, handle, special, lastElement, eventPath = [ elem || document ], type = hasOwn.call(event, "type") ? event.type : event, namespaces = hasOwn.call(event, "namespace") ? event.namespace.split(".") : [];
            cur = lastElement = tmp = elem = elem || document;
            if (elem.nodeType === 3 || elem.nodeType === 8) {
                return;
            }
            if (rfocusMorph.test(type + jQuery.event.triggered)) {
                return;
            }
            if (type.indexOf(".") > -1) {
                namespaces = type.split(".");
                type = namespaces.shift();
                namespaces.sort();
            }
            ontype = type.indexOf(":") < 0 && "on" + type;
            event = event[jQuery.expando] ? event : new jQuery.Event(type, typeof event === "object" && event);
            event.isTrigger = onlyHandlers ? 2 : 3;
            event.namespace = namespaces.join(".");
            event.rnamespace = event.namespace ? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)") : null;
            event.result = undefined;
            if (!event.target) {
                event.target = elem;
            }
            data = data == null ? [ event ] : jQuery.makeArray(data, [ event ]);
            special = jQuery.event.special[type] || {};
            if (!onlyHandlers && special.trigger && special.trigger.apply(elem, data) === false) {
                return;
            }
            if (!onlyHandlers && !special.noBubble && !isWindow(elem)) {
                bubbleType = special.delegateType || type;
                if (!rfocusMorph.test(bubbleType + type)) {
                    cur = cur.parentNode;
                }
                for (;cur; cur = cur.parentNode) {
                    eventPath.push(cur);
                    tmp = cur;
                }
                if (tmp === (elem.ownerDocument || document)) {
                    eventPath.push(tmp.defaultView || tmp.parentWindow || window);
                }
            }
            i = 0;
            while ((cur = eventPath[i++]) && !event.isPropagationStopped()) {
                lastElement = cur;
                event.type = i > 1 ? bubbleType : special.bindType || type;
                handle = (dataPriv.get(cur, "events") || Object.create(null))[event.type] && dataPriv.get(cur, "handle");
                if (handle) {
                    handle.apply(cur, data);
                }
                handle = ontype && cur[ontype];
                if (handle && handle.apply && acceptData(cur)) {
                    event.result = handle.apply(cur, data);
                    if (event.result === false) {
                        event.preventDefault();
                    }
                }
            }
            event.type = type;
            if (!onlyHandlers && !event.isDefaultPrevented()) {
                if ((!special._default || special._default.apply(eventPath.pop(), data) === false) && acceptData(elem)) {
                    if (ontype && isFunction(elem[type]) && !isWindow(elem)) {
                        tmp = elem[ontype];
                        if (tmp) {
                            elem[ontype] = null;
                        }
                        jQuery.event.triggered = type;
                        if (event.isPropagationStopped()) {
                            lastElement.addEventListener(type, stopPropagationCallback);
                        }
                        elem[type]();
                        if (event.isPropagationStopped()) {
                            lastElement.removeEventListener(type, stopPropagationCallback);
                        }
                        jQuery.event.triggered = undefined;
                        if (tmp) {
                            elem[ontype] = tmp;
                        }
                    }
                }
            }
            return event.result;
        },
        simulate: function(type, elem, event) {
            var e = jQuery.extend(new jQuery.Event(), event, {
                type: type,
                isSimulated: true
            });
            jQuery.event.trigger(e, null, elem);
        }
    });
    jQuery.fn.extend({
        trigger: function(type, data) {
            return this.each(function() {
                jQuery.event.trigger(type, data, this);
            });
        },
        triggerHandler: function(type, data) {
            var elem = this[0];
            if (elem) {
                return jQuery.event.trigger(type, data, elem, true);
            }
        }
    });
    if (!support.focusin) {
        jQuery.each({
            focus: "focusin",
            blur: "focusout"
        }, function(orig, fix) {
            var handler = function(event) {
                jQuery.event.simulate(fix, event.target, jQuery.event.fix(event));
            };
            jQuery.event.special[fix] = {
                setup: function() {
                    var doc = this.ownerDocument || this.document || this, attaches = dataPriv.access(doc, fix);
                    if (!attaches) {
                        doc.addEventListener(orig, handler, true);
                    }
                    dataPriv.access(doc, fix, (attaches || 0) + 1);
                },
                teardown: function() {
                    var doc = this.ownerDocument || this.document || this, attaches = dataPriv.access(doc, fix) - 1;
                    if (!attaches) {
                        doc.removeEventListener(orig, handler, true);
                        dataPriv.remove(doc, fix);
                    } else {
                        dataPriv.access(doc, fix, attaches);
                    }
                }
            };
        });
    }
    var location = window.location;
    var nonce = {
        guid: Date.now()
    };
    var rquery = /\?/;
    jQuery.parseXML = function(data) {
        var xml;
        if (!data || typeof data !== "string") {
            return null;
        }
        try {
            xml = new window.DOMParser().parseFromString(data, "text/xml");
        } catch (e) {
            xml = undefined;
        }
        if (!xml || xml.getElementsByTagName("parsererror").length) {
            jQuery.error("Invalid XML: " + data);
        }
        return xml;
    };
    var rbracket = /\[\]$/, rCRLF = /\r?\n/g, rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i, rsubmittable = /^(?:input|select|textarea|keygen)/i;
    function buildParams(prefix, obj, traditional, add) {
        var name;
        if (Array.isArray(obj)) {
            jQuery.each(obj, function(i, v) {
                if (traditional || rbracket.test(prefix)) {
                    add(prefix, v);
                } else {
                    buildParams(prefix + "[" + (typeof v === "object" && v != null ? i : "") + "]", v, traditional, add);
                }
            });
        } else if (!traditional && toType(obj) === "object") {
            for (name in obj) {
                buildParams(prefix + "[" + name + "]", obj[name], traditional, add);
            }
        } else {
            add(prefix, obj);
        }
    }
    jQuery.param = function(a, traditional) {
        var prefix, s = [], add = function(key, valueOrFunction) {
            var value = isFunction(valueOrFunction) ? valueOrFunction() : valueOrFunction;
            s[s.length] = encodeURIComponent(key) + "=" + encodeURIComponent(value == null ? "" : value);
        };
        if (a == null) {
            return "";
        }
        if (Array.isArray(a) || a.jquery && !jQuery.isPlainObject(a)) {
            jQuery.each(a, function() {
                add(this.name, this.value);
            });
        } else {
            for (prefix in a) {
                buildParams(prefix, a[prefix], traditional, add);
            }
        }
        return s.join("&");
    };
    jQuery.fn.extend({
        serialize: function() {
            return jQuery.param(this.serializeArray());
        },
        serializeArray: function() {
            return this.map(function() {
                var elements = jQuery.prop(this, "elements");
                return elements ? jQuery.makeArray(elements) : this;
            }).filter(function() {
                var type = this.type;
                return this.name && !jQuery(this).is(":disabled") && rsubmittable.test(this.nodeName) && !rsubmitterTypes.test(type) && (this.checked || !rcheckableType.test(type));
            }).map(function(_i, elem) {
                var val = jQuery(this).val();
                if (val == null) {
                    return null;
                }
                if (Array.isArray(val)) {
                    return jQuery.map(val, function(val) {
                        return {
                            name: elem.name,
                            value: val.replace(rCRLF, "\r\n")
                        };
                    });
                }
                return {
                    name: elem.name,
                    value: val.replace(rCRLF, "\r\n")
                };
            }).get();
        }
    });
    var r20 = /%20/g, rhash = /#.*$/, rantiCache = /([?&])_=[^&]*/, rheaders = /^(.*?):[ \t]*([^\r\n]*)$/gm, rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, rnoContent = /^(?:GET|HEAD)$/, rprotocol = /^\/\//, prefilters = {}, transports = {}, allTypes = "*/".concat("*"), originAnchor = document.createElement("a");
    originAnchor.href = location.href;
    function addToPrefiltersOrTransports(structure) {
        return function(dataTypeExpression, func) {
            if (typeof dataTypeExpression !== "string") {
                func = dataTypeExpression;
                dataTypeExpression = "*";
            }
            var dataType, i = 0, dataTypes = dataTypeExpression.toLowerCase().match(rnothtmlwhite) || [];
            if (isFunction(func)) {
                while (dataType = dataTypes[i++]) {
                    if (dataType[0] === "+") {
                        dataType = dataType.slice(1) || "*";
                        (structure[dataType] = structure[dataType] || []).unshift(func);
                    } else {
                        (structure[dataType] = structure[dataType] || []).push(func);
                    }
                }
            }
        };
    }
    function inspectPrefiltersOrTransports(structure, options, originalOptions, jqXHR) {
        var inspected = {}, seekingTransport = structure === transports;
        function inspect(dataType) {
            var selected;
            inspected[dataType] = true;
            jQuery.each(structure[dataType] || [], function(_, prefilterOrFactory) {
                var dataTypeOrTransport = prefilterOrFactory(options, originalOptions, jqXHR);
                if (typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[dataTypeOrTransport]) {
                    options.dataTypes.unshift(dataTypeOrTransport);
                    inspect(dataTypeOrTransport);
                    return false;
                } else if (seekingTransport) {
                    return !(selected = dataTypeOrTransport);
                }
            });
            return selected;
        }
        return inspect(options.dataTypes[0]) || !inspected["*"] && inspect("*");
    }
    function ajaxExtend(target, src) {
        var key, deep, flatOptions = jQuery.ajaxSettings.flatOptions || {};
        for (key in src) {
            if (src[key] !== undefined) {
                (flatOptions[key] ? target : deep || (deep = {}))[key] = src[key];
            }
        }
        if (deep) {
            jQuery.extend(true, target, deep);
        }
        return target;
    }
    function ajaxHandleResponses(s, jqXHR, responses) {
        var ct, type, finalDataType, firstDataType, contents = s.contents, dataTypes = s.dataTypes;
        while (dataTypes[0] === "*") {
            dataTypes.shift();
            if (ct === undefined) {
                ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
            }
        }
        if (ct) {
            for (type in contents) {
                if (contents[type] && contents[type].test(ct)) {
                    dataTypes.unshift(type);
                    break;
                }
            }
        }
        if (dataTypes[0] in responses) {
            finalDataType = dataTypes[0];
        } else {
            for (type in responses) {
                if (!dataTypes[0] || s.converters[type + " " + dataTypes[0]]) {
                    finalDataType = type;
                    break;
                }
                if (!firstDataType) {
                    firstDataType = type;
                }
            }
            finalDataType = finalDataType || firstDataType;
        }
        if (finalDataType) {
            if (finalDataType !== dataTypes[0]) {
                dataTypes.unshift(finalDataType);
            }
            return responses[finalDataType];
        }
    }
    function ajaxConvert(s, response, jqXHR, isSuccess) {
        var conv2, current, conv, tmp, prev, converters = {}, dataTypes = s.dataTypes.slice();
        if (dataTypes[1]) {
            for (conv in s.converters) {
                converters[conv.toLowerCase()] = s.converters[conv];
            }
        }
        current = dataTypes.shift();
        while (current) {
            if (s.responseFields[current]) {
                jqXHR[s.responseFields[current]] = response;
            }
            if (!prev && isSuccess && s.dataFilter) {
                response = s.dataFilter(response, s.dataType);
            }
            prev = current;
            current = dataTypes.shift();
            if (current) {
                if (current === "*") {
                    current = prev;
                } else if (prev !== "*" && prev !== current) {
                    conv = converters[prev + " " + current] || converters["* " + current];
                    if (!conv) {
                        for (conv2 in converters) {
                            tmp = conv2.split(" ");
                            if (tmp[1] === current) {
                                conv = converters[prev + " " + tmp[0]] || converters["* " + tmp[0]];
                                if (conv) {
                                    if (conv === true) {
                                        conv = converters[conv2];
                                    } else if (converters[conv2] !== true) {
                                        current = tmp[0];
                                        dataTypes.unshift(tmp[1]);
                                    }
                                    break;
                                }
                            }
                        }
                    }
                    if (conv !== true) {
                        if (conv && s.throws) {
                            response = conv(response);
                        } else {
                            try {
                                response = conv(response);
                            } catch (e) {
                                return {
                                    state: "parsererror",
                                    error: conv ? e : "No conversion from " + prev + " to " + current
                                };
                            }
                        }
                    }
                }
            }
        }
        return {
            state: "success",
            data: response
        };
    }
    jQuery.extend({
        active: 0,
        lastModified: {},
        etag: {},
        ajaxSettings: {
            url: location.href,
            type: "GET",
            isLocal: rlocalProtocol.test(location.protocol),
            global: true,
            processData: true,
            async: true,
            contentType: "application/x-www-form-urlencoded; charset=UTF-8",
            accepts: {
                "*": allTypes,
                text: "text/plain",
                html: "text/html",
                xml: "application/xml, text/xml",
                json: "application/json, text/javascript"
            },
            contents: {
                xml: /\bxml\b/,
                html: /\bhtml/,
                json: /\bjson\b/
            },
            responseFields: {
                xml: "responseXML",
                text: "responseText",
                json: "responseJSON"
            },
            converters: {
                "* text": String,
                "text html": true,
                "text json": JSON.parse,
                "text xml": jQuery.parseXML
            },
            flatOptions: {
                url: true,
                context: true
            }
        },
        ajaxSetup: function(target, settings) {
            return settings ? ajaxExtend(ajaxExtend(target, jQuery.ajaxSettings), settings) : ajaxExtend(jQuery.ajaxSettings, target);
        },
        ajaxPrefilter: addToPrefiltersOrTransports(prefilters),
        ajaxTransport: addToPrefiltersOrTransports(transports),
        ajax: function(url, options) {
            if (typeof url === "object") {
                options = url;
                url = undefined;
            }
            options = options || {};
            var transport, cacheURL, responseHeadersString, responseHeaders, timeoutTimer, urlAnchor, completed, fireGlobals, i, uncached, s = jQuery.ajaxSetup({}, options), callbackContext = s.context || s, globalEventContext = s.context && (callbackContext.nodeType || callbackContext.jquery) ? jQuery(callbackContext) : jQuery.event, deferred = jQuery.Deferred(), completeDeferred = jQuery.Callbacks("once memory"), statusCode = s.statusCode || {}, requestHeaders = {}, requestHeadersNames = {}, strAbort = "canceled", jqXHR = {
                readyState: 0,
                getResponseHeader: function(key) {
                    var match;
                    if (completed) {
                        if (!responseHeaders) {
                            responseHeaders = {};
                            while (match = rheaders.exec(responseHeadersString)) {
                                responseHeaders[match[1].toLowerCase() + " "] = (responseHeaders[match[1].toLowerCase() + " "] || []).concat(match[2]);
                            }
                        }
                        match = responseHeaders[key.toLowerCase() + " "];
                    }
                    return match == null ? null : match.join(", ");
                },
                getAllResponseHeaders: function() {
                    return completed ? responseHeadersString : null;
                },
                setRequestHeader: function(name, value) {
                    if (completed == null) {
                        name = requestHeadersNames[name.toLowerCase()] = requestHeadersNames[name.toLowerCase()] || name;
                        requestHeaders[name] = value;
                    }
                    return this;
                },
                overrideMimeType: function(type) {
                    if (completed == null) {
                        s.mimeType = type;
                    }
                    return this;
                },
                statusCode: function(map) {
                    var code;
                    if (map) {
                        if (completed) {
                            jqXHR.always(map[jqXHR.status]);
                        } else {
                            for (code in map) {
                                statusCode[code] = [ statusCode[code], map[code] ];
                            }
                        }
                    }
                    return this;
                },
                abort: function(statusText) {
                    var finalText = statusText || strAbort;
                    if (transport) {
                        transport.abort(finalText);
                    }
                    done(0, finalText);
                    return this;
                }
            };
            deferred.promise(jqXHR);
            s.url = ((url || s.url || location.href) + "").replace(rprotocol, location.protocol + "//");
            s.type = options.method || options.type || s.method || s.type;
            s.dataTypes = (s.dataType || "*").toLowerCase().match(rnothtmlwhite) || [ "" ];
            if (s.crossDomain == null) {
                urlAnchor = document.createElement("a");
                try {
                    urlAnchor.href = s.url;
                    urlAnchor.href = urlAnchor.href;
                    s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== urlAnchor.protocol + "//" + urlAnchor.host;
                } catch (e) {
                    s.crossDomain = true;
                }
            }
            if (s.data && s.processData && typeof s.data !== "string") {
                s.data = jQuery.param(s.data, s.traditional);
            }
            inspectPrefiltersOrTransports(prefilters, s, options, jqXHR);
            if (completed) {
                return jqXHR;
            }
            fireGlobals = jQuery.event && s.global;
            if (fireGlobals && jQuery.active++ === 0) {
                jQuery.event.trigger("ajaxStart");
            }
            s.type = s.type.toUpperCase();
            s.hasContent = !rnoContent.test(s.type);
            cacheURL = s.url.replace(rhash, "");
            if (!s.hasContent) {
                uncached = s.url.slice(cacheURL.length);
                if (s.data && (s.processData || typeof s.data === "string")) {
                    cacheURL += (rquery.test(cacheURL) ? "&" : "?") + s.data;
                    delete s.data;
                }
                if (s.cache === false) {
                    cacheURL = cacheURL.replace(rantiCache, "$1");
                    uncached = (rquery.test(cacheURL) ? "&" : "?") + "_=" + nonce.guid++ + uncached;
                }
                s.url = cacheURL + uncached;
            } else if (s.data && s.processData && (s.contentType || "").indexOf("application/x-www-form-urlencoded") === 0) {
                s.data = s.data.replace(r20, "+");
            }
            if (s.ifModified) {
                if (jQuery.lastModified[cacheURL]) {
                    jqXHR.setRequestHeader("If-Modified-Since", jQuery.lastModified[cacheURL]);
                }
                if (jQuery.etag[cacheURL]) {
                    jqXHR.setRequestHeader("If-None-Match", jQuery.etag[cacheURL]);
                }
            }
            if (s.data && s.hasContent && s.contentType !== false || options.contentType) {
                jqXHR.setRequestHeader("Content-Type", s.contentType);
            }
            jqXHR.setRequestHeader("Accept", s.dataTypes[0] && s.accepts[s.dataTypes[0]] ? s.accepts[s.dataTypes[0]] + (s.dataTypes[0] !== "*" ? ", " + allTypes + "; q=0.01" : "") : s.accepts["*"]);
            for (i in s.headers) {
                jqXHR.setRequestHeader(i, s.headers[i]);
            }
            if (s.beforeSend && (s.beforeSend.call(callbackContext, jqXHR, s) === false || completed)) {
                return jqXHR.abort();
            }
            strAbort = "abort";
            completeDeferred.add(s.complete);
            jqXHR.done(s.success);
            jqXHR.fail(s.error);
            transport = inspectPrefiltersOrTransports(transports, s, options, jqXHR);
            if (!transport) {
                done(-1, "No Transport");
            } else {
                jqXHR.readyState = 1;
                if (fireGlobals) {
                    globalEventContext.trigger("ajaxSend", [ jqXHR, s ]);
                }
                if (completed) {
                    return jqXHR;
                }
                if (s.async && s.timeout > 0) {
                    timeoutTimer = window.setTimeout(function() {
                        jqXHR.abort("timeout");
                    }, s.timeout);
                }
                try {
                    completed = false;
                    transport.send(requestHeaders, done);
                } catch (e) {
                    if (completed) {
                        throw e;
                    }
                    done(-1, e);
                }
            }
            function done(status, nativeStatusText, responses, headers) {
                var isSuccess, success, error, response, modified, statusText = nativeStatusText;
                if (completed) {
                    return;
                }
                completed = true;
                if (timeoutTimer) {
                    window.clearTimeout(timeoutTimer);
                }
                transport = undefined;
                responseHeadersString = headers || "";
                jqXHR.readyState = status > 0 ? 4 : 0;
                isSuccess = status >= 200 && status < 300 || status === 304;
                if (responses) {
                    response = ajaxHandleResponses(s, jqXHR, responses);
                }
                if (!isSuccess && jQuery.inArray("script", s.dataTypes) > -1) {
                    s.converters["text script"] = function() {};
                }
                response = ajaxConvert(s, response, jqXHR, isSuccess);
                if (isSuccess) {
                    if (s.ifModified) {
                        modified = jqXHR.getResponseHeader("Last-Modified");
                        if (modified) {
                            jQuery.lastModified[cacheURL] = modified;
                        }
                        modified = jqXHR.getResponseHeader("etag");
                        if (modified) {
                            jQuery.etag[cacheURL] = modified;
                        }
                    }
                    if (status === 204 || s.type === "HEAD") {
                        statusText = "nocontent";
                    } else if (status === 304) {
                        statusText = "notmodified";
                    } else {
                        statusText = response.state;
                        success = response.data;
                        error = response.error;
                        isSuccess = !error;
                    }
                } else {
                    error = statusText;
                    if (status || !statusText) {
                        statusText = "error";
                        if (status < 0) {
                            status = 0;
                        }
                    }
                }
                jqXHR.status = status;
                jqXHR.statusText = (nativeStatusText || statusText) + "";
                if (isSuccess) {
                    deferred.resolveWith(callbackContext, [ success, statusText, jqXHR ]);
                } else {
                    deferred.rejectWith(callbackContext, [ jqXHR, statusText, error ]);
                }
                jqXHR.statusCode(statusCode);
                statusCode = undefined;
                if (fireGlobals) {
                    globalEventContext.trigger(isSuccess ? "ajaxSuccess" : "ajaxError", [ jqXHR, s, isSuccess ? success : error ]);
                }
                completeDeferred.fireWith(callbackContext, [ jqXHR, statusText ]);
                if (fireGlobals) {
                    globalEventContext.trigger("ajaxComplete", [ jqXHR, s ]);
                    if (!--jQuery.active) {
                        jQuery.event.trigger("ajaxStop");
                    }
                }
            }
            return jqXHR;
        },
        getJSON: function(url, data, callback) {
            return jQuery.get(url, data, callback, "json");
        },
        getScript: function(url, callback) {
            return jQuery.get(url, undefined, callback, "script");
        }
    });
    jQuery.each([ "get", "post" ], function(_i, method) {
        jQuery[method] = function(url, data, callback, type) {
            if (isFunction(data)) {
                type = type || callback;
                callback = data;
                data = undefined;
            }
            return jQuery.ajax(jQuery.extend({
                url: url,
                type: method,
                dataType: type,
                data: data,
                success: callback
            }, jQuery.isPlainObject(url) && url));
        };
    });
    jQuery.ajaxPrefilter(function(s) {
        var i;
        for (i in s.headers) {
            if (i.toLowerCase() === "content-type") {
                s.contentType = s.headers[i] || "";
            }
        }
    });
    jQuery._evalUrl = function(url, options, doc) {
        return jQuery.ajax({
            url: url,
            type: "GET",
            dataType: "script",
            cache: true,
            async: false,
            global: false,
            converters: {
                "text script": function() {}
            },
            dataFilter: function(response) {
                jQuery.globalEval(response, options, doc);
            }
        });
    };
    jQuery.fn.extend({
        wrapAll: function(html) {
            var wrap;
            if (this[0]) {
                if (isFunction(html)) {
                    html = html.call(this[0]);
                }
                wrap = jQuery(html, this[0].ownerDocument).eq(0).clone(true);
                if (this[0].parentNode) {
                    wrap.insertBefore(this[0]);
                }
                wrap.map(function() {
                    var elem = this;
                    while (elem.firstElementChild) {
                        elem = elem.firstElementChild;
                    }
                    return elem;
                }).append(this);
            }
            return this;
        },
        wrapInner: function(html) {
            if (isFunction(html)) {
                return this.each(function(i) {
                    jQuery(this).wrapInner(html.call(this, i));
                });
            }
            return this.each(function() {
                var self = jQuery(this), contents = self.contents();
                if (contents.length) {
                    contents.wrapAll(html);
                } else {
                    self.append(html);
                }
            });
        },
        wrap: function(html) {
            var htmlIsFunction = isFunction(html);
            return this.each(function(i) {
                jQuery(this).wrapAll(htmlIsFunction ? html.call(this, i) : html);
            });
        },
        unwrap: function(selector) {
            this.parent(selector).not("body").each(function() {
                jQuery(this).replaceWith(this.childNodes);
            });
            return this;
        }
    });
    jQuery.expr.pseudos.hidden = function(elem) {
        return !jQuery.expr.pseudos.visible(elem);
    };
    jQuery.expr.pseudos.visible = function(elem) {
        return !!(elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length);
    };
    jQuery.ajaxSettings.xhr = function() {
        try {
            return new window.XMLHttpRequest();
        } catch (e) {}
    };
    var xhrSuccessStatus = {
        0: 200,
        1223: 204
    }, xhrSupported = jQuery.ajaxSettings.xhr();
    support.cors = !!xhrSupported && "withCredentials" in xhrSupported;
    support.ajax = xhrSupported = !!xhrSupported;
    jQuery.ajaxTransport(function(options) {
        var callback, errorCallback;
        if (support.cors || xhrSupported && !options.crossDomain) {
            return {
                send: function(headers, complete) {
                    var i, xhr = options.xhr();
                    xhr.open(options.type, options.url, options.async, options.username, options.password);
                    if (options.xhrFields) {
                        for (i in options.xhrFields) {
                            xhr[i] = options.xhrFields[i];
                        }
                    }
                    if (options.mimeType && xhr.overrideMimeType) {
                        xhr.overrideMimeType(options.mimeType);
                    }
                    if (!options.crossDomain && !headers["X-Requested-With"]) {
                        headers["X-Requested-With"] = "XMLHttpRequest";
                    }
                    for (i in headers) {
                        xhr.setRequestHeader(i, headers[i]);
                    }
                    callback = function(type) {
                        return function() {
                            if (callback) {
                                callback = errorCallback = xhr.onload = xhr.onerror = xhr.onabort = xhr.ontimeout = xhr.onreadystatechange = null;
                                if (type === "abort") {
                                    xhr.abort();
                                } else if (type === "error") {
                                    if (typeof xhr.status !== "number") {
                                        complete(0, "error");
                                    } else {
                                        complete(xhr.status, xhr.statusText);
                                    }
                                } else {
                                    complete(xhrSuccessStatus[xhr.status] || xhr.status, xhr.statusText, (xhr.responseType || "text") !== "text" || typeof xhr.responseText !== "string" ? {
                                        binary: xhr.response
                                    } : {
                                        text: xhr.responseText
                                    }, xhr.getAllResponseHeaders());
                                }
                            }
                        };
                    };
                    xhr.onload = callback();
                    errorCallback = xhr.onerror = xhr.ontimeout = callback("error");
                    if (xhr.onabort !== undefined) {
                        xhr.onabort = errorCallback;
                    } else {
                        xhr.onreadystatechange = function() {
                            if (xhr.readyState === 4) {
                                window.setTimeout(function() {
                                    if (callback) {
                                        errorCallback();
                                    }
                                });
                            }
                        };
                    }
                    callback = callback("abort");
                    try {
                        xhr.send(options.hasContent && options.data || null);
                    } catch (e) {
                        if (callback) {
                            throw e;
                        }
                    }
                },
                abort: function() {
                    if (callback) {
                        callback();
                    }
                }
            };
        }
    });
    jQuery.ajaxPrefilter(function(s) {
        if (s.crossDomain) {
            s.contents.script = false;
        }
    });
    jQuery.ajaxSetup({
        accepts: {
            script: "text/javascript, application/javascript, " + "application/ecmascript, application/x-ecmascript"
        },
        contents: {
            script: /\b(?:java|ecma)script\b/
        },
        converters: {
            "text script": function(text) {
                jQuery.globalEval(text);
                return text;
            }
        }
    });
    jQuery.ajaxPrefilter("script", function(s) {
        if (s.cache === undefined) {
            s.cache = false;
        }
        if (s.crossDomain) {
            s.type = "GET";
        }
    });
    jQuery.ajaxTransport("script", function(s) {
        if (s.crossDomain || s.scriptAttrs) {
            var script, callback;
            return {
                send: function(_, complete) {
                    script = jQuery("<script>").attr(s.scriptAttrs || {}).prop({
                        charset: s.scriptCharset,
                        src: s.url
                    }).on("load error", callback = function(evt) {
                        script.remove();
                        callback = null;
                        if (evt) {
                            complete(evt.type === "error" ? 404 : 200, evt.type);
                        }
                    });
                    document.head.appendChild(script[0]);
                },
                abort: function() {
                    if (callback) {
                        callback();
                    }
                }
            };
        }
    });
    var oldCallbacks = [], rjsonp = /(=)\?(?=&|$)|\?\?/;
    jQuery.ajaxSetup({
        jsonp: "callback",
        jsonpCallback: function() {
            var callback = oldCallbacks.pop() || jQuery.expando + "_" + nonce.guid++;
            this[callback] = true;
            return callback;
        }
    });
    jQuery.ajaxPrefilter("json jsonp", function(s, originalSettings, jqXHR) {
        var callbackName, overwritten, responseContainer, jsonProp = s.jsonp !== false && (rjsonp.test(s.url) ? "url" : typeof s.data === "string" && (s.contentType || "").indexOf("application/x-www-form-urlencoded") === 0 && rjsonp.test(s.data) && "data");
        if (jsonProp || s.dataTypes[0] === "jsonp") {
            callbackName = s.jsonpCallback = isFunction(s.jsonpCallback) ? s.jsonpCallback() : s.jsonpCallback;
            if (jsonProp) {
                s[jsonProp] = s[jsonProp].replace(rjsonp, "$1" + callbackName);
            } else if (s.jsonp !== false) {
                s.url += (rquery.test(s.url) ? "&" : "?") + s.jsonp + "=" + callbackName;
            }
            s.converters["script json"] = function() {
                if (!responseContainer) {
                    jQuery.error(callbackName + " was not called");
                }
                return responseContainer[0];
            };
            s.dataTypes[0] = "json";
            overwritten = window[callbackName];
            window[callbackName] = function() {
                responseContainer = arguments;
            };
            jqXHR.always(function() {
                if (overwritten === undefined) {
                    jQuery(window).removeProp(callbackName);
                } else {
                    window[callbackName] = overwritten;
                }
                if (s[callbackName]) {
                    s.jsonpCallback = originalSettings.jsonpCallback;
                    oldCallbacks.push(callbackName);
                }
                if (responseContainer && isFunction(overwritten)) {
                    overwritten(responseContainer[0]);
                }
                responseContainer = overwritten = undefined;
            });
            return "script";
        }
    });
    support.createHTMLDocument = function() {
        var body = document.implementation.createHTMLDocument("").body;
        body.innerHTML = "<form></form><form></form>";
        return body.childNodes.length === 2;
    }();
    jQuery.parseHTML = function(data, context, keepScripts) {
        if (typeof data !== "string") {
            return [];
        }
        if (typeof context === "boolean") {
            keepScripts = context;
            context = false;
        }
        var base, parsed, scripts;
        if (!context) {
            if (support.createHTMLDocument) {
                context = document.implementation.createHTMLDocument("");
                base = context.createElement("base");
                base.href = document.location.href;
                context.head.appendChild(base);
            } else {
                context = document;
            }
        }
        parsed = rsingleTag.exec(data);
        scripts = !keepScripts && [];
        if (parsed) {
            return [ context.createElement(parsed[1]) ];
        }
        parsed = buildFragment([ data ], context, scripts);
        if (scripts && scripts.length) {
            jQuery(scripts).remove();
        }
        return jQuery.merge([], parsed.childNodes);
    };
    jQuery.fn.load = function(url, params, callback) {
        var selector, type, response, self = this, off = url.indexOf(" ");
        if (off > -1) {
            selector = stripAndCollapse(url.slice(off));
            url = url.slice(0, off);
        }
        if (isFunction(params)) {
            callback = params;
            params = undefined;
        } else if (params && typeof params === "object") {
            type = "POST";
        }
        if (self.length > 0) {
            jQuery.ajax({
                url: url,
                type: type || "GET",
                dataType: "html",
                data: params
            }).done(function(responseText) {
                response = arguments;
                self.html(selector ? jQuery("<div>").append(jQuery.parseHTML(responseText)).find(selector) : responseText);
            }).always(callback && function(jqXHR, status) {
                self.each(function() {
                    callback.apply(this, response || [ jqXHR.responseText, status, jqXHR ]);
                });
            });
        }
        return this;
    };
    jQuery.expr.pseudos.animated = function(elem) {
        return jQuery.grep(jQuery.timers, function(fn) {
            return elem === fn.elem;
        }).length;
    };
    jQuery.offset = {
        setOffset: function(elem, options, i) {
            var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition, position = jQuery.css(elem, "position"), curElem = jQuery(elem), props = {};
            if (position === "static") {
                elem.style.position = "relative";
            }
            curOffset = curElem.offset();
            curCSSTop = jQuery.css(elem, "top");
            curCSSLeft = jQuery.css(elem, "left");
            calculatePosition = (position === "absolute" || position === "fixed") && (curCSSTop + curCSSLeft).indexOf("auto") > -1;
            if (calculatePosition) {
                curPosition = curElem.position();
                curTop = curPosition.top;
                curLeft = curPosition.left;
            } else {
                curTop = parseFloat(curCSSTop) || 0;
                curLeft = parseFloat(curCSSLeft) || 0;
            }
            if (isFunction(options)) {
                options = options.call(elem, i, jQuery.extend({}, curOffset));
            }
            if (options.top != null) {
                props.top = options.top - curOffset.top + curTop;
            }
            if (options.left != null) {
                props.left = options.left - curOffset.left + curLeft;
            }
            if ("using" in options) {
                options.using.call(elem, props);
            } else {
                if (typeof props.top === "number") {
                    props.top += "px";
                }
                if (typeof props.left === "number") {
                    props.left += "px";
                }
                curElem.css(props);
            }
        }
    };
    jQuery.fn.extend({
        offset: function(options) {
            if (arguments.length) {
                return options === undefined ? this : this.each(function(i) {
                    jQuery.offset.setOffset(this, options, i);
                });
            }
            var rect, win, elem = this[0];
            if (!elem) {
                return;
            }
            if (!elem.getClientRects().length) {
                return {
                    top: 0,
                    left: 0
                };
            }
            rect = elem.getBoundingClientRect();
            win = elem.ownerDocument.defaultView;
            return {
                top: rect.top + win.pageYOffset,
                left: rect.left + win.pageXOffset
            };
        },
        position: function() {
            if (!this[0]) {
                return;
            }
            var offsetParent, offset, doc, elem = this[0], parentOffset = {
                top: 0,
                left: 0
            };
            if (jQuery.css(elem, "position") === "fixed") {
                offset = elem.getBoundingClientRect();
            } else {
                offset = this.offset();
                doc = elem.ownerDocument;
                offsetParent = elem.offsetParent || doc.documentElement;
                while (offsetParent && (offsetParent === doc.body || offsetParent === doc.documentElement) && jQuery.css(offsetParent, "position") === "static") {
                    offsetParent = offsetParent.parentNode;
                }
                if (offsetParent && offsetParent !== elem && offsetParent.nodeType === 1) {
                    parentOffset = jQuery(offsetParent).offset();
                    parentOffset.top += jQuery.css(offsetParent, "borderTopWidth", true);
                    parentOffset.left += jQuery.css(offsetParent, "borderLeftWidth", true);
                }
            }
            return {
                top: offset.top - parentOffset.top - jQuery.css(elem, "marginTop", true),
                left: offset.left - parentOffset.left - jQuery.css(elem, "marginLeft", true)
            };
        },
        offsetParent: function() {
            return this.map(function() {
                var offsetParent = this.offsetParent;
                while (offsetParent && jQuery.css(offsetParent, "position") === "static") {
                    offsetParent = offsetParent.offsetParent;
                }
                return offsetParent || documentElement;
            });
        }
    });
    jQuery.each({
        scrollLeft: "pageXOffset",
        scrollTop: "pageYOffset"
    }, function(method, prop) {
        var top = "pageYOffset" === prop;
        jQuery.fn[method] = function(val) {
            return access(this, function(elem, method, val) {
                var win;
                if (isWindow(elem)) {
                    win = elem;
                } else if (elem.nodeType === 9) {
                    win = elem.defaultView;
                }
                if (val === undefined) {
                    return win ? win[prop] : elem[method];
                }
                if (win) {
                    win.scrollTo(!top ? val : win.pageXOffset, top ? val : win.pageYOffset);
                } else {
                    elem[method] = val;
                }
            }, method, val, arguments.length);
        };
    });
    jQuery.each([ "top", "left" ], function(_i, prop) {
        jQuery.cssHooks[prop] = addGetHookIf(support.pixelPosition, function(elem, computed) {
            if (computed) {
                computed = curCSS(elem, prop);
                return rnumnonpx.test(computed) ? jQuery(elem).position()[prop] + "px" : computed;
            }
        });
    });
    jQuery.each({
        Height: "height",
        Width: "width"
    }, function(name, type) {
        jQuery.each({
            padding: "inner" + name,
            content: type,
            "": "outer" + name
        }, function(defaultExtra, funcName) {
            jQuery.fn[funcName] = function(margin, value) {
                var chainable = arguments.length && (defaultExtra || typeof margin !== "boolean"), extra = defaultExtra || (margin === true || value === true ? "margin" : "border");
                return access(this, function(elem, type, value) {
                    var doc;
                    if (isWindow(elem)) {
                        return funcName.indexOf("outer") === 0 ? elem["inner" + name] : elem.document.documentElement["client" + name];
                    }
                    if (elem.nodeType === 9) {
                        doc = elem.documentElement;
                        return Math.max(elem.body["scroll" + name], doc["scroll" + name], elem.body["offset" + name], doc["offset" + name], doc["client" + name]);
                    }
                    return value === undefined ? jQuery.css(elem, type, extra) : jQuery.style(elem, type, value, extra);
                }, type, chainable ? margin : undefined, chainable);
            };
        });
    });
    jQuery.each([ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function(_i, type) {
        jQuery.fn[type] = function(fn) {
            return this.on(type, fn);
        };
    });
    jQuery.fn.extend({
        bind: function(types, data, fn) {
            return this.on(types, null, data, fn);
        },
        unbind: function(types, fn) {
            return this.off(types, null, fn);
        },
        delegate: function(selector, types, data, fn) {
            return this.on(types, selector, data, fn);
        },
        undelegate: function(selector, types, fn) {
            return arguments.length === 1 ? this.off(selector, "**") : this.off(types, selector || "**", fn);
        },
        hover: function(fnOver, fnOut) {
            return this.mouseenter(fnOver).mouseleave(fnOut || fnOver);
        }
    });
    jQuery.each(("blur focus focusin focusout resize scroll click dblclick " + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + "change select submit keydown keypress keyup contextmenu").split(" "), function(_i, name) {
        jQuery.fn[name] = function(data, fn) {
            return arguments.length > 0 ? this.on(name, null, data, fn) : this.trigger(name);
        };
    });
    var rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;
    jQuery.proxy = function(fn, context) {
        var tmp, args, proxy;
        if (typeof context === "string") {
            tmp = fn[context];
            context = fn;
            fn = tmp;
        }
        if (!isFunction(fn)) {
            return undefined;
        }
        args = slice.call(arguments, 2);
        proxy = function() {
            return fn.apply(context || this, args.concat(slice.call(arguments)));
        };
        proxy.guid = fn.guid = fn.guid || jQuery.guid++;
        return proxy;
    };
    jQuery.holdReady = function(hold) {
        if (hold) {
            jQuery.readyWait++;
        } else {
            jQuery.ready(true);
        }
    };
    jQuery.isArray = Array.isArray;
    jQuery.parseJSON = JSON.parse;
    jQuery.nodeName = nodeName;
    jQuery.isFunction = isFunction;
    jQuery.isWindow = isWindow;
    jQuery.camelCase = camelCase;
    jQuery.type = toType;
    jQuery.now = Date.now;
    jQuery.isNumeric = function(obj) {
        var type = jQuery.type(obj);
        return (type === "number" || type === "string") && !isNaN(obj - parseFloat(obj));
    };
    jQuery.trim = function(text) {
        return text == null ? "" : (text + "").replace(rtrim, "");
    };
    if (typeof define === "function" && define.amd) {
        define("jquery", [], function() {
            return jQuery;
        });
    }
    var _jQuery = window.jQuery, _$ = window.$;
    jQuery.noConflict = function(deep) {
        if (window.$ === jQuery) {
            window.$ = _$;
        }
        if (deep && window.jQuery === jQuery) {
            window.jQuery = _jQuery;
        }
        return jQuery;
    };
    if (typeof noGlobal === "undefined") {
        window.jQuery = window.$ = jQuery;
    }
    return jQuery;
});

(function(factory) {
    "use strict";
    if (typeof define === "function" && define.amd) {
        define([ "jquery" ], factory);
    } else {
        factory(jQuery);
    }
})(function($) {
    "use strict";
    $.ui = $.ui || {};
    var version = $.ui.version = "1.13.1";
    var widgetUuid = 0;
    var widgetHasOwnProperty = Array.prototype.hasOwnProperty;
    var widgetSlice = Array.prototype.slice;
    $.cleanData = function(orig) {
        return function(elems) {
            var events, elem, i;
            for (i = 0; (elem = elems[i]) != null; i++) {
                events = $._data(elem, "events");
                if (events && events.remove) {
                    $(elem).triggerHandler("remove");
                }
            }
            orig(elems);
        };
    }($.cleanData);
    $.widget = function(name, base, prototype) {
        var existingConstructor, constructor, basePrototype;
        var proxiedPrototype = {};
        var namespace = name.split(".")[0];
        name = name.split(".")[1];
        var fullName = namespace + "-" + name;
        if (!prototype) {
            prototype = base;
            base = $.Widget;
        }
        if (Array.isArray(prototype)) {
            prototype = $.extend.apply(null, [ {} ].concat(prototype));
        }
        $.expr.pseudos[fullName.toLowerCase()] = function(elem) {
            return !!$.data(elem, fullName);
        };
        $[namespace] = $[namespace] || {};
        existingConstructor = $[namespace][name];
        constructor = $[namespace][name] = function(options, element) {
            if (!this || !this._createWidget) {
                return new constructor(options, element);
            }
            if (arguments.length) {
                this._createWidget(options, element);
            }
        };
        $.extend(constructor, existingConstructor, {
            version: prototype.version,
            _proto: $.extend({}, prototype),
            _childConstructors: []
        });
        basePrototype = new base();
        basePrototype.options = $.widget.extend({}, basePrototype.options);
        $.each(prototype, function(prop, value) {
            if (typeof value !== "function") {
                proxiedPrototype[prop] = value;
                return;
            }
            proxiedPrototype[prop] = function() {
                function _super() {
                    return base.prototype[prop].apply(this, arguments);
                }
                function _superApply(args) {
                    return base.prototype[prop].apply(this, args);
                }
                return function() {
                    var __super = this._super;
                    var __superApply = this._superApply;
                    var returnValue;
                    this._super = _super;
                    this._superApply = _superApply;
                    returnValue = value.apply(this, arguments);
                    this._super = __super;
                    this._superApply = __superApply;
                    return returnValue;
                };
            }();
        });
        constructor.prototype = $.widget.extend(basePrototype, {
            widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix || name : name
        }, proxiedPrototype, {
            constructor: constructor,
            namespace: namespace,
            widgetName: name,
            widgetFullName: fullName
        });
        if (existingConstructor) {
            $.each(existingConstructor._childConstructors, function(i, child) {
                var childPrototype = child.prototype;
                $.widget(childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto);
            });
            delete existingConstructor._childConstructors;
        } else {
            base._childConstructors.push(constructor);
        }
        $.widget.bridge(name, constructor);
        return constructor;
    };
    $.widget.extend = function(target) {
        var input = widgetSlice.call(arguments, 1);
        var inputIndex = 0;
        var inputLength = input.length;
        var key;
        var value;
        for (;inputIndex < inputLength; inputIndex++) {
            for (key in input[inputIndex]) {
                value = input[inputIndex][key];
                if (widgetHasOwnProperty.call(input[inputIndex], key) && value !== undefined) {
                    if ($.isPlainObject(value)) {
                        target[key] = $.isPlainObject(target[key]) ? $.widget.extend({}, target[key], value) : $.widget.extend({}, value);
                    } else {
                        target[key] = value;
                    }
                }
            }
        }
        return target;
    };
    $.widget.bridge = function(name, object) {
        var fullName = object.prototype.widgetFullName || name;
        $.fn[name] = function(options) {
            var isMethodCall = typeof options === "string";
            var args = widgetSlice.call(arguments, 1);
            var returnValue = this;
            if (isMethodCall) {
                if (!this.length && options === "instance") {
                    returnValue = undefined;
                } else {
                    this.each(function() {
                        var methodValue;
                        var instance = $.data(this, fullName);
                        if (options === "instance") {
                            returnValue = instance;
                            return false;
                        }
                        if (!instance) {
                            return $.error("cannot call methods on " + name + " prior to initialization; " + "attempted to call method '" + options + "'");
                        }
                        if (typeof instance[options] !== "function" || options.charAt(0) === "_") {
                            return $.error("no such method '" + options + "' for " + name + " widget instance");
                        }
                        methodValue = instance[options].apply(instance, args);
                        if (methodValue !== instance && methodValue !== undefined) {
                            returnValue = methodValue && methodValue.jquery ? returnValue.pushStack(methodValue.get()) : methodValue;
                            return false;
                        }
                    });
                }
            } else {
                if (args.length) {
                    options = $.widget.extend.apply(null, [ options ].concat(args));
                }
                this.each(function() {
                    var instance = $.data(this, fullName);
                    if (instance) {
                        instance.option(options || {});
                        if (instance._init) {
                            instance._init();
                        }
                    } else {
                        $.data(this, fullName, new object(options, this));
                    }
                });
            }
            return returnValue;
        };
    };
    $.Widget = function() {};
    $.Widget._childConstructors = [];
    $.Widget.prototype = {
        widgetName: "widget",
        widgetEventPrefix: "",
        defaultElement: "<div>",
        options: {
            classes: {},
            disabled: false,
            create: null
        },
        _createWidget: function(options, element) {
            element = $(element || this.defaultElement || this)[0];
            this.element = $(element);
            this.uuid = widgetUuid++;
            this.eventNamespace = "." + this.widgetName + this.uuid;
            this.bindings = $();
            this.hoverable = $();
            this.focusable = $();
            this.classesElementLookup = {};
            if (element !== this) {
                $.data(element, this.widgetFullName, this);
                this._on(true, this.element, {
                    remove: function(event) {
                        if (event.target === element) {
                            this.destroy();
                        }
                    }
                });
                this.document = $(element.style ? element.ownerDocument : element.document || element);
                this.window = $(this.document[0].defaultView || this.document[0].parentWindow);
            }
            this.options = $.widget.extend({}, this.options, this._getCreateOptions(), options);
            this._create();
            if (this.options.disabled) {
                this._setOptionDisabled(this.options.disabled);
            }
            this._trigger("create", null, this._getCreateEventData());
            this._init();
        },
        _getCreateOptions: function() {
            return {};
        },
        _getCreateEventData: $.noop,
        _create: $.noop,
        _init: $.noop,
        destroy: function() {
            var that = this;
            this._destroy();
            $.each(this.classesElementLookup, function(key, value) {
                that._removeClass(value, key);
            });
            this.element.off(this.eventNamespace).removeData(this.widgetFullName);
            this.widget().off(this.eventNamespace).removeAttr("aria-disabled");
            this.bindings.off(this.eventNamespace);
        },
        _destroy: $.noop,
        widget: function() {
            return this.element;
        },
        option: function(key, value) {
            var options = key;
            var parts;
            var curOption;
            var i;
            if (arguments.length === 0) {
                return $.widget.extend({}, this.options);
            }
            if (typeof key === "string") {
                options = {};
                parts = key.split(".");
                key = parts.shift();
                if (parts.length) {
                    curOption = options[key] = $.widget.extend({}, this.options[key]);
                    for (i = 0; i < parts.length - 1; i++) {
                        curOption[parts[i]] = curOption[parts[i]] || {};
                        curOption = curOption[parts[i]];
                    }
                    key = parts.pop();
                    if (arguments.length === 1) {
                        return curOption[key] === undefined ? null : curOption[key];
                    }
                    curOption[key] = value;
                } else {
                    if (arguments.length === 1) {
                        return this.options[key] === undefined ? null : this.options[key];
                    }
                    options[key] = value;
                }
            }
            this._setOptions(options);
            return this;
        },
        _setOptions: function(options) {
            var key;
            for (key in options) {
                this._setOption(key, options[key]);
            }
            return this;
        },
        _setOption: function(key, value) {
            if (key === "classes") {
                this._setOptionClasses(value);
            }
            this.options[key] = value;
            if (key === "disabled") {
                this._setOptionDisabled(value);
            }
            return this;
        },
        _setOptionClasses: function(value) {
            var classKey, elements, currentElements;
            for (classKey in value) {
                currentElements = this.classesElementLookup[classKey];
                if (value[classKey] === this.options.classes[classKey] || !currentElements || !currentElements.length) {
                    continue;
                }
                elements = $(currentElements.get());
                this._removeClass(currentElements, classKey);
                elements.addClass(this._classes({
                    element: elements,
                    keys: classKey,
                    classes: value,
                    add: true
                }));
            }
        },
        _setOptionDisabled: function(value) {
            this._toggleClass(this.widget(), this.widgetFullName + "-disabled", null, !!value);
            if (value) {
                this._removeClass(this.hoverable, null, "ui-state-hover");
                this._removeClass(this.focusable, null, "ui-state-focus");
            }
        },
        enable: function() {
            return this._setOptions({
                disabled: false
            });
        },
        disable: function() {
            return this._setOptions({
                disabled: true
            });
        },
        _classes: function(options) {
            var full = [];
            var that = this;
            options = $.extend({
                element: this.element,
                classes: this.options.classes || {}
            }, options);
            function bindRemoveEvent() {
                var nodesToBind = [];
                options.element.each(function(_, element) {
                    var isTracked = $.map(that.classesElementLookup, function(elements) {
                        return elements;
                    }).some(function(elements) {
                        return elements.is(element);
                    });
                    if (!isTracked) {
                        nodesToBind.push(element);
                    }
                });
                that._on($(nodesToBind), {
                    remove: "_untrackClassesElement"
                });
            }
            function processClassString(classes, checkOption) {
                var current, i;
                for (i = 0; i < classes.length; i++) {
                    current = that.classesElementLookup[classes[i]] || $();
                    if (options.add) {
                        bindRemoveEvent();
                        current = $($.uniqueSort(current.get().concat(options.element.get())));
                    } else {
                        current = $(current.not(options.element).get());
                    }
                    that.classesElementLookup[classes[i]] = current;
                    full.push(classes[i]);
                    if (checkOption && options.classes[classes[i]]) {
                        full.push(options.classes[classes[i]]);
                    }
                }
            }
            if (options.keys) {
                processClassString(options.keys.match(/\S+/g) || [], true);
            }
            if (options.extra) {
                processClassString(options.extra.match(/\S+/g) || []);
            }
            return full.join(" ");
        },
        _untrackClassesElement: function(event) {
            var that = this;
            $.each(that.classesElementLookup, function(key, value) {
                if ($.inArray(event.target, value) !== -1) {
                    that.classesElementLookup[key] = $(value.not(event.target).get());
                }
            });
            this._off($(event.target));
        },
        _removeClass: function(element, keys, extra) {
            return this._toggleClass(element, keys, extra, false);
        },
        _addClass: function(element, keys, extra) {
            return this._toggleClass(element, keys, extra, true);
        },
        _toggleClass: function(element, keys, extra, add) {
            add = typeof add === "boolean" ? add : extra;
            var shift = typeof element === "string" || element === null, options = {
                extra: shift ? keys : extra,
                keys: shift ? element : keys,
                element: shift ? this.element : element,
                add: add
            };
            options.element.toggleClass(this._classes(options), add);
            return this;
        },
        _on: function(suppressDisabledCheck, element, handlers) {
            var delegateElement;
            var instance = this;
            if (typeof suppressDisabledCheck !== "boolean") {
                handlers = element;
                element = suppressDisabledCheck;
                suppressDisabledCheck = false;
            }
            if (!handlers) {
                handlers = element;
                element = this.element;
                delegateElement = this.widget();
            } else {
                element = delegateElement = $(element);
                this.bindings = this.bindings.add(element);
            }
            $.each(handlers, function(event, handler) {
                function handlerProxy() {
                    if (!suppressDisabledCheck && (instance.options.disabled === true || $(this).hasClass("ui-state-disabled"))) {
                        return;
                    }
                    return (typeof handler === "string" ? instance[handler] : handler).apply(instance, arguments);
                }
                if (typeof handler !== "string") {
                    handlerProxy.guid = handler.guid = handler.guid || handlerProxy.guid || $.guid++;
                }
                var match = event.match(/^([\w:-]*)\s*(.*)$/);
                var eventName = match[1] + instance.eventNamespace;
                var selector = match[2];
                if (selector) {
                    delegateElement.on(eventName, selector, handlerProxy);
                } else {
                    element.on(eventName, handlerProxy);
                }
            });
        },
        _off: function(element, eventName) {
            eventName = (eventName || "").split(" ").join(this.eventNamespace + " ") + this.eventNamespace;
            element.off(eventName);
            this.bindings = $(this.bindings.not(element).get());
            this.focusable = $(this.focusable.not(element).get());
            this.hoverable = $(this.hoverable.not(element).get());
        },
        _delay: function(handler, delay) {
            function handlerProxy() {
                return (typeof handler === "string" ? instance[handler] : handler).apply(instance, arguments);
            }
            var instance = this;
            return setTimeout(handlerProxy, delay || 0);
        },
        _hoverable: function(element) {
            this.hoverable = this.hoverable.add(element);
            this._on(element, {
                mouseenter: function(event) {
                    this._addClass($(event.currentTarget), null, "ui-state-hover");
                },
                mouseleave: function(event) {
                    this._removeClass($(event.currentTarget), null, "ui-state-hover");
                }
            });
        },
        _focusable: function(element) {
            this.focusable = this.focusable.add(element);
            this._on(element, {
                focusin: function(event) {
                    this._addClass($(event.currentTarget), null, "ui-state-focus");
                },
                focusout: function(event) {
                    this._removeClass($(event.currentTarget), null, "ui-state-focus");
                }
            });
        },
        _trigger: function(type, event, data) {
            var prop, orig;
            var callback = this.options[type];
            data = data || {};
            event = $.Event(event);
            event.type = (type === this.widgetEventPrefix ? type : this.widgetEventPrefix + type).toLowerCase();
            event.target = this.element[0];
            orig = event.originalEvent;
            if (orig) {
                for (prop in orig) {
                    if (!(prop in event)) {
                        event[prop] = orig[prop];
                    }
                }
            }
            this.element.trigger(event, data);
            return !(typeof callback === "function" && callback.apply(this.element[0], [ event ].concat(data)) === false || event.isDefaultPrevented());
        }
    };
    $.each({
        show: "fadeIn",
        hide: "fadeOut"
    }, function(method, defaultEffect) {
        $.Widget.prototype["_" + method] = function(element, options, callback) {
            if (typeof options === "string") {
                options = {
                    effect: options
                };
            }
            var hasOptions;
            var effectName = !options ? method : options === true || typeof options === "number" ? defaultEffect : options.effect || defaultEffect;
            options = options || {};
            if (typeof options === "number") {
                options = {
                    duration: options
                };
            } else if (options === true) {
                options = {};
            }
            hasOptions = !$.isEmptyObject(options);
            options.complete = callback;
            if (options.delay) {
                element.delay(options.delay);
            }
            if (hasOptions && $.effects && $.effects.effect[effectName]) {
                element[method](options);
            } else if (effectName !== method && element[effectName]) {
                element[effectName](options.duration, options.easing, callback);
            } else {
                element.queue(function(next) {
                    $(this)[method]();
                    if (callback) {
                        callback.call(element[0]);
                    }
                    next();
                });
            }
        };
    });
    var widget = $.widget;
    (function() {
        var cachedScrollbarWidth, max = Math.max, abs = Math.abs, rhorizontal = /left|center|right/, rvertical = /top|center|bottom/, roffset = /[\+\-]\d+(\.[\d]+)?%?/, rposition = /^\w+/, rpercent = /%$/, _position = $.fn.position;
        function getOffsets(offsets, width, height) {
            return [ parseFloat(offsets[0]) * (rpercent.test(offsets[0]) ? width / 100 : 1), parseFloat(offsets[1]) * (rpercent.test(offsets[1]) ? height / 100 : 1) ];
        }
        function parseCss(element, property) {
            return parseInt($.css(element, property), 10) || 0;
        }
        function isWindow(obj) {
            return obj != null && obj === obj.window;
        }
        function getDimensions(elem) {
            var raw = elem[0];
            if (raw.nodeType === 9) {
                return {
                    width: elem.width(),
                    height: elem.height(),
                    offset: {
                        top: 0,
                        left: 0
                    }
                };
            }
            if (isWindow(raw)) {
                return {
                    width: elem.width(),
                    height: elem.height(),
                    offset: {
                        top: elem.scrollTop(),
                        left: elem.scrollLeft()
                    }
                };
            }
            if (raw.preventDefault) {
                return {
                    width: 0,
                    height: 0,
                    offset: {
                        top: raw.pageY,
                        left: raw.pageX
                    }
                };
            }
            return {
                width: elem.outerWidth(),
                height: elem.outerHeight(),
                offset: elem.offset()
            };
        }
        $.position = {
            scrollbarWidth: function() {
                if (cachedScrollbarWidth !== undefined) {
                    return cachedScrollbarWidth;
                }
                var w1, w2, div = $("<div style=" + "'display:block;position:absolute;width:200px;height:200px;overflow:hidden;'>" + "<div style='height:300px;width:auto;'></div></div>"), innerDiv = div.children()[0];
                $("body").append(div);
                w1 = innerDiv.offsetWidth;
                div.css("overflow", "scroll");
                w2 = innerDiv.offsetWidth;
                if (w1 === w2) {
                    w2 = div[0].clientWidth;
                }
                div.remove();
                return cachedScrollbarWidth = w1 - w2;
            },
            getScrollInfo: function(within) {
                var overflowX = within.isWindow || within.isDocument ? "" : within.element.css("overflow-x"), overflowY = within.isWindow || within.isDocument ? "" : within.element.css("overflow-y"), hasOverflowX = overflowX === "scroll" || overflowX === "auto" && within.width < within.element[0].scrollWidth, hasOverflowY = overflowY === "scroll" || overflowY === "auto" && within.height < within.element[0].scrollHeight;
                return {
                    width: hasOverflowY ? $.position.scrollbarWidth() : 0,
                    height: hasOverflowX ? $.position.scrollbarWidth() : 0
                };
            },
            getWithinInfo: function(element) {
                var withinElement = $(element || window), isElemWindow = isWindow(withinElement[0]), isDocument = !!withinElement[0] && withinElement[0].nodeType === 9, hasOffset = !isElemWindow && !isDocument;
                return {
                    element: withinElement,
                    isWindow: isElemWindow,
                    isDocument: isDocument,
                    offset: hasOffset ? $(element).offset() : {
                        left: 0,
                        top: 0
                    },
                    scrollLeft: withinElement.scrollLeft(),
                    scrollTop: withinElement.scrollTop(),
                    width: withinElement.outerWidth(),
                    height: withinElement.outerHeight()
                };
            }
        };
        $.fn.position = function(options) {
            if (!options || !options.of) {
                return _position.apply(this, arguments);
            }
            options = $.extend({}, options);
            var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions, target = typeof options.of === "string" ? $(document).find(options.of) : $(options.of), within = $.position.getWithinInfo(options.within), scrollInfo = $.position.getScrollInfo(within), collision = (options.collision || "flip").split(" "), offsets = {};
            dimensions = getDimensions(target);
            if (target[0].preventDefault) {
                options.at = "left top";
            }
            targetWidth = dimensions.width;
            targetHeight = dimensions.height;
            targetOffset = dimensions.offset;
            basePosition = $.extend({}, targetOffset);
            $.each([ "my", "at" ], function() {
                var pos = (options[this] || "").split(" "), horizontalOffset, verticalOffset;
                if (pos.length === 1) {
                    pos = rhorizontal.test(pos[0]) ? pos.concat([ "center" ]) : rvertical.test(pos[0]) ? [ "center" ].concat(pos) : [ "center", "center" ];
                }
                pos[0] = rhorizontal.test(pos[0]) ? pos[0] : "center";
                pos[1] = rvertical.test(pos[1]) ? pos[1] : "center";
                horizontalOffset = roffset.exec(pos[0]);
                verticalOffset = roffset.exec(pos[1]);
                offsets[this] = [ horizontalOffset ? horizontalOffset[0] : 0, verticalOffset ? verticalOffset[0] : 0 ];
                options[this] = [ rposition.exec(pos[0])[0], rposition.exec(pos[1])[0] ];
            });
            if (collision.length === 1) {
                collision[1] = collision[0];
            }
            if (options.at[0] === "right") {
                basePosition.left += targetWidth;
            } else if (options.at[0] === "center") {
                basePosition.left += targetWidth / 2;
            }
            if (options.at[1] === "bottom") {
                basePosition.top += targetHeight;
            } else if (options.at[1] === "center") {
                basePosition.top += targetHeight / 2;
            }
            atOffset = getOffsets(offsets.at, targetWidth, targetHeight);
            basePosition.left += atOffset[0];
            basePosition.top += atOffset[1];
            return this.each(function() {
                var collisionPosition, using, elem = $(this), elemWidth = elem.outerWidth(), elemHeight = elem.outerHeight(), marginLeft = parseCss(this, "marginLeft"), marginTop = parseCss(this, "marginTop"), collisionWidth = elemWidth + marginLeft + parseCss(this, "marginRight") + scrollInfo.width, collisionHeight = elemHeight + marginTop + parseCss(this, "marginBottom") + scrollInfo.height, position = $.extend({}, basePosition), myOffset = getOffsets(offsets.my, elem.outerWidth(), elem.outerHeight());
                if (options.my[0] === "right") {
                    position.left -= elemWidth;
                } else if (options.my[0] === "center") {
                    position.left -= elemWidth / 2;
                }
                if (options.my[1] === "bottom") {
                    position.top -= elemHeight;
                } else if (options.my[1] === "center") {
                    position.top -= elemHeight / 2;
                }
                position.left += myOffset[0];
                position.top += myOffset[1];
                collisionPosition = {
                    marginLeft: marginLeft,
                    marginTop: marginTop
                };
                $.each([ "left", "top" ], function(i, dir) {
                    if ($.ui.position[collision[i]]) {
                        $.ui.position[collision[i]][dir](position, {
                            targetWidth: targetWidth,
                            targetHeight: targetHeight,
                            elemWidth: elemWidth,
                            elemHeight: elemHeight,
                            collisionPosition: collisionPosition,
                            collisionWidth: collisionWidth,
                            collisionHeight: collisionHeight,
                            offset: [ atOffset[0] + myOffset[0], atOffset[1] + myOffset[1] ],
                            my: options.my,
                            at: options.at,
                            within: within,
                            elem: elem
                        });
                    }
                });
                if (options.using) {
                    using = function(props) {
                        var left = targetOffset.left - position.left, right = left + targetWidth - elemWidth, top = targetOffset.top - position.top, bottom = top + targetHeight - elemHeight, feedback = {
                            target: {
                                element: target,
                                left: targetOffset.left,
                                top: targetOffset.top,
                                width: targetWidth,
                                height: targetHeight
                            },
                            element: {
                                element: elem,
                                left: position.left,
                                top: position.top,
                                width: elemWidth,
                                height: elemHeight
                            },
                            horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
                            vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
                        };
                        if (targetWidth < elemWidth && abs(left + right) < targetWidth) {
                            feedback.horizontal = "center";
                        }
                        if (targetHeight < elemHeight && abs(top + bottom) < targetHeight) {
                            feedback.vertical = "middle";
                        }
                        if (max(abs(left), abs(right)) > max(abs(top), abs(bottom))) {
                            feedback.important = "horizontal";
                        } else {
                            feedback.important = "vertical";
                        }
                        options.using.call(this, props, feedback);
                    };
                }
                elem.offset($.extend(position, {
                    using: using
                }));
            });
        };
        $.ui.position = {
            fit: {
                left: function(position, data) {
                    var within = data.within, withinOffset = within.isWindow ? within.scrollLeft : within.offset.left, outerWidth = within.width, collisionPosLeft = position.left - data.collisionPosition.marginLeft, overLeft = withinOffset - collisionPosLeft, overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset, newOverRight;
                    if (data.collisionWidth > outerWidth) {
                        if (overLeft > 0 && overRight <= 0) {
                            newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
                            position.left += overLeft - newOverRight;
                        } else if (overRight > 0 && overLeft <= 0) {
                            position.left = withinOffset;
                        } else {
                            if (overLeft > overRight) {
                                position.left = withinOffset + outerWidth - data.collisionWidth;
                            } else {
                                position.left = withinOffset;
                            }
                        }
                    } else if (overLeft > 0) {
                        position.left += overLeft;
                    } else if (overRight > 0) {
                        position.left -= overRight;
                    } else {
                        position.left = max(position.left - collisionPosLeft, position.left);
                    }
                },
                top: function(position, data) {
                    var within = data.within, withinOffset = within.isWindow ? within.scrollTop : within.offset.top, outerHeight = data.within.height, collisionPosTop = position.top - data.collisionPosition.marginTop, overTop = withinOffset - collisionPosTop, overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset, newOverBottom;
                    if (data.collisionHeight > outerHeight) {
                        if (overTop > 0 && overBottom <= 0) {
                            newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
                            position.top += overTop - newOverBottom;
                        } else if (overBottom > 0 && overTop <= 0) {
                            position.top = withinOffset;
                        } else {
                            if (overTop > overBottom) {
                                position.top = withinOffset + outerHeight - data.collisionHeight;
                            } else {
                                position.top = withinOffset;
                            }
                        }
                    } else if (overTop > 0) {
                        position.top += overTop;
                    } else if (overBottom > 0) {
                        position.top -= overBottom;
                    } else {
                        position.top = max(position.top - collisionPosTop, position.top);
                    }
                }
            },
            flip: {
                left: function(position, data) {
                    var within = data.within, withinOffset = within.offset.left + within.scrollLeft, outerWidth = within.width, offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left, collisionPosLeft = position.left - data.collisionPosition.marginLeft, overLeft = collisionPosLeft - offsetLeft, overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft, myOffset = data.my[0] === "left" ? -data.elemWidth : data.my[0] === "right" ? data.elemWidth : 0, atOffset = data.at[0] === "left" ? data.targetWidth : data.at[0] === "right" ? -data.targetWidth : 0, offset = -2 * data.offset[0], newOverRight, newOverLeft;
                    if (overLeft < 0) {
                        newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
                        if (newOverRight < 0 || newOverRight < abs(overLeft)) {
                            position.left += myOffset + atOffset + offset;
                        }
                    } else if (overRight > 0) {
                        newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
                        if (newOverLeft > 0 || abs(newOverLeft) < overRight) {
                            position.left += myOffset + atOffset + offset;
                        }
                    }
                },
                top: function(position, data) {
                    var within = data.within, withinOffset = within.offset.top + within.scrollTop, outerHeight = within.height, offsetTop = within.isWindow ? within.scrollTop : within.offset.top, collisionPosTop = position.top - data.collisionPosition.marginTop, overTop = collisionPosTop - offsetTop, overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop, top = data.my[1] === "top", myOffset = top ? -data.elemHeight : data.my[1] === "bottom" ? data.elemHeight : 0, atOffset = data.at[1] === "top" ? data.targetHeight : data.at[1] === "bottom" ? -data.targetHeight : 0, offset = -2 * data.offset[1], newOverTop, newOverBottom;
                    if (overTop < 0) {
                        newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
                        if (newOverBottom < 0 || newOverBottom < abs(overTop)) {
                            position.top += myOffset + atOffset + offset;
                        }
                    } else if (overBottom > 0) {
                        newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
                        if (newOverTop > 0 || abs(newOverTop) < overBottom) {
                            position.top += myOffset + atOffset + offset;
                        }
                    }
                }
            },
            flipfit: {
                left: function() {
                    $.ui.position.flip.left.apply(this, arguments);
                    $.ui.position.fit.left.apply(this, arguments);
                },
                top: function() {
                    $.ui.position.flip.top.apply(this, arguments);
                    $.ui.position.fit.top.apply(this, arguments);
                }
            }
        };
    })();
    var position = $.ui.position;
    var data = $.extend($.expr.pseudos, {
        data: $.expr.createPseudo ? $.expr.createPseudo(function(dataName) {
            return function(elem) {
                return !!$.data(elem, dataName);
            };
        }) : function(elem, i, match) {
            return !!$.data(elem, match[3]);
        }
    });
    var disableSelection = $.fn.extend({
        disableSelection: function() {
            var eventType = "onselectstart" in document.createElement("div") ? "selectstart" : "mousedown";
            return function() {
                return this.on(eventType + ".ui-disableSelection", function(event) {
                    event.preventDefault();
                });
            };
        }(),
        enableSelection: function() {
            return this.off(".ui-disableSelection");
        }
    });
    var jQuery = $;
    var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " + "borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor", class2type = {}, toString = class2type.toString, rplusequals = /^([\-+])=\s*(\d+\.?\d*)/, stringParsers = [ {
        re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
        parse: function(execResult) {
            return [ execResult[1], execResult[2], execResult[3], execResult[4] ];
        }
    }, {
        re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
        parse: function(execResult) {
            return [ execResult[1] * 2.55, execResult[2] * 2.55, execResult[3] * 2.55, execResult[4] ];
        }
    }, {
        re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})?/,
        parse: function(execResult) {
            return [ parseInt(execResult[1], 16), parseInt(execResult[2], 16), parseInt(execResult[3], 16), execResult[4] ? (parseInt(execResult[4], 16) / 255).toFixed(2) : 1 ];
        }
    }, {
        re: /#([a-f0-9])([a-f0-9])([a-f0-9])([a-f0-9])?/,
        parse: function(execResult) {
            return [ parseInt(execResult[1] + execResult[1], 16), parseInt(execResult[2] + execResult[2], 16), parseInt(execResult[3] + execResult[3], 16), execResult[4] ? (parseInt(execResult[4] + execResult[4], 16) / 255).toFixed(2) : 1 ];
        }
    }, {
        re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
        space: "hsla",
        parse: function(execResult) {
            return [ execResult[1], execResult[2] / 100, execResult[3] / 100, execResult[4] ];
        }
    } ], color = jQuery.Color = function(color, green, blue, alpha) {
        return new jQuery.Color.fn.parse(color, green, blue, alpha);
    }, spaces = {
        rgba: {
            props: {
                red: {
                    idx: 0,
                    type: "byte"
                },
                green: {
                    idx: 1,
                    type: "byte"
                },
                blue: {
                    idx: 2,
                    type: "byte"
                }
            }
        },
        hsla: {
            props: {
                hue: {
                    idx: 0,
                    type: "degrees"
                },
                saturation: {
                    idx: 1,
                    type: "percent"
                },
                lightness: {
                    idx: 2,
                    type: "percent"
                }
            }
        }
    }, propTypes = {
        byte: {
            floor: true,
            max: 255
        },
        percent: {
            max: 1
        },
        degrees: {
            mod: 360,
            floor: true
        }
    }, support = color.support = {}, supportElem = jQuery("<p>")[0], colors, each = jQuery.each;
    supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
    support.rgba = supportElem.style.backgroundColor.indexOf("rgba") > -1;
    each(spaces, function(spaceName, space) {
        space.cache = "_" + spaceName;
        space.props.alpha = {
            idx: 3,
            type: "percent",
            def: 1
        };
    });
    jQuery.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "), function(_i, name) {
        class2type["[object " + name + "]"] = name.toLowerCase();
    });
    function getType(obj) {
        if (obj == null) {
            return obj + "";
        }
        return typeof obj === "object" ? class2type[toString.call(obj)] || "object" : typeof obj;
    }
    function clamp(value, prop, allowEmpty) {
        var type = propTypes[prop.type] || {};
        if (value == null) {
            return allowEmpty || !prop.def ? null : prop.def;
        }
        value = type.floor ? ~~value : parseFloat(value);
        if (isNaN(value)) {
            return prop.def;
        }
        if (type.mod) {
            return (value + type.mod) % type.mod;
        }
        return Math.min(type.max, Math.max(0, value));
    }
    function stringParse(string) {
        var inst = color(), rgba = inst._rgba = [];
        string = string.toLowerCase();
        each(stringParsers, function(_i, parser) {
            var parsed, match = parser.re.exec(string), values = match && parser.parse(match), spaceName = parser.space || "rgba";
            if (values) {
                parsed = inst[spaceName](values);
                inst[spaces[spaceName].cache] = parsed[spaces[spaceName].cache];
                rgba = inst._rgba = parsed._rgba;
                return false;
            }
        });
        if (rgba.length) {
            if (rgba.join() === "0,0,0,0") {
                jQuery.extend(rgba, colors.transparent);
            }
            return inst;
        }
        return colors[string];
    }
    color.fn = jQuery.extend(color.prototype, {
        parse: function(red, green, blue, alpha) {
            if (red === undefined) {
                this._rgba = [ null, null, null, null ];
                return this;
            }
            if (red.jquery || red.nodeType) {
                red = jQuery(red).css(green);
                green = undefined;
            }
            var inst = this, type = getType(red), rgba = this._rgba = [];
            if (green !== undefined) {
                red = [ red, green, blue, alpha ];
                type = "array";
            }
            if (type === "string") {
                return this.parse(stringParse(red) || colors._default);
            }
            if (type === "array") {
                each(spaces.rgba.props, function(_key, prop) {
                    rgba[prop.idx] = clamp(red[prop.idx], prop);
                });
                return this;
            }
            if (type === "object") {
                if (red instanceof color) {
                    each(spaces, function(_spaceName, space) {
                        if (red[space.cache]) {
                            inst[space.cache] = red[space.cache].slice();
                        }
                    });
                } else {
                    each(spaces, function(_spaceName, space) {
                        var cache = space.cache;
                        each(space.props, function(key, prop) {
                            if (!inst[cache] && space.to) {
                                if (key === "alpha" || red[key] == null) {
                                    return;
                                }
                                inst[cache] = space.to(inst._rgba);
                            }
                            inst[cache][prop.idx] = clamp(red[key], prop, true);
                        });
                        if (inst[cache] && jQuery.inArray(null, inst[cache].slice(0, 3)) < 0) {
                            if (inst[cache][3] == null) {
                                inst[cache][3] = 1;
                            }
                            if (space.from) {
                                inst._rgba = space.from(inst[cache]);
                            }
                        }
                    });
                }
                return this;
            }
        },
        is: function(compare) {
            var is = color(compare), same = true, inst = this;
            each(spaces, function(_, space) {
                var localCache, isCache = is[space.cache];
                if (isCache) {
                    localCache = inst[space.cache] || space.to && space.to(inst._rgba) || [];
                    each(space.props, function(_, prop) {
                        if (isCache[prop.idx] != null) {
                            same = isCache[prop.idx] === localCache[prop.idx];
                            return same;
                        }
                    });
                }
                return same;
            });
            return same;
        },
        _space: function() {
            var used = [], inst = this;
            each(spaces, function(spaceName, space) {
                if (inst[space.cache]) {
                    used.push(spaceName);
                }
            });
            return used.pop();
        },
        transition: function(other, distance) {
            var end = color(other), spaceName = end._space(), space = spaces[spaceName], startColor = this.alpha() === 0 ? color("transparent") : this, start = startColor[space.cache] || space.to(startColor._rgba), result = start.slice();
            end = end[space.cache];
            each(space.props, function(_key, prop) {
                var index = prop.idx, startValue = start[index], endValue = end[index], type = propTypes[prop.type] || {};
                if (endValue === null) {
                    return;
                }
                if (startValue === null) {
                    result[index] = endValue;
                } else {
                    if (type.mod) {
                        if (endValue - startValue > type.mod / 2) {
                            startValue += type.mod;
                        } else if (startValue - endValue > type.mod / 2) {
                            startValue -= type.mod;
                        }
                    }
                    result[index] = clamp((endValue - startValue) * distance + startValue, prop);
                }
            });
            return this[spaceName](result);
        },
        blend: function(opaque) {
            if (this._rgba[3] === 1) {
                return this;
            }
            var rgb = this._rgba.slice(), a = rgb.pop(), blend = color(opaque)._rgba;
            return color(jQuery.map(rgb, function(v, i) {
                return (1 - a) * blend[i] + a * v;
            }));
        },
        toRgbaString: function() {
            var prefix = "rgba(", rgba = jQuery.map(this._rgba, function(v, i) {
                if (v != null) {
                    return v;
                }
                return i > 2 ? 1 : 0;
            });
            if (rgba[3] === 1) {
                rgba.pop();
                prefix = "rgb(";
            }
            return prefix + rgba.join() + ")";
        },
        toHslaString: function() {
            var prefix = "hsla(", hsla = jQuery.map(this.hsla(), function(v, i) {
                if (v == null) {
                    v = i > 2 ? 1 : 0;
                }
                if (i && i < 3) {
                    v = Math.round(v * 100) + "%";
                }
                return v;
            });
            if (hsla[3] === 1) {
                hsla.pop();
                prefix = "hsl(";
            }
            return prefix + hsla.join() + ")";
        },
        toHexString: function(includeAlpha) {
            var rgba = this._rgba.slice(), alpha = rgba.pop();
            if (includeAlpha) {
                rgba.push(~~(alpha * 255));
            }
            return "#" + jQuery.map(rgba, function(v) {
                v = (v || 0).toString(16);
                return v.length === 1 ? "0" + v : v;
            }).join("");
        },
        toString: function() {
            return this._rgba[3] === 0 ? "transparent" : this.toRgbaString();
        }
    });
    color.fn.parse.prototype = color.fn;
    function hue2rgb(p, q, h) {
        h = (h + 1) % 1;
        if (h * 6 < 1) {
            return p + (q - p) * h * 6;
        }
        if (h * 2 < 1) {
            return q;
        }
        if (h * 3 < 2) {
            return p + (q - p) * (2 / 3 - h) * 6;
        }
        return p;
    }
    spaces.hsla.to = function(rgba) {
        if (rgba[0] == null || rgba[1] == null || rgba[2] == null) {
            return [ null, null, null, rgba[3] ];
        }
        var r = rgba[0] / 255, g = rgba[1] / 255, b = rgba[2] / 255, a = rgba[3], max = Math.max(r, g, b), min = Math.min(r, g, b), diff = max - min, add = max + min, l = add * .5, h, s;
        if (min === max) {
            h = 0;
        } else if (r === max) {
            h = 60 * (g - b) / diff + 360;
        } else if (g === max) {
            h = 60 * (b - r) / diff + 120;
        } else {
            h = 60 * (r - g) / diff + 240;
        }
        if (diff === 0) {
            s = 0;
        } else if (l <= .5) {
            s = diff / add;
        } else {
            s = diff / (2 - add);
        }
        return [ Math.round(h) % 360, s, l, a == null ? 1 : a ];
    };
    spaces.hsla.from = function(hsla) {
        if (hsla[0] == null || hsla[1] == null || hsla[2] == null) {
            return [ null, null, null, hsla[3] ];
        }
        var h = hsla[0] / 360, s = hsla[1], l = hsla[2], a = hsla[3], q = l <= .5 ? l * (1 + s) : l + s - l * s, p = 2 * l - q;
        return [ Math.round(hue2rgb(p, q, h + 1 / 3) * 255), Math.round(hue2rgb(p, q, h) * 255), Math.round(hue2rgb(p, q, h - 1 / 3) * 255), a ];
    };
    each(spaces, function(spaceName, space) {
        var props = space.props, cache = space.cache, to = space.to, from = space.from;
        color.fn[spaceName] = function(value) {
            if (to && !this[cache]) {
                this[cache] = to(this._rgba);
            }
            if (value === undefined) {
                return this[cache].slice();
            }
            var ret, type = getType(value), arr = type === "array" || type === "object" ? value : arguments, local = this[cache].slice();
            each(props, function(key, prop) {
                var val = arr[type === "object" ? key : prop.idx];
                if (val == null) {
                    val = local[prop.idx];
                }
                local[prop.idx] = clamp(val, prop);
            });
            if (from) {
                ret = color(from(local));
                ret[cache] = local;
                return ret;
            } else {
                return color(local);
            }
        };
        each(props, function(key, prop) {
            if (color.fn[key]) {
                return;
            }
            color.fn[key] = function(value) {
                var local, cur, match, fn, vtype = getType(value);
                if (key === "alpha") {
                    fn = this._hsla ? "hsla" : "rgba";
                } else {
                    fn = spaceName;
                }
                local = this[fn]();
                cur = local[prop.idx];
                if (vtype === "undefined") {
                    return cur;
                }
                if (vtype === "function") {
                    value = value.call(this, cur);
                    vtype = getType(value);
                }
                if (value == null && prop.empty) {
                    return this;
                }
                if (vtype === "string") {
                    match = rplusequals.exec(value);
                    if (match) {
                        value = cur + parseFloat(match[2]) * (match[1] === "+" ? 1 : -1);
                    }
                }
                local[prop.idx] = value;
                return this[fn](local);
            };
        });
    });
    color.hook = function(hook) {
        var hooks = hook.split(" ");
        each(hooks, function(_i, hook) {
            jQuery.cssHooks[hook] = {
                set: function(elem, value) {
                    var parsed, curElem, backgroundColor = "";
                    if (value !== "transparent" && (getType(value) !== "string" || (parsed = stringParse(value)))) {
                        value = color(parsed || value);
                        if (!support.rgba && value._rgba[3] !== 1) {
                            curElem = hook === "backgroundColor" ? elem.parentNode : elem;
                            while ((backgroundColor === "" || backgroundColor === "transparent") && curElem && curElem.style) {
                                try {
                                    backgroundColor = jQuery.css(curElem, "backgroundColor");
                                    curElem = curElem.parentNode;
                                } catch (e) {}
                            }
                            value = value.blend(backgroundColor && backgroundColor !== "transparent" ? backgroundColor : "_default");
                        }
                        value = value.toRgbaString();
                    }
                    try {
                        elem.style[hook] = value;
                    } catch (e) {}
                }
            };
            jQuery.fx.step[hook] = function(fx) {
                if (!fx.colorInit) {
                    fx.start = color(fx.elem, hook);
                    fx.end = color(fx.end);
                    fx.colorInit = true;
                }
                jQuery.cssHooks[hook].set(fx.elem, fx.start.transition(fx.end, fx.pos));
            };
        });
    };
    color.hook(stepHooks);
    jQuery.cssHooks.borderColor = {
        expand: function(value) {
            var expanded = {};
            each([ "Top", "Right", "Bottom", "Left" ], function(_i, part) {
                expanded["border" + part + "Color"] = value;
            });
            return expanded;
        }
    };
    colors = jQuery.Color.names = {
        aqua: "#00ffff",
        black: "#000000",
        blue: "#0000ff",
        fuchsia: "#ff00ff",
        gray: "#808080",
        green: "#008000",
        lime: "#00ff00",
        maroon: "#800000",
        navy: "#000080",
        olive: "#808000",
        purple: "#800080",
        red: "#ff0000",
        silver: "#c0c0c0",
        teal: "#008080",
        white: "#ffffff",
        yellow: "#ffff00",
        transparent: [ null, null, null, 0 ],
        _default: "#ffffff"
    };
    var dataSpace = "ui-effects-", dataSpaceStyle = "ui-effects-style", dataSpaceAnimated = "ui-effects-animated";
    $.effects = {
        effect: {}
    };
    (function() {
        var classAnimationActions = [ "add", "remove", "toggle" ], shorthandStyles = {
            border: 1,
            borderBottom: 1,
            borderColor: 1,
            borderLeft: 1,
            borderRight: 1,
            borderTop: 1,
            borderWidth: 1,
            margin: 1,
            padding: 1
        };
        $.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function(_, prop) {
            $.fx.step[prop] = function(fx) {
                if (fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr) {
                    jQuery.style(fx.elem, prop, fx.end);
                    fx.setAttr = true;
                }
            };
        });
        function camelCase(string) {
            return string.replace(/-([\da-z])/gi, function(all, letter) {
                return letter.toUpperCase();
            });
        }
        function getElementStyles(elem) {
            var key, len, style = elem.ownerDocument.defaultView ? elem.ownerDocument.defaultView.getComputedStyle(elem, null) : elem.currentStyle, styles = {};
            if (style && style.length && style[0] && style[style[0]]) {
                len = style.length;
                while (len--) {
                    key = style[len];
                    if (typeof style[key] === "string") {
                        styles[camelCase(key)] = style[key];
                    }
                }
            } else {
                for (key in style) {
                    if (typeof style[key] === "string") {
                        styles[key] = style[key];
                    }
                }
            }
            return styles;
        }
        function styleDifference(oldStyle, newStyle) {
            var diff = {}, name, value;
            for (name in newStyle) {
                value = newStyle[name];
                if (oldStyle[name] !== value) {
                    if (!shorthandStyles[name]) {
                        if ($.fx.step[name] || !isNaN(parseFloat(value))) {
                            diff[name] = value;
                        }
                    }
                }
            }
            return diff;
        }
        if (!$.fn.addBack) {
            $.fn.addBack = function(selector) {
                return this.add(selector == null ? this.prevObject : this.prevObject.filter(selector));
            };
        }
        $.effects.animateClass = function(value, duration, easing, callback) {
            var o = $.speed(duration, easing, callback);
            return this.queue(function() {
                var animated = $(this), baseClass = animated.attr("class") || "", applyClassChange, allAnimations = o.children ? animated.find("*").addBack() : animated;
                allAnimations = allAnimations.map(function() {
                    var el = $(this);
                    return {
                        el: el,
                        start: getElementStyles(this)
                    };
                });
                applyClassChange = function() {
                    $.each(classAnimationActions, function(i, action) {
                        if (value[action]) {
                            animated[action + "Class"](value[action]);
                        }
                    });
                };
                applyClassChange();
                allAnimations = allAnimations.map(function() {
                    this.end = getElementStyles(this.el[0]);
                    this.diff = styleDifference(this.start, this.end);
                    return this;
                });
                animated.attr("class", baseClass);
                allAnimations = allAnimations.map(function() {
                    var styleInfo = this, dfd = $.Deferred(), opts = $.extend({}, o, {
                        queue: false,
                        complete: function() {
                            dfd.resolve(styleInfo);
                        }
                    });
                    this.el.animate(this.diff, opts);
                    return dfd.promise();
                });
                $.when.apply($, allAnimations.get()).done(function() {
                    applyClassChange();
                    $.each(arguments, function() {
                        var el = this.el;
                        $.each(this.diff, function(key) {
                            el.css(key, "");
                        });
                    });
                    o.complete.call(animated[0]);
                });
            });
        };
        $.fn.extend({
            addClass: function(orig) {
                return function(classNames, speed, easing, callback) {
                    return speed ? $.effects.animateClass.call(this, {
                        add: classNames
                    }, speed, easing, callback) : orig.apply(this, arguments);
                };
            }($.fn.addClass),
            removeClass: function(orig) {
                return function(classNames, speed, easing, callback) {
                    return arguments.length > 1 ? $.effects.animateClass.call(this, {
                        remove: classNames
                    }, speed, easing, callback) : orig.apply(this, arguments);
                };
            }($.fn.removeClass),
            toggleClass: function(orig) {
                return function(classNames, force, speed, easing, callback) {
                    if (typeof force === "boolean" || force === undefined) {
                        if (!speed) {
                            return orig.apply(this, arguments);
                        } else {
                            return $.effects.animateClass.call(this, force ? {
                                add: classNames
                            } : {
                                remove: classNames
                            }, speed, easing, callback);
                        }
                    } else {
                        return $.effects.animateClass.call(this, {
                            toggle: classNames
                        }, force, speed, easing);
                    }
                };
            }($.fn.toggleClass),
            switchClass: function(remove, add, speed, easing, callback) {
                return $.effects.animateClass.call(this, {
                    add: add,
                    remove: remove
                }, speed, easing, callback);
            }
        });
    })();
    (function() {
        if ($.expr && $.expr.pseudos && $.expr.pseudos.animated) {
            $.expr.pseudos.animated = function(orig) {
                return function(elem) {
                    return !!$(elem).data(dataSpaceAnimated) || orig(elem);
                };
            }($.expr.pseudos.animated);
        }
        if ($.uiBackCompat !== false) {
            $.extend($.effects, {
                save: function(element, set) {
                    var i = 0, length = set.length;
                    for (;i < length; i++) {
                        if (set[i] !== null) {
                            element.data(dataSpace + set[i], element[0].style[set[i]]);
                        }
                    }
                },
                restore: function(element, set) {
                    var val, i = 0, length = set.length;
                    for (;i < length; i++) {
                        if (set[i] !== null) {
                            val = element.data(dataSpace + set[i]);
                            element.css(set[i], val);
                        }
                    }
                },
                setMode: function(el, mode) {
                    if (mode === "toggle") {
                        mode = el.is(":hidden") ? "show" : "hide";
                    }
                    return mode;
                },
                createWrapper: function(element) {
                    if (element.parent().is(".ui-effects-wrapper")) {
                        return element.parent();
                    }
                    var props = {
                        width: element.outerWidth(true),
                        height: element.outerHeight(true),
                        float: element.css("float")
                    }, wrapper = $("<div></div>").addClass("ui-effects-wrapper").css({
                        fontSize: "100%",
                        background: "transparent",
                        border: "none",
                        margin: 0,
                        padding: 0
                    }), size = {
                        width: element.width(),
                        height: element.height()
                    }, active = document.activeElement;
                    try {
                        active.id;
                    } catch (e) {
                        active = document.body;
                    }
                    element.wrap(wrapper);
                    if (element[0] === active || $.contains(element[0], active)) {
                        $(active).trigger("focus");
                    }
                    wrapper = element.parent();
                    if (element.css("position") === "static") {
                        wrapper.css({
                            position: "relative"
                        });
                        element.css({
                            position: "relative"
                        });
                    } else {
                        $.extend(props, {
                            position: element.css("position"),
                            zIndex: element.css("z-index")
                        });
                        $.each([ "top", "left", "bottom", "right" ], function(i, pos) {
                            props[pos] = element.css(pos);
                            if (isNaN(parseInt(props[pos], 10))) {
                                props[pos] = "auto";
                            }
                        });
                        element.css({
                            position: "relative",
                            top: 0,
                            left: 0,
                            right: "auto",
                            bottom: "auto"
                        });
                    }
                    element.css(size);
                    return wrapper.css(props).show();
                },
                removeWrapper: function(element) {
                    var active = document.activeElement;
                    if (element.parent().is(".ui-effects-wrapper")) {
                        element.parent().replaceWith(element);
                        if (element[0] === active || $.contains(element[0], active)) {
                            $(active).trigger("focus");
                        }
                    }
                    return element;
                }
            });
        }
        $.extend($.effects, {
            version: "1.13.1",
            define: function(name, mode, effect) {
                if (!effect) {
                    effect = mode;
                    mode = "effect";
                }
                $.effects.effect[name] = effect;
                $.effects.effect[name].mode = mode;
                return effect;
            },
            scaledDimensions: function(element, percent, direction) {
                if (percent === 0) {
                    return {
                        height: 0,
                        width: 0,
                        outerHeight: 0,
                        outerWidth: 0
                    };
                }
                var x = direction !== "horizontal" ? (percent || 100) / 100 : 1, y = direction !== "vertical" ? (percent || 100) / 100 : 1;
                return {
                    height: element.height() * y,
                    width: element.width() * x,
                    outerHeight: element.outerHeight() * y,
                    outerWidth: element.outerWidth() * x
                };
            },
            clipToBox: function(animation) {
                return {
                    width: animation.clip.right - animation.clip.left,
                    height: animation.clip.bottom - animation.clip.top,
                    left: animation.clip.left,
                    top: animation.clip.top
                };
            },
            unshift: function(element, queueLength, count) {
                var queue = element.queue();
                if (queueLength > 1) {
                    queue.splice.apply(queue, [ 1, 0 ].concat(queue.splice(queueLength, count)));
                }
                element.dequeue();
            },
            saveStyle: function(element) {
                element.data(dataSpaceStyle, element[0].style.cssText);
            },
            restoreStyle: function(element) {
                element[0].style.cssText = element.data(dataSpaceStyle) || "";
                element.removeData(dataSpaceStyle);
            },
            mode: function(element, mode) {
                var hidden = element.is(":hidden");
                if (mode === "toggle") {
                    mode = hidden ? "show" : "hide";
                }
                if (hidden ? mode === "hide" : mode === "show") {
                    mode = "none";
                }
                return mode;
            },
            getBaseline: function(origin, original) {
                var y, x;
                switch (origin[0]) {
                  case "top":
                    y = 0;
                    break;

                  case "middle":
                    y = .5;
                    break;

                  case "bottom":
                    y = 1;
                    break;

                  default:
                    y = origin[0] / original.height;
                }
                switch (origin[1]) {
                  case "left":
                    x = 0;
                    break;

                  case "center":
                    x = .5;
                    break;

                  case "right":
                    x = 1;
                    break;

                  default:
                    x = origin[1] / original.width;
                }
                return {
                    x: x,
                    y: y
                };
            },
            createPlaceholder: function(element) {
                var placeholder, cssPosition = element.css("position"), position = element.position();
                element.css({
                    marginTop: element.css("marginTop"),
                    marginBottom: element.css("marginBottom"),
                    marginLeft: element.css("marginLeft"),
                    marginRight: element.css("marginRight")
                }).outerWidth(element.outerWidth()).outerHeight(element.outerHeight());
                if (/^(static|relative)/.test(cssPosition)) {
                    cssPosition = "absolute";
                    placeholder = $("<" + element[0].nodeName + ">").insertAfter(element).css({
                        display: /^(inline|ruby)/.test(element.css("display")) ? "inline-block" : "block",
                        visibility: "hidden",
                        marginTop: element.css("marginTop"),
                        marginBottom: element.css("marginBottom"),
                        marginLeft: element.css("marginLeft"),
                        marginRight: element.css("marginRight"),
                        float: element.css("float")
                    }).outerWidth(element.outerWidth()).outerHeight(element.outerHeight()).addClass("ui-effects-placeholder");
                    element.data(dataSpace + "placeholder", placeholder);
                }
                element.css({
                    position: cssPosition,
                    left: position.left,
                    top: position.top
                });
                return placeholder;
            },
            removePlaceholder: function(element) {
                var dataKey = dataSpace + "placeholder", placeholder = element.data(dataKey);
                if (placeholder) {
                    placeholder.remove();
                    element.removeData(dataKey);
                }
            },
            cleanUp: function(element) {
                $.effects.restoreStyle(element);
                $.effects.removePlaceholder(element);
            },
            setTransition: function(element, list, factor, value) {
                value = value || {};
                $.each(list, function(i, x) {
                    var unit = element.cssUnit(x);
                    if (unit[0] > 0) {
                        value[x] = unit[0] * factor + unit[1];
                    }
                });
                return value;
            }
        });
        function _normalizeArguments(effect, options, speed, callback) {
            if ($.isPlainObject(effect)) {
                options = effect;
                effect = effect.effect;
            }
            effect = {
                effect: effect
            };
            if (options == null) {
                options = {};
            }
            if (typeof options === "function") {
                callback = options;
                speed = null;
                options = {};
            }
            if (typeof options === "number" || $.fx.speeds[options]) {
                callback = speed;
                speed = options;
                options = {};
            }
            if (typeof speed === "function") {
                callback = speed;
                speed = null;
            }
            if (options) {
                $.extend(effect, options);
            }
            speed = speed || options.duration;
            effect.duration = $.fx.off ? 0 : typeof speed === "number" ? speed : speed in $.fx.speeds ? $.fx.speeds[speed] : $.fx.speeds._default;
            effect.complete = callback || options.complete;
            return effect;
        }
        function standardAnimationOption(option) {
            if (!option || typeof option === "number" || $.fx.speeds[option]) {
                return true;
            }
            if (typeof option === "string" && !$.effects.effect[option]) {
                return true;
            }
            if (typeof option === "function") {
                return true;
            }
            if (typeof option === "object" && !option.effect) {
                return true;
            }
            return false;
        }
        $.fn.extend({
            effect: function() {
                var args = _normalizeArguments.apply(this, arguments), effectMethod = $.effects.effect[args.effect], defaultMode = effectMethod.mode, queue = args.queue, queueName = queue || "fx", complete = args.complete, mode = args.mode, modes = [], prefilter = function(next) {
                    var el = $(this), normalizedMode = $.effects.mode(el, mode) || defaultMode;
                    el.data(dataSpaceAnimated, true);
                    modes.push(normalizedMode);
                    if (defaultMode && (normalizedMode === "show" || normalizedMode === defaultMode && normalizedMode === "hide")) {
                        el.show();
                    }
                    if (!defaultMode || normalizedMode !== "none") {
                        $.effects.saveStyle(el);
                    }
                    if (typeof next === "function") {
                        next();
                    }
                };
                if ($.fx.off || !effectMethod) {
                    if (mode) {
                        return this[mode](args.duration, complete);
                    } else {
                        return this.each(function() {
                            if (complete) {
                                complete.call(this);
                            }
                        });
                    }
                }
                function run(next) {
                    var elem = $(this);
                    function cleanup() {
                        elem.removeData(dataSpaceAnimated);
                        $.effects.cleanUp(elem);
                        if (args.mode === "hide") {
                            elem.hide();
                        }
                        done();
                    }
                    function done() {
                        if (typeof complete === "function") {
                            complete.call(elem[0]);
                        }
                        if (typeof next === "function") {
                            next();
                        }
                    }
                    args.mode = modes.shift();
                    if ($.uiBackCompat !== false && !defaultMode) {
                        if (elem.is(":hidden") ? mode === "hide" : mode === "show") {
                            elem[mode]();
                            done();
                        } else {
                            effectMethod.call(elem[0], args, done);
                        }
                    } else {
                        if (args.mode === "none") {
                            elem[mode]();
                            done();
                        } else {
                            effectMethod.call(elem[0], args, cleanup);
                        }
                    }
                }
                return queue === false ? this.each(prefilter).each(run) : this.queue(queueName, prefilter).queue(queueName, run);
            },
            show: function(orig) {
                return function(option) {
                    if (standardAnimationOption(option)) {
                        return orig.apply(this, arguments);
                    } else {
                        var args = _normalizeArguments.apply(this, arguments);
                        args.mode = "show";
                        return this.effect.call(this, args);
                    }
                };
            }($.fn.show),
            hide: function(orig) {
                return function(option) {
                    if (standardAnimationOption(option)) {
                        return orig.apply(this, arguments);
                    } else {
                        var args = _normalizeArguments.apply(this, arguments);
                        args.mode = "hide";
                        return this.effect.call(this, args);
                    }
                };
            }($.fn.hide),
            toggle: function(orig) {
                return function(option) {
                    if (standardAnimationOption(option) || typeof option === "boolean") {
                        return orig.apply(this, arguments);
                    } else {
                        var args = _normalizeArguments.apply(this, arguments);
                        args.mode = "toggle";
                        return this.effect.call(this, args);
                    }
                };
            }($.fn.toggle),
            cssUnit: function(key) {
                var style = this.css(key), val = [];
                $.each([ "em", "px", "%", "pt" ], function(i, unit) {
                    if (style.indexOf(unit) > 0) {
                        val = [ parseFloat(style), unit ];
                    }
                });
                return val;
            },
            cssClip: function(clipObj) {
                if (clipObj) {
                    return this.css("clip", "rect(" + clipObj.top + "px " + clipObj.right + "px " + clipObj.bottom + "px " + clipObj.left + "px)");
                }
                return parseClip(this.css("clip"), this);
            },
            transfer: function(options, done) {
                var element = $(this), target = $(options.to), targetFixed = target.css("position") === "fixed", body = $("body"), fixTop = targetFixed ? body.scrollTop() : 0, fixLeft = targetFixed ? body.scrollLeft() : 0, endPosition = target.offset(), animation = {
                    top: endPosition.top - fixTop,
                    left: endPosition.left - fixLeft,
                    height: target.innerHeight(),
                    width: target.innerWidth()
                }, startPosition = element.offset(), transfer = $("<div class='ui-effects-transfer'></div>");
                transfer.appendTo("body").addClass(options.className).css({
                    top: startPosition.top - fixTop,
                    left: startPosition.left - fixLeft,
                    height: element.innerHeight(),
                    width: element.innerWidth(),
                    position: targetFixed ? "fixed" : "absolute"
                }).animate(animation, options.duration, options.easing, function() {
                    transfer.remove();
                    if (typeof done === "function") {
                        done();
                    }
                });
            }
        });
        function parseClip(str, element) {
            var outerWidth = element.outerWidth(), outerHeight = element.outerHeight(), clipRegex = /^rect\((-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto)\)$/, values = clipRegex.exec(str) || [ "", 0, outerWidth, outerHeight, 0 ];
            return {
                top: parseFloat(values[1]) || 0,
                right: values[2] === "auto" ? outerWidth : parseFloat(values[2]),
                bottom: values[3] === "auto" ? outerHeight : parseFloat(values[3]),
                left: parseFloat(values[4]) || 0
            };
        }
        $.fx.step.clip = function(fx) {
            if (!fx.clipInit) {
                fx.start = $(fx.elem).cssClip();
                if (typeof fx.end === "string") {
                    fx.end = parseClip(fx.end, fx.elem);
                }
                fx.clipInit = true;
            }
            $(fx.elem).cssClip({
                top: fx.pos * (fx.end.top - fx.start.top) + fx.start.top,
                right: fx.pos * (fx.end.right - fx.start.right) + fx.start.right,
                bottom: fx.pos * (fx.end.bottom - fx.start.bottom) + fx.start.bottom,
                left: fx.pos * (fx.end.left - fx.start.left) + fx.start.left
            });
        };
    })();
    (function() {
        var baseEasings = {};
        $.each([ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function(i, name) {
            baseEasings[name] = function(p) {
                return Math.pow(p, i + 2);
            };
        });
        $.extend(baseEasings, {
            Sine: function(p) {
                return 1 - Math.cos(p * Math.PI / 2);
            },
            Circ: function(p) {
                return 1 - Math.sqrt(1 - p * p);
            },
            Elastic: function(p) {
                return p === 0 || p === 1 ? p : -Math.pow(2, 8 * (p - 1)) * Math.sin(((p - 1) * 80 - 7.5) * Math.PI / 15);
            },
            Back: function(p) {
                return p * p * (3 * p - 2);
            },
            Bounce: function(p) {
                var pow2, bounce = 4;
                while (p < ((pow2 = Math.pow(2, --bounce)) - 1) / 11) {}
                return 1 / Math.pow(4, 3 - bounce) - 7.5625 * Math.pow((pow2 * 3 - 2) / 22 - p, 2);
            }
        });
        $.each(baseEasings, function(name, easeIn) {
            $.easing["easeIn" + name] = easeIn;
            $.easing["easeOut" + name] = function(p) {
                return 1 - easeIn(1 - p);
            };
            $.easing["easeInOut" + name] = function(p) {
                return p < .5 ? easeIn(p * 2) / 2 : 1 - easeIn(p * -2 + 2) / 2;
            };
        });
    })();
    var effect = $.effects;
    var effectsEffectBlind = $.effects.define("blind", "hide", function(options, done) {
        var map = {
            up: [ "bottom", "top" ],
            vertical: [ "bottom", "top" ],
            down: [ "top", "bottom" ],
            left: [ "right", "left" ],
            horizontal: [ "right", "left" ],
            right: [ "left", "right" ]
        }, element = $(this), direction = options.direction || "up", start = element.cssClip(), animate = {
            clip: $.extend({}, start)
        }, placeholder = $.effects.createPlaceholder(element);
        animate.clip[map[direction][0]] = animate.clip[map[direction][1]];
        if (options.mode === "show") {
            element.cssClip(animate.clip);
            if (placeholder) {
                placeholder.css($.effects.clipToBox(animate));
            }
            animate.clip = start;
        }
        if (placeholder) {
            placeholder.animate($.effects.clipToBox(animate), options.duration, options.easing);
        }
        element.animate(animate, {
            queue: false,
            duration: options.duration,
            easing: options.easing,
            complete: done
        });
    });
    var effectsEffectBounce = $.effects.define("bounce", function(options, done) {
        var upAnim, downAnim, refValue, element = $(this), mode = options.mode, hide = mode === "hide", show = mode === "show", direction = options.direction || "up", distance = options.distance, times = options.times || 5, anims = times * 2 + (show || hide ? 1 : 0), speed = options.duration / anims, easing = options.easing, ref = direction === "up" || direction === "down" ? "top" : "left", motion = direction === "up" || direction === "left", i = 0, queuelen = element.queue().length;
        $.effects.createPlaceholder(element);
        refValue = element.css(ref);
        if (!distance) {
            distance = element[ref === "top" ? "outerHeight" : "outerWidth"]() / 3;
        }
        if (show) {
            downAnim = {
                opacity: 1
            };
            downAnim[ref] = refValue;
            element.css("opacity", 0).css(ref, motion ? -distance * 2 : distance * 2).animate(downAnim, speed, easing);
        }
        if (hide) {
            distance = distance / Math.pow(2, times - 1);
        }
        downAnim = {};
        downAnim[ref] = refValue;
        for (;i < times; i++) {
            upAnim = {};
            upAnim[ref] = (motion ? "-=" : "+=") + distance;
            element.animate(upAnim, speed, easing).animate(downAnim, speed, easing);
            distance = hide ? distance * 2 : distance / 2;
        }
        if (hide) {
            upAnim = {
                opacity: 0
            };
            upAnim[ref] = (motion ? "-=" : "+=") + distance;
            element.animate(upAnim, speed, easing);
        }
        element.queue(done);
        $.effects.unshift(element, queuelen, anims + 1);
    });
    var effectsEffectClip = $.effects.define("clip", "hide", function(options, done) {
        var start, animate = {}, element = $(this), direction = options.direction || "vertical", both = direction === "both", horizontal = both || direction === "horizontal", vertical = both || direction === "vertical";
        start = element.cssClip();
        animate.clip = {
            top: vertical ? (start.bottom - start.top) / 2 : start.top,
            right: horizontal ? (start.right - start.left) / 2 : start.right,
            bottom: vertical ? (start.bottom - start.top) / 2 : start.bottom,
            left: horizontal ? (start.right - start.left) / 2 : start.left
        };
        $.effects.createPlaceholder(element);
        if (options.mode === "show") {
            element.cssClip(animate.clip);
            animate.clip = start;
        }
        element.animate(animate, {
            queue: false,
            duration: options.duration,
            easing: options.easing,
            complete: done
        });
    });
    var effectsEffectDrop = $.effects.define("drop", "hide", function(options, done) {
        var distance, element = $(this), mode = options.mode, show = mode === "show", direction = options.direction || "left", ref = direction === "up" || direction === "down" ? "top" : "left", motion = direction === "up" || direction === "left" ? "-=" : "+=", oppositeMotion = motion === "+=" ? "-=" : "+=", animation = {
            opacity: 0
        };
        $.effects.createPlaceholder(element);
        distance = options.distance || element[ref === "top" ? "outerHeight" : "outerWidth"](true) / 2;
        animation[ref] = motion + distance;
        if (show) {
            element.css(animation);
            animation[ref] = oppositeMotion + distance;
            animation.opacity = 1;
        }
        element.animate(animation, {
            queue: false,
            duration: options.duration,
            easing: options.easing,
            complete: done
        });
    });
    var effectsEffectExplode = $.effects.define("explode", "hide", function(options, done) {
        var i, j, left, top, mx, my, rows = options.pieces ? Math.round(Math.sqrt(options.pieces)) : 3, cells = rows, element = $(this), mode = options.mode, show = mode === "show", offset = element.show().css("visibility", "hidden").offset(), width = Math.ceil(element.outerWidth() / cells), height = Math.ceil(element.outerHeight() / rows), pieces = [];
        function childComplete() {
            pieces.push(this);
            if (pieces.length === rows * cells) {
                animComplete();
            }
        }
        for (i = 0; i < rows; i++) {
            top = offset.top + i * height;
            my = i - (rows - 1) / 2;
            for (j = 0; j < cells; j++) {
                left = offset.left + j * width;
                mx = j - (cells - 1) / 2;
                element.clone().appendTo("body").wrap("<div></div>").css({
                    position: "absolute",
                    visibility: "visible",
                    left: -j * width,
                    top: -i * height
                }).parent().addClass("ui-effects-explode").css({
                    position: "absolute",
                    overflow: "hidden",
                    width: width,
                    height: height,
                    left: left + (show ? mx * width : 0),
                    top: top + (show ? my * height : 0),
                    opacity: show ? 0 : 1
                }).animate({
                    left: left + (show ? 0 : mx * width),
                    top: top + (show ? 0 : my * height),
                    opacity: show ? 1 : 0
                }, options.duration || 500, options.easing, childComplete);
            }
        }
        function animComplete() {
            element.css({
                visibility: "visible"
            });
            $(pieces).remove();
            done();
        }
    });
    var effectsEffectFade = $.effects.define("fade", "toggle", function(options, done) {
        var show = options.mode === "show";
        $(this).css("opacity", show ? 0 : 1).animate({
            opacity: show ? 1 : 0
        }, {
            queue: false,
            duration: options.duration,
            easing: options.easing,
            complete: done
        });
    });
    var effectsEffectFold = $.effects.define("fold", "hide", function(options, done) {
        var element = $(this), mode = options.mode, show = mode === "show", hide = mode === "hide", size = options.size || 15, percent = /([0-9]+)%/.exec(size), horizFirst = !!options.horizFirst, ref = horizFirst ? [ "right", "bottom" ] : [ "bottom", "right" ], duration = options.duration / 2, placeholder = $.effects.createPlaceholder(element), start = element.cssClip(), animation1 = {
            clip: $.extend({}, start)
        }, animation2 = {
            clip: $.extend({}, start)
        }, distance = [ start[ref[0]], start[ref[1]] ], queuelen = element.queue().length;
        if (percent) {
            size = parseInt(percent[1], 10) / 100 * distance[hide ? 0 : 1];
        }
        animation1.clip[ref[0]] = size;
        animation2.clip[ref[0]] = size;
        animation2.clip[ref[1]] = 0;
        if (show) {
            element.cssClip(animation2.clip);
            if (placeholder) {
                placeholder.css($.effects.clipToBox(animation2));
            }
            animation2.clip = start;
        }
        element.queue(function(next) {
            if (placeholder) {
                placeholder.animate($.effects.clipToBox(animation1), duration, options.easing).animate($.effects.clipToBox(animation2), duration, options.easing);
            }
            next();
        }).animate(animation1, duration, options.easing).animate(animation2, duration, options.easing).queue(done);
        $.effects.unshift(element, queuelen, 4);
    });
    var effectsEffectHighlight = $.effects.define("highlight", "show", function(options, done) {
        var element = $(this), animation = {
            backgroundColor: element.css("backgroundColor")
        };
        if (options.mode === "hide") {
            animation.opacity = 0;
        }
        $.effects.saveStyle(element);
        element.css({
            backgroundImage: "none",
            backgroundColor: options.color || "#ffff99"
        }).animate(animation, {
            queue: false,
            duration: options.duration,
            easing: options.easing,
            complete: done
        });
    });
    var effectsEffectSize = $.effects.define("size", function(options, done) {
        var baseline, factor, temp, element = $(this), cProps = [ "fontSize" ], vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ], hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ], mode = options.mode, restore = mode !== "effect", scale = options.scale || "both", origin = options.origin || [ "middle", "center" ], position = element.css("position"), pos = element.position(), original = $.effects.scaledDimensions(element), from = options.from || original, to = options.to || $.effects.scaledDimensions(element, 0);
        $.effects.createPlaceholder(element);
        if (mode === "show") {
            temp = from;
            from = to;
            to = temp;
        }
        factor = {
            from: {
                y: from.height / original.height,
                x: from.width / original.width
            },
            to: {
                y: to.height / original.height,
                x: to.width / original.width
            }
        };
        if (scale === "box" || scale === "both") {
            if (factor.from.y !== factor.to.y) {
                from = $.effects.setTransition(element, vProps, factor.from.y, from);
                to = $.effects.setTransition(element, vProps, factor.to.y, to);
            }
            if (factor.from.x !== factor.to.x) {
                from = $.effects.setTransition(element, hProps, factor.from.x, from);
                to = $.effects.setTransition(element, hProps, factor.to.x, to);
            }
        }
        if (scale === "content" || scale === "both") {
            if (factor.from.y !== factor.to.y) {
                from = $.effects.setTransition(element, cProps, factor.from.y, from);
                to = $.effects.setTransition(element, cProps, factor.to.y, to);
            }
        }
        if (origin) {
            baseline = $.effects.getBaseline(origin, original);
            from.top = (original.outerHeight - from.outerHeight) * baseline.y + pos.top;
            from.left = (original.outerWidth - from.outerWidth) * baseline.x + pos.left;
            to.top = (original.outerHeight - to.outerHeight) * baseline.y + pos.top;
            to.left = (original.outerWidth - to.outerWidth) * baseline.x + pos.left;
        }
        delete from.outerHeight;
        delete from.outerWidth;
        element.css(from);
        if (scale === "content" || scale === "both") {
            vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps);
            hProps = hProps.concat([ "marginLeft", "marginRight" ]);
            element.find("*[width]").each(function() {
                var child = $(this), childOriginal = $.effects.scaledDimensions(child), childFrom = {
                    height: childOriginal.height * factor.from.y,
                    width: childOriginal.width * factor.from.x,
                    outerHeight: childOriginal.outerHeight * factor.from.y,
                    outerWidth: childOriginal.outerWidth * factor.from.x
                }, childTo = {
                    height: childOriginal.height * factor.to.y,
                    width: childOriginal.width * factor.to.x,
                    outerHeight: childOriginal.height * factor.to.y,
                    outerWidth: childOriginal.width * factor.to.x
                };
                if (factor.from.y !== factor.to.y) {
                    childFrom = $.effects.setTransition(child, vProps, factor.from.y, childFrom);
                    childTo = $.effects.setTransition(child, vProps, factor.to.y, childTo);
                }
                if (factor.from.x !== factor.to.x) {
                    childFrom = $.effects.setTransition(child, hProps, factor.from.x, childFrom);
                    childTo = $.effects.setTransition(child, hProps, factor.to.x, childTo);
                }
                if (restore) {
                    $.effects.saveStyle(child);
                }
                child.css(childFrom);
                child.animate(childTo, options.duration, options.easing, function() {
                    if (restore) {
                        $.effects.restoreStyle(child);
                    }
                });
            });
        }
        element.animate(to, {
            queue: false,
            duration: options.duration,
            easing: options.easing,
            complete: function() {
                var offset = element.offset();
                if (to.opacity === 0) {
                    element.css("opacity", from.opacity);
                }
                if (!restore) {
                    element.css("position", position === "static" ? "relative" : position).offset(offset);
                    $.effects.saveStyle(element);
                }
                done();
            }
        });
    });
    var effectsEffectScale = $.effects.define("scale", function(options, done) {
        var el = $(this), mode = options.mode, percent = parseInt(options.percent, 10) || (parseInt(options.percent, 10) === 0 ? 0 : mode !== "effect" ? 0 : 100), newOptions = $.extend(true, {
            from: $.effects.scaledDimensions(el),
            to: $.effects.scaledDimensions(el, percent, options.direction || "both"),
            origin: options.origin || [ "middle", "center" ]
        }, options);
        if (options.fade) {
            newOptions.from.opacity = 1;
            newOptions.to.opacity = 0;
        }
        $.effects.effect.size.call(this, newOptions, done);
    });
    var effectsEffectPuff = $.effects.define("puff", "hide", function(options, done) {
        var newOptions = $.extend(true, {}, options, {
            fade: true,
            percent: parseInt(options.percent, 10) || 150
        });
        $.effects.effect.scale.call(this, newOptions, done);
    });
    var effectsEffectPulsate = $.effects.define("pulsate", "show", function(options, done) {
        var element = $(this), mode = options.mode, show = mode === "show", hide = mode === "hide", showhide = show || hide, anims = (options.times || 5) * 2 + (showhide ? 1 : 0), duration = options.duration / anims, animateTo = 0, i = 1, queuelen = element.queue().length;
        if (show || !element.is(":visible")) {
            element.css("opacity", 0).show();
            animateTo = 1;
        }
        for (;i < anims; i++) {
            element.animate({
                opacity: animateTo
            }, duration, options.easing);
            animateTo = 1 - animateTo;
        }
        element.animate({
            opacity: animateTo
        }, duration, options.easing);
        element.queue(done);
        $.effects.unshift(element, queuelen, anims + 1);
    });
    var effectsEffectShake = $.effects.define("shake", function(options, done) {
        var i = 1, element = $(this), direction = options.direction || "left", distance = options.distance || 20, times = options.times || 3, anims = times * 2 + 1, speed = Math.round(options.duration / anims), ref = direction === "up" || direction === "down" ? "top" : "left", positiveMotion = direction === "up" || direction === "left", animation = {}, animation1 = {}, animation2 = {}, queuelen = element.queue().length;
        $.effects.createPlaceholder(element);
        animation[ref] = (positiveMotion ? "-=" : "+=") + distance;
        animation1[ref] = (positiveMotion ? "+=" : "-=") + distance * 2;
        animation2[ref] = (positiveMotion ? "-=" : "+=") + distance * 2;
        element.animate(animation, speed, options.easing);
        for (;i < times; i++) {
            element.animate(animation1, speed, options.easing).animate(animation2, speed, options.easing);
        }
        element.animate(animation1, speed, options.easing).animate(animation, speed / 2, options.easing).queue(done);
        $.effects.unshift(element, queuelen, anims + 1);
    });
    var effectsEffectSlide = $.effects.define("slide", "show", function(options, done) {
        var startClip, startRef, element = $(this), map = {
            up: [ "bottom", "top" ],
            down: [ "top", "bottom" ],
            left: [ "right", "left" ],
            right: [ "left", "right" ]
        }, mode = options.mode, direction = options.direction || "left", ref = direction === "up" || direction === "down" ? "top" : "left", positiveMotion = direction === "up" || direction === "left", distance = options.distance || element[ref === "top" ? "outerHeight" : "outerWidth"](true), animation = {};
        $.effects.createPlaceholder(element);
        startClip = element.cssClip();
        startRef = element.position()[ref];
        animation[ref] = (positiveMotion ? -1 : 1) * distance + startRef;
        animation.clip = element.cssClip();
        animation.clip[map[direction][1]] = animation.clip[map[direction][0]];
        if (mode === "show") {
            element.cssClip(animation.clip);
            element.css(ref, animation[ref]);
            animation.clip = startClip;
            animation[ref] = startRef;
        }
        element.animate(animation, {
            queue: false,
            duration: options.duration,
            easing: options.easing,
            complete: done
        });
    });
    var effect;
    if ($.uiBackCompat !== false) {
        effect = $.effects.define("transfer", function(options, done) {
            $(this).transfer(options, done);
        });
    }
    var effectsEffectTransfer = effect;
    $.ui.focusable = function(element, hasTabindex) {
        var map, mapName, img, focusableIfVisible, fieldset, nodeName = element.nodeName.toLowerCase();
        if ("area" === nodeName) {
            map = element.parentNode;
            mapName = map.name;
            if (!element.href || !mapName || map.nodeName.toLowerCase() !== "map") {
                return false;
            }
            img = $("img[usemap='#" + mapName + "']");
            return img.length > 0 && img.is(":visible");
        }
        if (/^(input|select|textarea|button|object)$/.test(nodeName)) {
            focusableIfVisible = !element.disabled;
            if (focusableIfVisible) {
                fieldset = $(element).closest("fieldset")[0];
                if (fieldset) {
                    focusableIfVisible = !fieldset.disabled;
                }
            }
        } else if ("a" === nodeName) {
            focusableIfVisible = element.href || hasTabindex;
        } else {
            focusableIfVisible = hasTabindex;
        }
        return focusableIfVisible && $(element).is(":visible") && visible($(element));
    };
    function visible(element) {
        var visibility = element.css("visibility");
        while (visibility === "inherit") {
            element = element.parent();
            visibility = element.css("visibility");
        }
        return visibility === "visible";
    }
    $.extend($.expr.pseudos, {
        focusable: function(element) {
            return $.ui.focusable(element, $.attr(element, "tabindex") != null);
        }
    });
    var focusable = $.ui.focusable;
    var form = $.fn._form = function() {
        return typeof this[0].form === "string" ? this.closest("form") : $(this[0].form);
    };
    var formResetMixin = $.ui.formResetMixin = {
        _formResetHandler: function() {
            var form = $(this);
            setTimeout(function() {
                var instances = form.data("ui-form-reset-instances");
                $.each(instances, function() {
                    this.refresh();
                });
            });
        },
        _bindFormResetHandler: function() {
            this.form = this.element._form();
            if (!this.form.length) {
                return;
            }
            var instances = this.form.data("ui-form-reset-instances") || [];
            if (!instances.length) {
                this.form.on("reset.ui-form-reset", this._formResetHandler);
            }
            instances.push(this);
            this.form.data("ui-form-reset-instances", instances);
        },
        _unbindFormResetHandler: function() {
            if (!this.form.length) {
                return;
            }
            var instances = this.form.data("ui-form-reset-instances");
            instances.splice($.inArray(this, instances), 1);
            if (instances.length) {
                this.form.data("ui-form-reset-instances", instances);
            } else {
                this.form.removeData("ui-form-reset-instances").off("reset.ui-form-reset");
            }
        }
    };
    if (!$.expr.pseudos) {
        $.expr.pseudos = $.expr[":"];
    }
    if (!$.uniqueSort) {
        $.uniqueSort = $.unique;
    }
    if (!$.escapeSelector) {
        var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g;
        var fcssescape = function(ch, asCodePoint) {
            if (asCodePoint) {
                if (ch === "\0") {
                    return "�";
                }
                return ch.slice(0, -1) + "\\" + ch.charCodeAt(ch.length - 1).toString(16) + " ";
            }
            return "\\" + ch;
        };
        $.escapeSelector = function(sel) {
            return (sel + "").replace(rcssescape, fcssescape);
        };
    }
    if (!$.fn.even || !$.fn.odd) {
        $.fn.extend({
            even: function() {
                return this.filter(function(i) {
                    return i % 2 === 0;
                });
            },
            odd: function() {
                return this.filter(function(i) {
                    return i % 2 === 1;
                });
            }
        });
    }
    var keycode = $.ui.keyCode = {
        BACKSPACE: 8,
        COMMA: 188,
        DELETE: 46,
        DOWN: 40,
        END: 35,
        ENTER: 13,
        ESCAPE: 27,
        HOME: 36,
        LEFT: 37,
        PAGE_DOWN: 34,
        PAGE_UP: 33,
        PERIOD: 190,
        RIGHT: 39,
        SPACE: 32,
        TAB: 9,
        UP: 38
    };
    var labels = $.fn.labels = function() {
        var ancestor, selector, id, labels, ancestors;
        if (!this.length) {
            return this.pushStack([]);
        }
        if (this[0].labels && this[0].labels.length) {
            return this.pushStack(this[0].labels);
        }
        labels = this.eq(0).parents("label");
        id = this.attr("id");
        if (id) {
            ancestor = this.eq(0).parents().last();
            ancestors = ancestor.add(ancestor.length ? ancestor.siblings() : this.siblings());
            selector = "label[for='" + $.escapeSelector(id) + "']";
            labels = labels.add(ancestors.find(selector).addBack(selector));
        }
        return this.pushStack(labels);
    };
    var scrollParent = $.fn.scrollParent = function(includeHidden) {
        var position = this.css("position"), excludeStaticParent = position === "absolute", overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/, scrollParent = this.parents().filter(function() {
            var parent = $(this);
            if (excludeStaticParent && parent.css("position") === "static") {
                return false;
            }
            return overflowRegex.test(parent.css("overflow") + parent.css("overflow-y") + parent.css("overflow-x"));
        }).eq(0);
        return position === "fixed" || !scrollParent.length ? $(this[0].ownerDocument || document) : scrollParent;
    };
    var tabbable = $.extend($.expr.pseudos, {
        tabbable: function(element) {
            var tabIndex = $.attr(element, "tabindex"), hasTabindex = tabIndex != null;
            return (!hasTabindex || tabIndex >= 0) && $.ui.focusable(element, hasTabindex);
        }
    });
    var uniqueId = $.fn.extend({
        uniqueId: function() {
            var uuid = 0;
            return function() {
                return this.each(function() {
                    if (!this.id) {
                        this.id = "ui-id-" + ++uuid;
                    }
                });
            };
        }(),
        removeUniqueId: function() {
            return this.each(function() {
                if (/^ui-id-\d+$/.test(this.id)) {
                    $(this).removeAttr("id");
                }
            });
        }
    });
    var widgetsAccordion = $.widget("ui.accordion", {
        version: "1.13.1",
        options: {
            active: 0,
            animate: {},
            classes: {
                "ui-accordion-header": "ui-corner-top",
                "ui-accordion-header-collapsed": "ui-corner-all",
                "ui-accordion-content": "ui-corner-bottom"
            },
            collapsible: false,
            event: "click",
            header: function(elem) {
                return elem.find("> li > :first-child").add(elem.find("> :not(li)").even());
            },
            heightStyle: "auto",
            icons: {
                activeHeader: "ui-icon-triangle-1-s",
                header: "ui-icon-triangle-1-e"
            },
            activate: null,
            beforeActivate: null
        },
        hideProps: {
            borderTopWidth: "hide",
            borderBottomWidth: "hide",
            paddingTop: "hide",
            paddingBottom: "hide",
            height: "hide"
        },
        showProps: {
            borderTopWidth: "show",
            borderBottomWidth: "show",
            paddingTop: "show",
            paddingBottom: "show",
            height: "show"
        },
        _create: function() {
            var options = this.options;
            this.prevShow = this.prevHide = $();
            this._addClass("ui-accordion", "ui-widget ui-helper-reset");
            this.element.attr("role", "tablist");
            if (!options.collapsible && (options.active === false || options.active == null)) {
                options.active = 0;
            }
            this._processPanels();
            if (options.active < 0) {
                options.active += this.headers.length;
            }
            this._refresh();
        },
        _getCreateEventData: function() {
            return {
                header: this.active,
                panel: !this.active.length ? $() : this.active.next()
            };
        },
        _createIcons: function() {
            var icon, children, icons = this.options.icons;
            if (icons) {
                icon = $("<span>");
                this._addClass(icon, "ui-accordion-header-icon", "ui-icon " + icons.header);
                icon.prependTo(this.headers);
                children = this.active.children(".ui-accordion-header-icon");
                this._removeClass(children, icons.header)._addClass(children, null, icons.activeHeader)._addClass(this.headers, "ui-accordion-icons");
            }
        },
        _destroyIcons: function() {
            this._removeClass(this.headers, "ui-accordion-icons");
            this.headers.children(".ui-accordion-header-icon").remove();
        },
        _destroy: function() {
            var contents;
            this.element.removeAttr("role");
            this.headers.removeAttr("role aria-expanded aria-selected aria-controls tabIndex").removeUniqueId();
            this._destroyIcons();
            contents = this.headers.next().css("display", "").removeAttr("role aria-hidden aria-labelledby").removeUniqueId();
            if (this.options.heightStyle !== "content") {
                contents.css("height", "");
            }
        },
        _setOption: function(key, value) {
            if (key === "active") {
                this._activate(value);
                return;
            }
            if (key === "event") {
                if (this.options.event) {
                    this._off(this.headers, this.options.event);
                }
                this._setupEvents(value);
            }
            this._super(key, value);
            if (key === "collapsible" && !value && this.options.active === false) {
                this._activate(0);
            }
            if (key === "icons") {
                this._destroyIcons();
                if (value) {
                    this._createIcons();
                }
            }
        },
        _setOptionDisabled: function(value) {
            this._super(value);
            this.element.attr("aria-disabled", value);
            this._toggleClass(null, "ui-state-disabled", !!value);
            this._toggleClass(this.headers.add(this.headers.next()), null, "ui-state-disabled", !!value);
        },
        _keydown: function(event) {
            if (event.altKey || event.ctrlKey) {
                return;
            }
            var keyCode = $.ui.keyCode, length = this.headers.length, currentIndex = this.headers.index(event.target), toFocus = false;
            switch (event.keyCode) {
              case keyCode.RIGHT:
              case keyCode.DOWN:
                toFocus = this.headers[(currentIndex + 1) % length];
                break;

              case keyCode.LEFT:
              case keyCode.UP:
                toFocus = this.headers[(currentIndex - 1 + length) % length];
                break;

              case keyCode.SPACE:
              case keyCode.ENTER:
                this._eventHandler(event);
                break;

              case keyCode.HOME:
                toFocus = this.headers[0];
                break;

              case keyCode.END:
                toFocus = this.headers[length - 1];
                break;
            }
            if (toFocus) {
                $(event.target).attr("tabIndex", -1);
                $(toFocus).attr("tabIndex", 0);
                $(toFocus).trigger("focus");
                event.preventDefault();
            }
        },
        _panelKeyDown: function(event) {
            if (event.keyCode === $.ui.keyCode.UP && event.ctrlKey) {
                $(event.currentTarget).prev().trigger("focus");
            }
        },
        refresh: function() {
            var options = this.options;
            this._processPanels();
            if (options.active === false && options.collapsible === true || !this.headers.length) {
                options.active = false;
                this.active = $();
            } else if (options.active === false) {
                this._activate(0);
            } else if (this.active.length && !$.contains(this.element[0], this.active[0])) {
                if (this.headers.length === this.headers.find(".ui-state-disabled").length) {
                    options.active = false;
                    this.active = $();
                } else {
                    this._activate(Math.max(0, options.active - 1));
                }
            } else {
                options.active = this.headers.index(this.active);
            }
            this._destroyIcons();
            this._refresh();
        },
        _processPanels: function() {
            var prevHeaders = this.headers, prevPanels = this.panels;
            if (typeof this.options.header === "function") {
                this.headers = this.options.header(this.element);
            } else {
                this.headers = this.element.find(this.options.header);
            }
            this._addClass(this.headers, "ui-accordion-header ui-accordion-header-collapsed", "ui-state-default");
            this.panels = this.headers.next().filter(":not(.ui-accordion-content-active)").hide();
            this._addClass(this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content");
            if (prevPanels) {
                this._off(prevHeaders.not(this.headers));
                this._off(prevPanels.not(this.panels));
            }
        },
        _refresh: function() {
            var maxHeight, options = this.options, heightStyle = options.heightStyle, parent = this.element.parent();
            this.active = this._findActive(options.active);
            this._addClass(this.active, "ui-accordion-header-active", "ui-state-active")._removeClass(this.active, "ui-accordion-header-collapsed");
            this._addClass(this.active.next(), "ui-accordion-content-active");
            this.active.next().show();
            this.headers.attr("role", "tab").each(function() {
                var header = $(this), headerId = header.uniqueId().attr("id"), panel = header.next(), panelId = panel.uniqueId().attr("id");
                header.attr("aria-controls", panelId);
                panel.attr("aria-labelledby", headerId);
            }).next().attr("role", "tabpanel");
            this.headers.not(this.active).attr({
                "aria-selected": "false",
                "aria-expanded": "false",
                tabIndex: -1
            }).next().attr({
                "aria-hidden": "true"
            }).hide();
            if (!this.active.length) {
                this.headers.eq(0).attr("tabIndex", 0);
            } else {
                this.active.attr({
                    "aria-selected": "true",
                    "aria-expanded": "true",
                    tabIndex: 0
                }).next().attr({
                    "aria-hidden": "false"
                });
            }
            this._createIcons();
            this._setupEvents(options.event);
            if (heightStyle === "fill") {
                maxHeight = parent.height();
                this.element.siblings(":visible").each(function() {
                    var elem = $(this), position = elem.css("position");
                    if (position === "absolute" || position === "fixed") {
                        return;
                    }
                    maxHeight -= elem.outerHeight(true);
                });
                this.headers.each(function() {
                    maxHeight -= $(this).outerHeight(true);
                });
                this.headers.next().each(function() {
                    $(this).height(Math.max(0, maxHeight - $(this).innerHeight() + $(this).height()));
                }).css("overflow", "auto");
            } else if (heightStyle === "auto") {
                maxHeight = 0;
                this.headers.next().each(function() {
                    var isVisible = $(this).is(":visible");
                    if (!isVisible) {
                        $(this).show();
                    }
                    maxHeight = Math.max(maxHeight, $(this).css("height", "").height());
                    if (!isVisible) {
                        $(this).hide();
                    }
                }).height(maxHeight);
            }
        },
        _activate: function(index) {
            var active = this._findActive(index)[0];
            if (active === this.active[0]) {
                return;
            }
            active = active || this.active[0];
            this._eventHandler({
                target: active,
                currentTarget: active,
                preventDefault: $.noop
            });
        },
        _findActive: function(selector) {
            return typeof selector === "number" ? this.headers.eq(selector) : $();
        },
        _setupEvents: function(event) {
            var events = {
                keydown: "_keydown"
            };
            if (event) {
                $.each(event.split(" "), function(index, eventName) {
                    events[eventName] = "_eventHandler";
                });
            }
            this._off(this.headers.add(this.headers.next()));
            this._on(this.headers, events);
            this._on(this.headers.next(), {
                keydown: "_panelKeyDown"
            });
            this._hoverable(this.headers);
            this._focusable(this.headers);
        },
        _eventHandler: function(event) {
            var activeChildren, clickedChildren, options = this.options, active = this.active, clicked = $(event.currentTarget), clickedIsActive = clicked[0] === active[0], collapsing = clickedIsActive && options.collapsible, toShow = collapsing ? $() : clicked.next(), toHide = active.next(), eventData = {
                oldHeader: active,
                oldPanel: toHide,
                newHeader: collapsing ? $() : clicked,
                newPanel: toShow
            };
            event.preventDefault();
            if (clickedIsActive && !options.collapsible || this._trigger("beforeActivate", event, eventData) === false) {
                return;
            }
            options.active = collapsing ? false : this.headers.index(clicked);
            this.active = clickedIsActive ? $() : clicked;
            this._toggle(eventData);
            this._removeClass(active, "ui-accordion-header-active", "ui-state-active");
            if (options.icons) {
                activeChildren = active.children(".ui-accordion-header-icon");
                this._removeClass(activeChildren, null, options.icons.activeHeader)._addClass(activeChildren, null, options.icons.header);
            }
            if (!clickedIsActive) {
                this._removeClass(clicked, "ui-accordion-header-collapsed")._addClass(clicked, "ui-accordion-header-active", "ui-state-active");
                if (options.icons) {
                    clickedChildren = clicked.children(".ui-accordion-header-icon");
                    this._removeClass(clickedChildren, null, options.icons.header)._addClass(clickedChildren, null, options.icons.activeHeader);
                }
                this._addClass(clicked.next(), "ui-accordion-content-active");
            }
        },
        _toggle: function(data) {
            var toShow = data.newPanel, toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
            this.prevShow.add(this.prevHide).stop(true, true);
            this.prevShow = toShow;
            this.prevHide = toHide;
            if (this.options.animate) {
                this._animate(toShow, toHide, data);
            } else {
                toHide.hide();
                toShow.show();
                this._toggleComplete(data);
            }
            toHide.attr({
                "aria-hidden": "true"
            });
            toHide.prev().attr({
                "aria-selected": "false",
                "aria-expanded": "false"
            });
            if (toShow.length && toHide.length) {
                toHide.prev().attr({
                    tabIndex: -1,
                    "aria-expanded": "false"
                });
            } else if (toShow.length) {
                this.headers.filter(function() {
                    return parseInt($(this).attr("tabIndex"), 10) === 0;
                }).attr("tabIndex", -1);
            }
            toShow.attr("aria-hidden", "false").prev().attr({
                "aria-selected": "true",
                "aria-expanded": "true",
                tabIndex: 0
            });
        },
        _animate: function(toShow, toHide, data) {
            var total, easing, duration, that = this, adjust = 0, boxSizing = toShow.css("box-sizing"), down = toShow.length && (!toHide.length || toShow.index() < toHide.index()), animate = this.options.animate || {}, options = down && animate.down || animate, complete = function() {
                that._toggleComplete(data);
            };
            if (typeof options === "number") {
                duration = options;
            }
            if (typeof options === "string") {
                easing = options;
            }
            easing = easing || options.easing || animate.easing;
            duration = duration || options.duration || animate.duration;
            if (!toHide.length) {
                return toShow.animate(this.showProps, duration, easing, complete);
            }
            if (!toShow.length) {
                return toHide.animate(this.hideProps, duration, easing, complete);
            }
            total = toShow.show().outerHeight();
            toHide.animate(this.hideProps, {
                duration: duration,
                easing: easing,
                step: function(now, fx) {
                    fx.now = Math.round(now);
                }
            });
            toShow.hide().animate(this.showProps, {
                duration: duration,
                easing: easing,
                complete: complete,
                step: function(now, fx) {
                    fx.now = Math.round(now);
                    if (fx.prop !== "height") {
                        if (boxSizing === "content-box") {
                            adjust += fx.now;
                        }
                    } else if (that.options.heightStyle !== "content") {
                        fx.now = Math.round(total - toHide.outerHeight() - adjust);
                        adjust = 0;
                    }
                }
            });
        },
        _toggleComplete: function(data) {
            var toHide = data.oldPanel, prev = toHide.prev();
            this._removeClass(toHide, "ui-accordion-content-active");
            this._removeClass(prev, "ui-accordion-header-active")._addClass(prev, "ui-accordion-header-collapsed");
            if (toHide.length) {
                toHide.parent()[0].className = toHide.parent()[0].className;
            }
            this._trigger("activate", null, data);
        }
    });
    var safeActiveElement = $.ui.safeActiveElement = function(document) {
        var activeElement;
        try {
            activeElement = document.activeElement;
        } catch (error) {
            activeElement = document.body;
        }
        if (!activeElement) {
            activeElement = document.body;
        }
        if (!activeElement.nodeName) {
            activeElement = document.body;
        }
        return activeElement;
    };
    var widgetsMenu = $.widget("ui.menu", {
        version: "1.13.1",
        defaultElement: "<ul>",
        delay: 300,
        options: {
            icons: {
                submenu: "ui-icon-caret-1-e"
            },
            items: "> *",
            menus: "ul",
            position: {
                my: "left top",
                at: "right top"
            },
            role: "menu",
            blur: null,
            focus: null,
            select: null
        },
        _create: function() {
            this.activeMenu = this.element;
            this.mouseHandled = false;
            this.lastMousePosition = {
                x: null,
                y: null
            };
            this.element.uniqueId().attr({
                role: this.options.role,
                tabIndex: 0
            });
            this._addClass("ui-menu", "ui-widget ui-widget-content");
            this._on({
                "mousedown .ui-menu-item": function(event) {
                    event.preventDefault();
                    this._activateItem(event);
                },
                "click .ui-menu-item": function(event) {
                    var target = $(event.target);
                    var active = $($.ui.safeActiveElement(this.document[0]));
                    if (!this.mouseHandled && target.not(".ui-state-disabled").length) {
                        this.select(event);
                        if (!event.isPropagationStopped()) {
                            this.mouseHandled = true;
                        }
                        if (target.has(".ui-menu").length) {
                            this.expand(event);
                        } else if (!this.element.is(":focus") && active.closest(".ui-menu").length) {
                            this.element.trigger("focus", [ true ]);
                            if (this.active && this.active.parents(".ui-menu").length === 1) {
                                clearTimeout(this.timer);
                            }
                        }
                    }
                },
                "mouseenter .ui-menu-item": "_activateItem",
                "mousemove .ui-menu-item": "_activateItem",
                mouseleave: "collapseAll",
                "mouseleave .ui-menu": "collapseAll",
                focus: function(event, keepActiveItem) {
                    var item = this.active || this._menuItems().first();
                    if (!keepActiveItem) {
                        this.focus(event, item);
                    }
                },
                blur: function(event) {
                    this._delay(function() {
                        var notContained = !$.contains(this.element[0], $.ui.safeActiveElement(this.document[0]));
                        if (notContained) {
                            this.collapseAll(event);
                        }
                    });
                },
                keydown: "_keydown"
            });
            this.refresh();
            this._on(this.document, {
                click: function(event) {
                    if (this._closeOnDocumentClick(event)) {
                        this.collapseAll(event, true);
                    }
                    this.mouseHandled = false;
                }
            });
        },
        _activateItem: function(event) {
            if (this.previousFilter) {
                return;
            }
            if (event.clientX === this.lastMousePosition.x && event.clientY === this.lastMousePosition.y) {
                return;
            }
            this.lastMousePosition = {
                x: event.clientX,
                y: event.clientY
            };
            var actualTarget = $(event.target).closest(".ui-menu-item"), target = $(event.currentTarget);
            if (actualTarget[0] !== target[0]) {
                return;
            }
            if (target.is(".ui-state-active")) {
                return;
            }
            this._removeClass(target.siblings().children(".ui-state-active"), null, "ui-state-active");
            this.focus(event, target);
        },
        _destroy: function() {
            var items = this.element.find(".ui-menu-item").removeAttr("role aria-disabled"), submenus = items.children(".ui-menu-item-wrapper").removeUniqueId().removeAttr("tabIndex role aria-haspopup");
            this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeAttr("role aria-labelledby aria-expanded aria-hidden aria-disabled " + "tabIndex").removeUniqueId().show();
            submenus.children().each(function() {
                var elem = $(this);
                if (elem.data("ui-menu-submenu-caret")) {
                    elem.remove();
                }
            });
        },
        _keydown: function(event) {
            var match, prev, character, skip, preventDefault = true;
            switch (event.keyCode) {
              case $.ui.keyCode.PAGE_UP:
                this.previousPage(event);
                break;

              case $.ui.keyCode.PAGE_DOWN:
                this.nextPage(event);
                break;

              case $.ui.keyCode.HOME:
                this._move("first", "first", event);
                break;

              case $.ui.keyCode.END:
                this._move("last", "last", event);
                break;

              case $.ui.keyCode.UP:
                this.previous(event);
                break;

              case $.ui.keyCode.DOWN:
                this.next(event);
                break;

              case $.ui.keyCode.LEFT:
                this.collapse(event);
                break;

              case $.ui.keyCode.RIGHT:
                if (this.active && !this.active.is(".ui-state-disabled")) {
                    this.expand(event);
                }
                break;

              case $.ui.keyCode.ENTER:
              case $.ui.keyCode.SPACE:
                this._activate(event);
                break;

              case $.ui.keyCode.ESCAPE:
                this.collapse(event);
                break;

              default:
                preventDefault = false;
                prev = this.previousFilter || "";
                skip = false;
                character = event.keyCode >= 96 && event.keyCode <= 105 ? (event.keyCode - 96).toString() : String.fromCharCode(event.keyCode);
                clearTimeout(this.filterTimer);
                if (character === prev) {
                    skip = true;
                } else {
                    character = prev + character;
                }
                match = this._filterMenuItems(character);
                match = skip && match.index(this.active.next()) !== -1 ? this.active.nextAll(".ui-menu-item") : match;
                if (!match.length) {
                    character = String.fromCharCode(event.keyCode);
                    match = this._filterMenuItems(character);
                }
                if (match.length) {
                    this.focus(event, match);
                    this.previousFilter = character;
                    this.filterTimer = this._delay(function() {
                        delete this.previousFilter;
                    }, 1e3);
                } else {
                    delete this.previousFilter;
                }
            }
            if (preventDefault) {
                event.preventDefault();
            }
        },
        _activate: function(event) {
            if (this.active && !this.active.is(".ui-state-disabled")) {
                if (this.active.children("[aria-haspopup='true']").length) {
                    this.expand(event);
                } else {
                    this.select(event);
                }
            }
        },
        refresh: function() {
            var menus, items, newSubmenus, newItems, newWrappers, that = this, icon = this.options.icons.submenu, submenus = this.element.find(this.options.menus);
            this._toggleClass("ui-menu-icons", null, !!this.element.find(".ui-icon").length);
            newSubmenus = submenus.filter(":not(.ui-menu)").hide().attr({
                role: this.options.role,
                "aria-hidden": "true",
                "aria-expanded": "false"
            }).each(function() {
                var menu = $(this), item = menu.prev(), submenuCaret = $("<span>").data("ui-menu-submenu-caret", true);
                that._addClass(submenuCaret, "ui-menu-icon", "ui-icon " + icon);
                item.attr("aria-haspopup", "true").prepend(submenuCaret);
                menu.attr("aria-labelledby", item.attr("id"));
            });
            this._addClass(newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front");
            menus = submenus.add(this.element);
            items = menus.find(this.options.items);
            items.not(".ui-menu-item").each(function() {
                var item = $(this);
                if (that._isDivider(item)) {
                    that._addClass(item, "ui-menu-divider", "ui-widget-content");
                }
            });
            newItems = items.not(".ui-menu-item, .ui-menu-divider");
            newWrappers = newItems.children().not(".ui-menu").uniqueId().attr({
                tabIndex: -1,
                role: this._itemRole()
            });
            this._addClass(newItems, "ui-menu-item")._addClass(newWrappers, "ui-menu-item-wrapper");
            items.filter(".ui-state-disabled").attr("aria-disabled", "true");
            if (this.active && !$.contains(this.element[0], this.active[0])) {
                this.blur();
            }
        },
        _itemRole: function() {
            return {
                menu: "menuitem",
                listbox: "option"
            }[this.options.role];
        },
        _setOption: function(key, value) {
            if (key === "icons") {
                var icons = this.element.find(".ui-menu-icon");
                this._removeClass(icons, null, this.options.icons.submenu)._addClass(icons, null, value.submenu);
            }
            this._super(key, value);
        },
        _setOptionDisabled: function(value) {
            this._super(value);
            this.element.attr("aria-disabled", String(value));
            this._toggleClass(null, "ui-state-disabled", !!value);
        },
        focus: function(event, item) {
            var nested, focused, activeParent;
            this.blur(event, event && event.type === "focus");
            this._scrollIntoView(item);
            this.active = item.first();
            focused = this.active.children(".ui-menu-item-wrapper");
            this._addClass(focused, null, "ui-state-active");
            if (this.options.role) {
                this.element.attr("aria-activedescendant", focused.attr("id"));
            }
            activeParent = this.active.parent().closest(".ui-menu-item").children(".ui-menu-item-wrapper");
            this._addClass(activeParent, null, "ui-state-active");
            if (event && event.type === "keydown") {
                this._close();
            } else {
                this.timer = this._delay(function() {
                    this._close();
                }, this.delay);
            }
            nested = item.children(".ui-menu");
            if (nested.length && event && /^mouse/.test(event.type)) {
                this._startOpening(nested);
            }
            this.activeMenu = item.parent();
            this._trigger("focus", event, {
                item: item
            });
        },
        _scrollIntoView: function(item) {
            var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
            if (this._hasScroll()) {
                borderTop = parseFloat($.css(this.activeMenu[0], "borderTopWidth")) || 0;
                paddingTop = parseFloat($.css(this.activeMenu[0], "paddingTop")) || 0;
                offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
                scroll = this.activeMenu.scrollTop();
                elementHeight = this.activeMenu.height();
                itemHeight = item.outerHeight();
                if (offset < 0) {
                    this.activeMenu.scrollTop(scroll + offset);
                } else if (offset + itemHeight > elementHeight) {
                    this.activeMenu.scrollTop(scroll + offset - elementHeight + itemHeight);
                }
            }
        },
        blur: function(event, fromFocus) {
            if (!fromFocus) {
                clearTimeout(this.timer);
            }
            if (!this.active) {
                return;
            }
            this._removeClass(this.active.children(".ui-menu-item-wrapper"), null, "ui-state-active");
            this._trigger("blur", event, {
                item: this.active
            });
            this.active = null;
        },
        _startOpening: function(submenu) {
            clearTimeout(this.timer);
            if (submenu.attr("aria-hidden") !== "true") {
                return;
            }
            this.timer = this._delay(function() {
                this._close();
                this._open(submenu);
            }, this.delay);
        },
        _open: function(submenu) {
            var position = $.extend({
                of: this.active
            }, this.options.position);
            clearTimeout(this.timer);
            this.element.find(".ui-menu").not(submenu.parents(".ui-menu")).hide().attr("aria-hidden", "true");
            submenu.show().removeAttr("aria-hidden").attr("aria-expanded", "true").position(position);
        },
        collapseAll: function(event, all) {
            clearTimeout(this.timer);
            this.timer = this._delay(function() {
                var currentMenu = all ? this.element : $(event && event.target).closest(this.element.find(".ui-menu"));
                if (!currentMenu.length) {
                    currentMenu = this.element;
                }
                this._close(currentMenu);
                this.blur(event);
                this._removeClass(currentMenu.find(".ui-state-active"), null, "ui-state-active");
                this.activeMenu = currentMenu;
            }, all ? 0 : this.delay);
        },
        _close: function(startMenu) {
            if (!startMenu) {
                startMenu = this.active ? this.active.parent() : this.element;
            }
            startMenu.find(".ui-menu").hide().attr("aria-hidden", "true").attr("aria-expanded", "false");
        },
        _closeOnDocumentClick: function(event) {
            return !$(event.target).closest(".ui-menu").length;
        },
        _isDivider: function(item) {
            return !/[^\-\u2014\u2013\s]/.test(item.text());
        },
        collapse: function(event) {
            var newItem = this.active && this.active.parent().closest(".ui-menu-item", this.element);
            if (newItem && newItem.length) {
                this._close();
                this.focus(event, newItem);
            }
        },
        expand: function(event) {
            var newItem = this.active && this._menuItems(this.active.children(".ui-menu")).first();
            if (newItem && newItem.length) {
                this._open(newItem.parent());
                this._delay(function() {
                    this.focus(event, newItem);
                });
            }
        },
        next: function(event) {
            this._move("next", "first", event);
        },
        previous: function(event) {
            this._move("prev", "last", event);
        },
        isFirstItem: function() {
            return this.active && !this.active.prevAll(".ui-menu-item").length;
        },
        isLastItem: function() {
            return this.active && !this.active.nextAll(".ui-menu-item").length;
        },
        _menuItems: function(menu) {
            return (menu || this.element).find(this.options.items).filter(".ui-menu-item");
        },
        _move: function(direction, filter, event) {
            var next;
            if (this.active) {
                if (direction === "first" || direction === "last") {
                    next = this.active[direction === "first" ? "prevAll" : "nextAll"](".ui-menu-item").last();
                } else {
                    next = this.active[direction + "All"](".ui-menu-item").first();
                }
            }
            if (!next || !next.length || !this.active) {
                next = this._menuItems(this.activeMenu)[filter]();
            }
            this.focus(event, next);
        },
        nextPage: function(event) {
            var item, base, height;
            if (!this.active) {
                this.next(event);
                return;
            }
            if (this.isLastItem()) {
                return;
            }
            if (this._hasScroll()) {
                base = this.active.offset().top;
                height = this.element.innerHeight();
                if ($.fn.jquery.indexOf("3.2.") === 0) {
                    height += this.element[0].offsetHeight - this.element.outerHeight();
                }
                this.active.nextAll(".ui-menu-item").each(function() {
                    item = $(this);
                    return item.offset().top - base - height < 0;
                });
                this.focus(event, item);
            } else {
                this.focus(event, this._menuItems(this.activeMenu)[!this.active ? "first" : "last"]());
            }
        },
        previousPage: function(event) {
            var item, base, height;
            if (!this.active) {
                this.next(event);
                return;
            }
            if (this.isFirstItem()) {
                return;
            }
            if (this._hasScroll()) {
                base = this.active.offset().top;
                height = this.element.innerHeight();
                if ($.fn.jquery.indexOf("3.2.") === 0) {
                    height += this.element[0].offsetHeight - this.element.outerHeight();
                }
                this.active.prevAll(".ui-menu-item").each(function() {
                    item = $(this);
                    return item.offset().top - base + height > 0;
                });
                this.focus(event, item);
            } else {
                this.focus(event, this._menuItems(this.activeMenu).first());
            }
        },
        _hasScroll: function() {
            return this.element.outerHeight() < this.element.prop("scrollHeight");
        },
        select: function(event) {
            this.active = this.active || $(event.target).closest(".ui-menu-item");
            var ui = {
                item: this.active
            };
            if (!this.active.has(".ui-menu").length) {
                this.collapseAll(event, true);
            }
            this._trigger("select", event, ui);
        },
        _filterMenuItems: function(character) {
            var escapedCharacter = character.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&"), regex = new RegExp("^" + escapedCharacter, "i");
            return this.activeMenu.find(this.options.items).filter(".ui-menu-item").filter(function() {
                return regex.test(String.prototype.trim.call($(this).children(".ui-menu-item-wrapper").text()));
            });
        }
    });
    $.widget("ui.autocomplete", {
        version: "1.13.1",
        defaultElement: "<input>",
        options: {
            appendTo: null,
            autoFocus: false,
            delay: 300,
            minLength: 1,
            position: {
                my: "left top",
                at: "left bottom",
                collision: "none"
            },
            source: null,
            change: null,
            close: null,
            focus: null,
            open: null,
            response: null,
            search: null,
            select: null
        },
        requestIndex: 0,
        pending: 0,
        liveRegionTimer: null,
        _create: function() {
            var suppressKeyPress, suppressKeyPressRepeat, suppressInput, nodeName = this.element[0].nodeName.toLowerCase(), isTextarea = nodeName === "textarea", isInput = nodeName === "input";
            this.isMultiLine = isTextarea || !isInput && this._isContentEditable(this.element);
            this.valueMethod = this.element[isTextarea || isInput ? "val" : "text"];
            this.isNewMenu = true;
            this._addClass("ui-autocomplete-input");
            this.element.attr("autocomplete", "off");
            this._on(this.element, {
                keydown: function(event) {
                    if (this.element.prop("readOnly")) {
                        suppressKeyPress = true;
                        suppressInput = true;
                        suppressKeyPressRepeat = true;
                        return;
                    }
                    suppressKeyPress = false;
                    suppressInput = false;
                    suppressKeyPressRepeat = false;
                    var keyCode = $.ui.keyCode;
                    switch (event.keyCode) {
                      case keyCode.PAGE_UP:
                        suppressKeyPress = true;
                        this._move("previousPage", event);
                        break;

                      case keyCode.PAGE_DOWN:
                        suppressKeyPress = true;
                        this._move("nextPage", event);
                        break;

                      case keyCode.UP:
                        suppressKeyPress = true;
                        this._keyEvent("previous", event);
                        break;

                      case keyCode.DOWN:
                        suppressKeyPress = true;
                        this._keyEvent("next", event);
                        break;

                      case keyCode.ENTER:
                        if (this.menu.active) {
                            suppressKeyPress = true;
                            event.preventDefault();
                            this.menu.select(event);
                        }
                        break;

                      case keyCode.TAB:
                        if (this.menu.active) {
                            this.menu.select(event);
                        }
                        break;

                      case keyCode.ESCAPE:
                        if (this.menu.element.is(":visible")) {
                            if (!this.isMultiLine) {
                                this._value(this.term);
                            }
                            this.close(event);
                            event.preventDefault();
                        }
                        break;

                      default:
                        suppressKeyPressRepeat = true;
                        this._searchTimeout(event);
                        break;
                    }
                },
                keypress: function(event) {
                    if (suppressKeyPress) {
                        suppressKeyPress = false;
                        if (!this.isMultiLine || this.menu.element.is(":visible")) {
                            event.preventDefault();
                        }
                        return;
                    }
                    if (suppressKeyPressRepeat) {
                        return;
                    }
                    var keyCode = $.ui.keyCode;
                    switch (event.keyCode) {
                      case keyCode.PAGE_UP:
                        this._move("previousPage", event);
                        break;

                      case keyCode.PAGE_DOWN:
                        this._move("nextPage", event);
                        break;

                      case keyCode.UP:
                        this._keyEvent("previous", event);
                        break;

                      case keyCode.DOWN:
                        this._keyEvent("next", event);
                        break;
                    }
                },
                input: function(event) {
                    if (suppressInput) {
                        suppressInput = false;
                        event.preventDefault();
                        return;
                    }
                    this._searchTimeout(event);
                },
                focus: function() {
                    this.selectedItem = null;
                    this.previous = this._value();
                },
                blur: function(event) {
                    clearTimeout(this.searching);
                    this.close(event);
                    this._change(event);
                }
            });
            this._initSource();
            this.menu = $("<ul>").appendTo(this._appendTo()).menu({
                role: null
            }).hide().attr({
                unselectable: "on"
            }).menu("instance");
            this._addClass(this.menu.element, "ui-autocomplete", "ui-front");
            this._on(this.menu.element, {
                mousedown: function(event) {
                    event.preventDefault();
                },
                menufocus: function(event, ui) {
                    var label, item;
                    if (this.isNewMenu) {
                        this.isNewMenu = false;
                        if (event.originalEvent && /^mouse/.test(event.originalEvent.type)) {
                            this.menu.blur();
                            this.document.one("mousemove", function() {
                                $(event.target).trigger(event.originalEvent);
                            });
                            return;
                        }
                    }
                    item = ui.item.data("ui-autocomplete-item");
                    if (false !== this._trigger("focus", event, {
                        item: item
                    })) {
                        if (event.originalEvent && /^key/.test(event.originalEvent.type)) {
                            this._value(item.value);
                        }
                    }
                    label = ui.item.attr("aria-label") || item.value;
                    if (label && String.prototype.trim.call(label).length) {
                        clearTimeout(this.liveRegionTimer);
                        this.liveRegionTimer = this._delay(function() {
                            this.liveRegion.html($("<div>").text(label));
                        }, 100);
                    }
                },
                menuselect: function(event, ui) {
                    var item = ui.item.data("ui-autocomplete-item"), previous = this.previous;
                    if (this.element[0] !== $.ui.safeActiveElement(this.document[0])) {
                        this.element.trigger("focus");
                        this.previous = previous;
                        this._delay(function() {
                            this.previous = previous;
                            this.selectedItem = item;
                        });
                    }
                    if (false !== this._trigger("select", event, {
                        item: item
                    })) {
                        this._value(item.value);
                    }
                    this.term = this._value();
                    this.close(event);
                    this.selectedItem = item;
                }
            });
            this.liveRegion = $("<div>", {
                role: "status",
                "aria-live": "assertive",
                "aria-relevant": "additions"
            }).appendTo(this.document[0].body);
            this._addClass(this.liveRegion, null, "ui-helper-hidden-accessible");
            this._on(this.window, {
                beforeunload: function() {
                    this.element.removeAttr("autocomplete");
                }
            });
        },
        _destroy: function() {
            clearTimeout(this.searching);
            this.element.removeAttr("autocomplete");
            this.menu.element.remove();
            this.liveRegion.remove();
        },
        _setOption: function(key, value) {
            this._super(key, value);
            if (key === "source") {
                this._initSource();
            }
            if (key === "appendTo") {
                this.menu.element.appendTo(this._appendTo());
            }
            if (key === "disabled" && value && this.xhr) {
                this.xhr.abort();
            }
        },
        _isEventTargetInWidget: function(event) {
            var menuElement = this.menu.element[0];
            return event.target === this.element[0] || event.target === menuElement || $.contains(menuElement, event.target);
        },
        _closeOnClickOutside: function(event) {
            if (!this._isEventTargetInWidget(event)) {
                this.close();
            }
        },
        _appendTo: function() {
            var element = this.options.appendTo;
            if (element) {
                element = element.jquery || element.nodeType ? $(element) : this.document.find(element).eq(0);
            }
            if (!element || !element[0]) {
                element = this.element.closest(".ui-front, dialog");
            }
            if (!element.length) {
                element = this.document[0].body;
            }
            return element;
        },
        _initSource: function() {
            var array, url, that = this;
            if (Array.isArray(this.options.source)) {
                array = this.options.source;
                this.source = function(request, response) {
                    response($.ui.autocomplete.filter(array, request.term));
                };
            } else if (typeof this.options.source === "string") {
                url = this.options.source;
                this.source = function(request, response) {
                    if (that.xhr) {
                        that.xhr.abort();
                    }
                    that.xhr = $.ajax({
                        url: url,
                        data: request,
                        dataType: "json",
                        success: function(data) {
                            response(data);
                        },
                        error: function() {
                            response([]);
                        }
                    });
                };
            } else {
                this.source = this.options.source;
            }
        },
        _searchTimeout: function(event) {
            clearTimeout(this.searching);
            this.searching = this._delay(function() {
                var equalValues = this.term === this._value(), menuVisible = this.menu.element.is(":visible"), modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
                if (!equalValues || equalValues && !menuVisible && !modifierKey) {
                    this.selectedItem = null;
                    this.search(null, event);
                }
            }, this.options.delay);
        },
        search: function(value, event) {
            value = value != null ? value : this._value();
            this.term = this._value();
            if (value.length < this.options.minLength) {
                return this.close(event);
            }
            if (this._trigger("search", event) === false) {
                return;
            }
            return this._search(value);
        },
        _search: function(value) {
            this.pending++;
            this._addClass("ui-autocomplete-loading");
            this.cancelSearch = false;
            this.source({
                term: value
            }, this._response());
        },
        _response: function() {
            var index = ++this.requestIndex;
            return function(content) {
                if (index === this.requestIndex) {
                    this.__response(content);
                }
                this.pending--;
                if (!this.pending) {
                    this._removeClass("ui-autocomplete-loading");
                }
            }.bind(this);
        },
        __response: function(content) {
            if (content) {
                content = this._normalize(content);
            }
            this._trigger("response", null, {
                content: content
            });
            if (!this.options.disabled && content && content.length && !this.cancelSearch) {
                this._suggest(content);
                this._trigger("open");
            } else {
                this._close();
            }
        },
        close: function(event) {
            this.cancelSearch = true;
            this._close(event);
        },
        _close: function(event) {
            this._off(this.document, "mousedown");
            if (this.menu.element.is(":visible")) {
                this.menu.element.hide();
                this.menu.blur();
                this.isNewMenu = true;
                this._trigger("close", event);
            }
        },
        _change: function(event) {
            if (this.previous !== this._value()) {
                this._trigger("change", event, {
                    item: this.selectedItem
                });
            }
        },
        _normalize: function(items) {
            if (items.length && items[0].label && items[0].value) {
                return items;
            }
            return $.map(items, function(item) {
                if (typeof item === "string") {
                    return {
                        label: item,
                        value: item
                    };
                }
                return $.extend({}, item, {
                    label: item.label || item.value,
                    value: item.value || item.label
                });
            });
        },
        _suggest: function(items) {
            var ul = this.menu.element.empty();
            this._renderMenu(ul, items);
            this.isNewMenu = true;
            this.menu.refresh();
            ul.show();
            this._resizeMenu();
            ul.position($.extend({
                of: this.element
            }, this.options.position));
            if (this.options.autoFocus) {
                this.menu.next();
            }
            this._on(this.document, {
                mousedown: "_closeOnClickOutside"
            });
        },
        _resizeMenu: function() {
            var ul = this.menu.element;
            ul.outerWidth(Math.max(ul.width("").outerWidth() + 1, this.element.outerWidth()));
        },
        _renderMenu: function(ul, items) {
            var that = this;
            $.each(items, function(index, item) {
                that._renderItemData(ul, item);
            });
        },
        _renderItemData: function(ul, item) {
            return this._renderItem(ul, item).data("ui-autocomplete-item", item);
        },
        _renderItem: function(ul, item) {
            return $("<li>").append($("<div>").text(item.label)).appendTo(ul);
        },
        _move: function(direction, event) {
            if (!this.menu.element.is(":visible")) {
                this.search(null, event);
                return;
            }
            if (this.menu.isFirstItem() && /^previous/.test(direction) || this.menu.isLastItem() && /^next/.test(direction)) {
                if (!this.isMultiLine) {
                    this._value(this.term);
                }
                this.menu.blur();
                return;
            }
            this.menu[direction](event);
        },
        widget: function() {
            return this.menu.element;
        },
        _value: function() {
            return this.valueMethod.apply(this.element, arguments);
        },
        _keyEvent: function(keyEvent, event) {
            if (!this.isMultiLine || this.menu.element.is(":visible")) {
                this._move(keyEvent, event);
                event.preventDefault();
            }
        },
        _isContentEditable: function(element) {
            if (!element.length) {
                return false;
            }
            var editable = element.prop("contentEditable");
            if (editable === "inherit") {
                return this._isContentEditable(element.parent());
            }
            return editable === "true";
        }
    });
    $.extend($.ui.autocomplete, {
        escapeRegex: function(value) {
            return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
        },
        filter: function(array, term) {
            var matcher = new RegExp($.ui.autocomplete.escapeRegex(term), "i");
            return $.grep(array, function(value) {
                return matcher.test(value.label || value.value || value);
            });
        }
    });
    $.widget("ui.autocomplete", $.ui.autocomplete, {
        options: {
            messages: {
                noResults: "No search results.",
                results: function(amount) {
                    return amount + (amount > 1 ? " results are" : " result is") + " available, use up and down arrow keys to navigate.";
                }
            }
        },
        __response: function(content) {
            var message;
            this._superApply(arguments);
            if (this.options.disabled || this.cancelSearch) {
                return;
            }
            if (content && content.length) {
                message = this.options.messages.results(content.length);
            } else {
                message = this.options.messages.noResults;
            }
            clearTimeout(this.liveRegionTimer);
            this.liveRegionTimer = this._delay(function() {
                this.liveRegion.html($("<div>").text(message));
            }, 100);
        }
    });
    var widgetsAutocomplete = $.ui.autocomplete;
    var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g;
    var widgetsControlgroup = $.widget("ui.controlgroup", {
        version: "1.13.1",
        defaultElement: "<div>",
        options: {
            direction: "horizontal",
            disabled: null,
            onlyVisible: true,
            items: {
                button: "input[type=button], input[type=submit], input[type=reset], button, a",
                controlgroupLabel: ".ui-controlgroup-label",
                checkboxradio: "input[type='checkbox'], input[type='radio']",
                selectmenu: "select",
                spinner: ".ui-spinner-input"
            }
        },
        _create: function() {
            this._enhance();
        },
        _enhance: function() {
            this.element.attr("role", "toolbar");
            this.refresh();
        },
        _destroy: function() {
            this._callChildMethod("destroy");
            this.childWidgets.removeData("ui-controlgroup-data");
            this.element.removeAttr("role");
            if (this.options.items.controlgroupLabel) {
                this.element.find(this.options.items.controlgroupLabel).find(".ui-controlgroup-label-contents").contents().unwrap();
            }
        },
        _initWidgets: function() {
            var that = this, childWidgets = [];
            $.each(this.options.items, function(widget, selector) {
                var labels;
                var options = {};
                if (!selector) {
                    return;
                }
                if (widget === "controlgroupLabel") {
                    labels = that.element.find(selector);
                    labels.each(function() {
                        var element = $(this);
                        if (element.children(".ui-controlgroup-label-contents").length) {
                            return;
                        }
                        element.contents().wrapAll("<span class='ui-controlgroup-label-contents'></span>");
                    });
                    that._addClass(labels, null, "ui-widget ui-widget-content ui-state-default");
                    childWidgets = childWidgets.concat(labels.get());
                    return;
                }
                if (!$.fn[widget]) {
                    return;
                }
                if (that["_" + widget + "Options"]) {
                    options = that["_" + widget + "Options"]("middle");
                } else {
                    options = {
                        classes: {}
                    };
                }
                that.element.find(selector).each(function() {
                    var element = $(this);
                    var instance = element[widget]("instance");
                    var instanceOptions = $.widget.extend({}, options);
                    if (widget === "button" && element.parent(".ui-spinner").length) {
                        return;
                    }
                    if (!instance) {
                        instance = element[widget]()[widget]("instance");
                    }
                    if (instance) {
                        instanceOptions.classes = that._resolveClassesValues(instanceOptions.classes, instance);
                    }
                    element[widget](instanceOptions);
                    var widgetElement = element[widget]("widget");
                    $.data(widgetElement[0], "ui-controlgroup-data", instance ? instance : element[widget]("instance"));
                    childWidgets.push(widgetElement[0]);
                });
            });
            this.childWidgets = $($.uniqueSort(childWidgets));
            this._addClass(this.childWidgets, "ui-controlgroup-item");
        },
        _callChildMethod: function(method) {
            this.childWidgets.each(function() {
                var element = $(this), data = element.data("ui-controlgroup-data");
                if (data && data[method]) {
                    data[method]();
                }
            });
        },
        _updateCornerClass: function(element, position) {
            var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all";
            var add = this._buildSimpleOptions(position, "label").classes.label;
            this._removeClass(element, null, remove);
            this._addClass(element, null, add);
        },
        _buildSimpleOptions: function(position, key) {
            var direction = this.options.direction === "vertical";
            var result = {
                classes: {}
            };
            result.classes[key] = {
                middle: "",
                first: "ui-corner-" + (direction ? "top" : "left"),
                last: "ui-corner-" + (direction ? "bottom" : "right"),
                only: "ui-corner-all"
            }[position];
            return result;
        },
        _spinnerOptions: function(position) {
            var options = this._buildSimpleOptions(position, "ui-spinner");
            options.classes["ui-spinner-up"] = "";
            options.classes["ui-spinner-down"] = "";
            return options;
        },
        _buttonOptions: function(position) {
            return this._buildSimpleOptions(position, "ui-button");
        },
        _checkboxradioOptions: function(position) {
            return this._buildSimpleOptions(position, "ui-checkboxradio-label");
        },
        _selectmenuOptions: function(position) {
            var direction = this.options.direction === "vertical";
            return {
                width: direction ? "auto" : false,
                classes: {
                    middle: {
                        "ui-selectmenu-button-open": "",
                        "ui-selectmenu-button-closed": ""
                    },
                    first: {
                        "ui-selectmenu-button-open": "ui-corner-" + (direction ? "top" : "tl"),
                        "ui-selectmenu-button-closed": "ui-corner-" + (direction ? "top" : "left")
                    },
                    last: {
                        "ui-selectmenu-button-open": direction ? "" : "ui-corner-tr",
                        "ui-selectmenu-button-closed": "ui-corner-" + (direction ? "bottom" : "right")
                    },
                    only: {
                        "ui-selectmenu-button-open": "ui-corner-top",
                        "ui-selectmenu-button-closed": "ui-corner-all"
                    }
                }[position]
            };
        },
        _resolveClassesValues: function(classes, instance) {
            var result = {};
            $.each(classes, function(key) {
                var current = instance.options.classes[key] || "";
                current = String.prototype.trim.call(current.replace(controlgroupCornerRegex, ""));
                result[key] = (current + " " + classes[key]).replace(/\s+/g, " ");
            });
            return result;
        },
        _setOption: function(key, value) {
            if (key === "direction") {
                this._removeClass("ui-controlgroup-" + this.options.direction);
            }
            this._super(key, value);
            if (key === "disabled") {
                this._callChildMethod(value ? "disable" : "enable");
                return;
            }
            this.refresh();
        },
        refresh: function() {
            var children, that = this;
            this._addClass("ui-controlgroup ui-controlgroup-" + this.options.direction);
            if (this.options.direction === "horizontal") {
                this._addClass(null, "ui-helper-clearfix");
            }
            this._initWidgets();
            children = this.childWidgets;
            if (this.options.onlyVisible) {
                children = children.filter(":visible");
            }
            if (children.length) {
                $.each([ "first", "last" ], function(index, value) {
                    var instance = children[value]().data("ui-controlgroup-data");
                    if (instance && that["_" + instance.widgetName + "Options"]) {
                        var options = that["_" + instance.widgetName + "Options"](children.length === 1 ? "only" : value);
                        options.classes = that._resolveClassesValues(options.classes, instance);
                        instance.element[instance.widgetName](options);
                    } else {
                        that._updateCornerClass(children[value](), value);
                    }
                });
                this._callChildMethod("refresh");
            }
        }
    });
    $.widget("ui.checkboxradio", [ $.ui.formResetMixin, {
        version: "1.13.1",
        options: {
            disabled: null,
            label: null,
            icon: true,
            classes: {
                "ui-checkboxradio-label": "ui-corner-all",
                "ui-checkboxradio-icon": "ui-corner-all"
            }
        },
        _getCreateOptions: function() {
            var disabled, labels;
            var that = this;
            var options = this._super() || {};
            this._readType();
            labels = this.element.labels();
            this.label = $(labels[labels.length - 1]);
            if (!this.label.length) {
                $.error("No label found for checkboxradio widget");
            }
            this.originalLabel = "";
            this.label.contents().not(this.element[0]).each(function() {
                that.originalLabel += this.nodeType === 3 ? $(this).text() : this.outerHTML;
            });
            if (this.originalLabel) {
                options.label = this.originalLabel;
            }
            disabled = this.element[0].disabled;
            if (disabled != null) {
                options.disabled = disabled;
            }
            return options;
        },
        _create: function() {
            var checked = this.element[0].checked;
            this._bindFormResetHandler();
            if (this.options.disabled == null) {
                this.options.disabled = this.element[0].disabled;
            }
            this._setOption("disabled", this.options.disabled);
            this._addClass("ui-checkboxradio", "ui-helper-hidden-accessible");
            this._addClass(this.label, "ui-checkboxradio-label", "ui-button ui-widget");
            if (this.type === "radio") {
                this._addClass(this.label, "ui-checkboxradio-radio-label");
            }
            if (this.options.label && this.options.label !== this.originalLabel) {
                this._updateLabel();
            } else if (this.originalLabel) {
                this.options.label = this.originalLabel;
            }
            this._enhance();
            if (checked) {
                this._addClass(this.label, "ui-checkboxradio-checked", "ui-state-active");
            }
            this._on({
                change: "_toggleClasses",
                focus: function() {
                    this._addClass(this.label, null, "ui-state-focus ui-visual-focus");
                },
                blur: function() {
                    this._removeClass(this.label, null, "ui-state-focus ui-visual-focus");
                }
            });
        },
        _readType: function() {
            var nodeName = this.element[0].nodeName.toLowerCase();
            this.type = this.element[0].type;
            if (nodeName !== "input" || !/radio|checkbox/.test(this.type)) {
                $.error("Can't create checkboxradio on element.nodeName=" + nodeName + " and element.type=" + this.type);
            }
        },
        _enhance: function() {
            this._updateIcon(this.element[0].checked);
        },
        widget: function() {
            return this.label;
        },
        _getRadioGroup: function() {
            var group;
            var name = this.element[0].name;
            var nameSelector = "input[name='" + $.escapeSelector(name) + "']";
            if (!name) {
                return $([]);
            }
            if (this.form.length) {
                group = $(this.form[0].elements).filter(nameSelector);
            } else {
                group = $(nameSelector).filter(function() {
                    return $(this)._form().length === 0;
                });
            }
            return group.not(this.element);
        },
        _toggleClasses: function() {
            var checked = this.element[0].checked;
            this._toggleClass(this.label, "ui-checkboxradio-checked", "ui-state-active", checked);
            if (this.options.icon && this.type === "checkbox") {
                this._toggleClass(this.icon, null, "ui-icon-check ui-state-checked", checked)._toggleClass(this.icon, null, "ui-icon-blank", !checked);
            }
            if (this.type === "radio") {
                this._getRadioGroup().each(function() {
                    var instance = $(this).checkboxradio("instance");
                    if (instance) {
                        instance._removeClass(instance.label, "ui-checkboxradio-checked", "ui-state-active");
                    }
                });
            }
        },
        _destroy: function() {
            this._unbindFormResetHandler();
            if (this.icon) {
                this.icon.remove();
                this.iconSpace.remove();
            }
        },
        _setOption: function(key, value) {
            if (key === "label" && !value) {
                return;
            }
            this._super(key, value);
            if (key === "disabled") {
                this._toggleClass(this.label, null, "ui-state-disabled", value);
                this.element[0].disabled = value;
                return;
            }
            this.refresh();
        },
        _updateIcon: function(checked) {
            var toAdd = "ui-icon ui-icon-background ";
            if (this.options.icon) {
                if (!this.icon) {
                    this.icon = $("<span>");
                    this.iconSpace = $("<span> </span>");
                    this._addClass(this.iconSpace, "ui-checkboxradio-icon-space");
                }
                if (this.type === "checkbox") {
                    toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank";
                    this._removeClass(this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check");
                } else {
                    toAdd += "ui-icon-blank";
                }
                this._addClass(this.icon, "ui-checkboxradio-icon", toAdd);
                if (!checked) {
                    this._removeClass(this.icon, null, "ui-icon-check ui-state-checked");
                }
                this.icon.prependTo(this.label).after(this.iconSpace);
            } else if (this.icon !== undefined) {
                this.icon.remove();
                this.iconSpace.remove();
                delete this.icon;
            }
        },
        _updateLabel: function() {
            var contents = this.label.contents().not(this.element[0]);
            if (this.icon) {
                contents = contents.not(this.icon[0]);
            }
            if (this.iconSpace) {
                contents = contents.not(this.iconSpace[0]);
            }
            contents.remove();
            this.label.append(this.options.label);
        },
        refresh: function() {
            var checked = this.element[0].checked, isDisabled = this.element[0].disabled;
            this._updateIcon(checked);
            this._toggleClass(this.label, "ui-checkboxradio-checked", "ui-state-active", checked);
            if (this.options.label !== null) {
                this._updateLabel();
            }
            if (isDisabled !== this.options.disabled) {
                this._setOptions({
                    disabled: isDisabled
                });
            }
        }
    } ]);
    var widgetsCheckboxradio = $.ui.checkboxradio;
    $.widget("ui.button", {
        version: "1.13.1",
        defaultElement: "<button>",
        options: {
            classes: {
                "ui-button": "ui-corner-all"
            },
            disabled: null,
            icon: null,
            iconPosition: "beginning",
            label: null,
            showLabel: true
        },
        _getCreateOptions: function() {
            var disabled, options = this._super() || {};
            this.isInput = this.element.is("input");
            disabled = this.element[0].disabled;
            if (disabled != null) {
                options.disabled = disabled;
            }
            this.originalLabel = this.isInput ? this.element.val() : this.element.html();
            if (this.originalLabel) {
                options.label = this.originalLabel;
            }
            return options;
        },
        _create: function() {
            if (!this.option.showLabel & !this.options.icon) {
                this.options.showLabel = true;
            }
            if (this.options.disabled == null) {
                this.options.disabled = this.element[0].disabled || false;
            }
            this.hasTitle = !!this.element.attr("title");
            if (this.options.label && this.options.label !== this.originalLabel) {
                if (this.isInput) {
                    this.element.val(this.options.label);
                } else {
                    this.element.html(this.options.label);
                }
            }
            this._addClass("ui-button", "ui-widget");
            this._setOption("disabled", this.options.disabled);
            this._enhance();
            if (this.element.is("a")) {
                this._on({
                    keyup: function(event) {
                        if (event.keyCode === $.ui.keyCode.SPACE) {
                            event.preventDefault();
                            if (this.element[0].click) {
                                this.element[0].click();
                            } else {
                                this.element.trigger("click");
                            }
                        }
                    }
                });
            }
        },
        _enhance: function() {
            if (!this.element.is("button")) {
                this.element.attr("role", "button");
            }
            if (this.options.icon) {
                this._updateIcon("icon", this.options.icon);
                this._updateTooltip();
            }
        },
        _updateTooltip: function() {
            this.title = this.element.attr("title");
            if (!this.options.showLabel && !this.title) {
                this.element.attr("title", this.options.label);
            }
        },
        _updateIcon: function(option, value) {
            var icon = option !== "iconPosition", position = icon ? this.options.iconPosition : value, displayBlock = position === "top" || position === "bottom";
            if (!this.icon) {
                this.icon = $("<span>");
                this._addClass(this.icon, "ui-button-icon", "ui-icon");
                if (!this.options.showLabel) {
                    this._addClass("ui-button-icon-only");
                }
            } else if (icon) {
                this._removeClass(this.icon, null, this.options.icon);
            }
            if (icon) {
                this._addClass(this.icon, null, value);
            }
            this._attachIcon(position);
            if (displayBlock) {
                this._addClass(this.icon, null, "ui-widget-icon-block");
                if (this.iconSpace) {
                    this.iconSpace.remove();
                }
            } else {
                if (!this.iconSpace) {
                    this.iconSpace = $("<span> </span>");
                    this._addClass(this.iconSpace, "ui-button-icon-space");
                }
                this._removeClass(this.icon, null, "ui-wiget-icon-block");
                this._attachIconSpace(position);
            }
        },
        _destroy: function() {
            this.element.removeAttr("role");
            if (this.icon) {
                this.icon.remove();
            }
            if (this.iconSpace) {
                this.iconSpace.remove();
            }
            if (!this.hasTitle) {
                this.element.removeAttr("title");
            }
        },
        _attachIconSpace: function(iconPosition) {
            this.icon[/^(?:end|bottom)/.test(iconPosition) ? "before" : "after"](this.iconSpace);
        },
        _attachIcon: function(iconPosition) {
            this.element[/^(?:end|bottom)/.test(iconPosition) ? "append" : "prepend"](this.icon);
        },
        _setOptions: function(options) {
            var newShowLabel = options.showLabel === undefined ? this.options.showLabel : options.showLabel, newIcon = options.icon === undefined ? this.options.icon : options.icon;
            if (!newShowLabel && !newIcon) {
                options.showLabel = true;
            }
            this._super(options);
        },
        _setOption: function(key, value) {
            if (key === "icon") {
                if (value) {
                    this._updateIcon(key, value);
                } else if (this.icon) {
                    this.icon.remove();
                    if (this.iconSpace) {
                        this.iconSpace.remove();
                    }
                }
            }
            if (key === "iconPosition") {
                this._updateIcon(key, value);
            }
            if (key === "showLabel") {
                this._toggleClass("ui-button-icon-only", null, !value);
                this._updateTooltip();
            }
            if (key === "label") {
                if (this.isInput) {
                    this.element.val(value);
                } else {
                    this.element.html(value);
                    if (this.icon) {
                        this._attachIcon(this.options.iconPosition);
                        this._attachIconSpace(this.options.iconPosition);
                    }
                }
            }
            this._super(key, value);
            if (key === "disabled") {
                this._toggleClass(null, "ui-state-disabled", value);
                this.element[0].disabled = value;
                if (value) {
                    this.element.trigger("blur");
                }
            }
        },
        refresh: function() {
            var isDisabled = this.element.is("input, button") ? this.element[0].disabled : this.element.hasClass("ui-button-disabled");
            if (isDisabled !== this.options.disabled) {
                this._setOptions({
                    disabled: isDisabled
                });
            }
            this._updateTooltip();
        }
    });
    if ($.uiBackCompat !== false) {
        $.widget("ui.button", $.ui.button, {
            options: {
                text: true,
                icons: {
                    primary: null,
                    secondary: null
                }
            },
            _create: function() {
                if (this.options.showLabel && !this.options.text) {
                    this.options.showLabel = this.options.text;
                }
                if (!this.options.showLabel && this.options.text) {
                    this.options.text = this.options.showLabel;
                }
                if (!this.options.icon && (this.options.icons.primary || this.options.icons.secondary)) {
                    if (this.options.icons.primary) {
                        this.options.icon = this.options.icons.primary;
                    } else {
                        this.options.icon = this.options.icons.secondary;
                        this.options.iconPosition = "end";
                    }
                } else if (this.options.icon) {
                    this.options.icons.primary = this.options.icon;
                }
                this._super();
            },
            _setOption: function(key, value) {
                if (key === "text") {
                    this._super("showLabel", value);
                    return;
                }
                if (key === "showLabel") {
                    this.options.text = value;
                }
                if (key === "icon") {
                    this.options.icons.primary = value;
                }
                if (key === "icons") {
                    if (value.primary) {
                        this._super("icon", value.primary);
                        this._super("iconPosition", "beginning");
                    } else if (value.secondary) {
                        this._super("icon", value.secondary);
                        this._super("iconPosition", "end");
                    }
                }
                this._superApply(arguments);
            }
        });
        $.fn.button = function(orig) {
            return function(options) {
                var isMethodCall = typeof options === "string";
                var args = Array.prototype.slice.call(arguments, 1);
                var returnValue = this;
                if (isMethodCall) {
                    if (!this.length && options === "instance") {
                        returnValue = undefined;
                    } else {
                        this.each(function() {
                            var methodValue;
                            var type = $(this).attr("type");
                            var name = type !== "checkbox" && type !== "radio" ? "button" : "checkboxradio";
                            var instance = $.data(this, "ui-" + name);
                            if (options === "instance") {
                                returnValue = instance;
                                return false;
                            }
                            if (!instance) {
                                return $.error("cannot call methods on button" + " prior to initialization; " + "attempted to call method '" + options + "'");
                            }
                            if (typeof instance[options] !== "function" || options.charAt(0) === "_") {
                                return $.error("no such method '" + options + "' for button" + " widget instance");
                            }
                            methodValue = instance[options].apply(instance, args);
                            if (methodValue !== instance && methodValue !== undefined) {
                                returnValue = methodValue && methodValue.jquery ? returnValue.pushStack(methodValue.get()) : methodValue;
                                return false;
                            }
                        });
                    }
                } else {
                    if (args.length) {
                        options = $.widget.extend.apply(null, [ options ].concat(args));
                    }
                    this.each(function() {
                        var type = $(this).attr("type");
                        var name = type !== "checkbox" && type !== "radio" ? "button" : "checkboxradio";
                        var instance = $.data(this, "ui-" + name);
                        if (instance) {
                            instance.option(options || {});
                            if (instance._init) {
                                instance._init();
                            }
                        } else {
                            if (name === "button") {
                                orig.call($(this), options);
                                return;
                            }
                            $(this).checkboxradio($.extend({
                                icon: false
                            }, options));
                        }
                    });
                }
                return returnValue;
            };
        }($.fn.button);
        $.fn.buttonset = function() {
            if (!$.ui.controlgroup) {
                $.error("Controlgroup widget missing");
            }
            if (arguments[0] === "option" && arguments[1] === "items" && arguments[2]) {
                return this.controlgroup.apply(this, [ arguments[0], "items.button", arguments[2] ]);
            }
            if (arguments[0] === "option" && arguments[1] === "items") {
                return this.controlgroup.apply(this, [ arguments[0], "items.button" ]);
            }
            if (typeof arguments[0] === "object" && arguments[0].items) {
                arguments[0].items = {
                    button: arguments[0].items
                };
            }
            return this.controlgroup.apply(this, arguments);
        };
    }
    var widgetsButton = $.ui.button;
    $.extend($.ui, {
        datepicker: {
            version: "1.13.1"
        }
    });
    var datepicker_instActive;
    function datepicker_getZindex(elem) {
        var position, value;
        while (elem.length && elem[0] !== document) {
            position = elem.css("position");
            if (position === "absolute" || position === "relative" || position === "fixed") {
                value = parseInt(elem.css("zIndex"), 10);
                if (!isNaN(value) && value !== 0) {
                    return value;
                }
            }
            elem = elem.parent();
        }
        return 0;
    }
    function Datepicker() {
        this._curInst = null;
        this._keyEvent = false;
        this._disabledInputs = [];
        this._datepickerShowing = false;
        this._inDialog = false;
        this._mainDivId = "ui-datepicker-div";
        this._inlineClass = "ui-datepicker-inline";
        this._appendClass = "ui-datepicker-append";
        this._triggerClass = "ui-datepicker-trigger";
        this._dialogClass = "ui-datepicker-dialog";
        this._disableClass = "ui-datepicker-disabled";
        this._unselectableClass = "ui-datepicker-unselectable";
        this._currentClass = "ui-datepicker-current-day";
        this._dayOverClass = "ui-datepicker-days-cell-over";
        this.regional = [];
        this.regional[""] = {
            closeText: "Done",
            prevText: "Prev",
            nextText: "Next",
            currentText: "Today",
            monthNames: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ],
            monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ],
            dayNames: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ],
            dayNamesShort: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ],
            dayNamesMin: [ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ],
            weekHeader: "Wk",
            dateFormat: "mm/dd/yy",
            firstDay: 0,
            isRTL: false,
            showMonthAfterYear: false,
            yearSuffix: "",
            selectMonthLabel: "Select month",
            selectYearLabel: "Select year"
        };
        this._defaults = {
            showOn: "focus",
            showAnim: "fadeIn",
            showOptions: {},
            defaultDate: null,
            appendText: "",
            buttonText: "...",
            buttonImage: "",
            buttonImageOnly: false,
            hideIfNoPrevNext: false,
            navigationAsDateFormat: false,
            gotoCurrent: false,
            changeMonth: false,
            changeYear: false,
            yearRange: "c-10:c+10",
            showOtherMonths: false,
            selectOtherMonths: false,
            showWeek: false,
            calculateWeek: this.iso8601Week,
            shortYearCutoff: "+10",
            minDate: null,
            maxDate: null,
            duration: "fast",
            beforeShowDay: null,
            beforeShow: null,
            onSelect: null,
            onChangeMonthYear: null,
            onClose: null,
            onUpdateDatepicker: null,
            numberOfMonths: 1,
            showCurrentAtPos: 0,
            stepMonths: 1,
            stepBigMonths: 12,
            altField: "",
            altFormat: "",
            constrainInput: true,
            showButtonPanel: false,
            autoSize: false,
            disabled: false
        };
        $.extend(this._defaults, this.regional[""]);
        this.regional.en = $.extend(true, {}, this.regional[""]);
        this.regional["en-US"] = $.extend(true, {}, this.regional.en);
        this.dpDiv = datepicker_bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"));
    }
    $.extend(Datepicker.prototype, {
        markerClassName: "hasDatepicker",
        maxRows: 4,
        _widgetDatepicker: function() {
            return this.dpDiv;
        },
        setDefaults: function(settings) {
            datepicker_extendRemove(this._defaults, settings || {});
            return this;
        },
        _attachDatepicker: function(target, settings) {
            var nodeName, inline, inst;
            nodeName = target.nodeName.toLowerCase();
            inline = nodeName === "div" || nodeName === "span";
            if (!target.id) {
                this.uuid += 1;
                target.id = "dp" + this.uuid;
            }
            inst = this._newInst($(target), inline);
            inst.settings = $.extend({}, settings || {});
            if (nodeName === "input") {
                this._connectDatepicker(target, inst);
            } else if (inline) {
                this._inlineDatepicker(target, inst);
            }
        },
        _newInst: function(target, inline) {
            var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1");
            return {
                id: id,
                input: target,
                selectedDay: 0,
                selectedMonth: 0,
                selectedYear: 0,
                drawMonth: 0,
                drawYear: 0,
                inline: inline,
                dpDiv: !inline ? this.dpDiv : datepicker_bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"))
            };
        },
        _connectDatepicker: function(target, inst) {
            var input = $(target);
            inst.append = $([]);
            inst.trigger = $([]);
            if (input.hasClass(this.markerClassName)) {
                return;
            }
            this._attachments(input, inst);
            input.addClass(this.markerClassName).on("keydown", this._doKeyDown).on("keypress", this._doKeyPress).on("keyup", this._doKeyUp);
            this._autoSize(inst);
            $.data(target, "datepicker", inst);
            if (inst.settings.disabled) {
                this._disableDatepicker(target);
            }
        },
        _attachments: function(input, inst) {
            var showOn, buttonText, buttonImage, appendText = this._get(inst, "appendText"), isRTL = this._get(inst, "isRTL");
            if (inst.append) {
                inst.append.remove();
            }
            if (appendText) {
                inst.append = $("<span>").addClass(this._appendClass).text(appendText);
                input[isRTL ? "before" : "after"](inst.append);
            }
            input.off("focus", this._showDatepicker);
            if (inst.trigger) {
                inst.trigger.remove();
            }
            showOn = this._get(inst, "showOn");
            if (showOn === "focus" || showOn === "both") {
                input.on("focus", this._showDatepicker);
            }
            if (showOn === "button" || showOn === "both") {
                buttonText = this._get(inst, "buttonText");
                buttonImage = this._get(inst, "buttonImage");
                if (this._get(inst, "buttonImageOnly")) {
                    inst.trigger = $("<img>").addClass(this._triggerClass).attr({
                        src: buttonImage,
                        alt: buttonText,
                        title: buttonText
                    });
                } else {
                    inst.trigger = $("<button type='button'>").addClass(this._triggerClass);
                    if (buttonImage) {
                        inst.trigger.html($("<img>").attr({
                            src: buttonImage,
                            alt: buttonText,
                            title: buttonText
                        }));
                    } else {
                        inst.trigger.text(buttonText);
                    }
                }
                input[isRTL ? "before" : "after"](inst.trigger);
                inst.trigger.on("click", function() {
                    if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) {
                        $.datepicker._hideDatepicker();
                    } else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) {
                        $.datepicker._hideDatepicker();
                        $.datepicker._showDatepicker(input[0]);
                    } else {
                        $.datepicker._showDatepicker(input[0]);
                    }
                    return false;
                });
            }
        },
        _autoSize: function(inst) {
            if (this._get(inst, "autoSize") && !inst.inline) {
                var findMax, max, maxI, i, date = new Date(2009, 12 - 1, 20), dateFormat = this._get(inst, "dateFormat");
                if (dateFormat.match(/[DM]/)) {
                    findMax = function(names) {
                        max = 0;
                        maxI = 0;
                        for (i = 0; i < names.length; i++) {
                            if (names[i].length > max) {
                                max = names[i].length;
                                maxI = i;
                            }
                        }
                        return maxI;
                    };
                    date.setMonth(findMax(this._get(inst, dateFormat.match(/MM/) ? "monthNames" : "monthNamesShort")));
                    date.setDate(findMax(this._get(inst, dateFormat.match(/DD/) ? "dayNames" : "dayNamesShort")) + 20 - date.getDay());
                }
                inst.input.attr("size", this._formatDate(inst, date).length);
            }
        },
        _inlineDatepicker: function(target, inst) {
            var divSpan = $(target);
            if (divSpan.hasClass(this.markerClassName)) {
                return;
            }
            divSpan.addClass(this.markerClassName).append(inst.dpDiv);
            $.data(target, "datepicker", inst);
            this._setDate(inst, this._getDefaultDate(inst), true);
            this._updateDatepicker(inst);
            this._updateAlternate(inst);
            if (inst.settings.disabled) {
                this._disableDatepicker(target);
            }
            inst.dpDiv.css("display", "block");
        },
        _dialogDatepicker: function(input, date, onSelect, settings, pos) {
            var id, browserWidth, browserHeight, scrollX, scrollY, inst = this._dialogInst;
            if (!inst) {
                this.uuid += 1;
                id = "dp" + this.uuid;
                this._dialogInput = $("<input type='text' id='" + id + "' style='position: absolute; top: -100px; width: 0px;'/>");
                this._dialogInput.on("keydown", this._doKeyDown);
                $("body").append(this._dialogInput);
                inst = this._dialogInst = this._newInst(this._dialogInput, false);
                inst.settings = {};
                $.data(this._dialogInput[0], "datepicker", inst);
            }
            datepicker_extendRemove(inst.settings, settings || {});
            date = date && date.constructor === Date ? this._formatDate(inst, date) : date;
            this._dialogInput.val(date);
            this._pos = pos ? pos.length ? pos : [ pos.pageX, pos.pageY ] : null;
            if (!this._pos) {
                browserWidth = document.documentElement.clientWidth;
                browserHeight = document.documentElement.clientHeight;
                scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
                scrollY = document.documentElement.scrollTop || document.body.scrollTop;
                this._pos = [ browserWidth / 2 - 100 + scrollX, browserHeight / 2 - 150 + scrollY ];
            }
            this._dialogInput.css("left", this._pos[0] + 20 + "px").css("top", this._pos[1] + "px");
            inst.settings.onSelect = onSelect;
            this._inDialog = true;
            this.dpDiv.addClass(this._dialogClass);
            this._showDatepicker(this._dialogInput[0]);
            if ($.blockUI) {
                $.blockUI(this.dpDiv);
            }
            $.data(this._dialogInput[0], "datepicker", inst);
            return this;
        },
        _destroyDatepicker: function(target) {
            var nodeName, $target = $(target), inst = $.data(target, "datepicker");
            if (!$target.hasClass(this.markerClassName)) {
                return;
            }
            nodeName = target.nodeName.toLowerCase();
            $.removeData(target, "datepicker");
            if (nodeName === "input") {
                inst.append.remove();
                inst.trigger.remove();
                $target.removeClass(this.markerClassName).off("focus", this._showDatepicker).off("keydown", this._doKeyDown).off("keypress", this._doKeyPress).off("keyup", this._doKeyUp);
            } else if (nodeName === "div" || nodeName === "span") {
                $target.removeClass(this.markerClassName).empty();
            }
            if (datepicker_instActive === inst) {
                datepicker_instActive = null;
                this._curInst = null;
            }
        },
        _enableDatepicker: function(target) {
            var nodeName, inline, $target = $(target), inst = $.data(target, "datepicker");
            if (!$target.hasClass(this.markerClassName)) {
                return;
            }
            nodeName = target.nodeName.toLowerCase();
            if (nodeName === "input") {
                target.disabled = false;
                inst.trigger.filter("button").each(function() {
                    this.disabled = false;
                }).end().filter("img").css({
                    opacity: "1.0",
                    cursor: ""
                });
            } else if (nodeName === "div" || nodeName === "span") {
                inline = $target.children("." + this._inlineClass);
                inline.children().removeClass("ui-state-disabled");
                inline.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled", false);
            }
            this._disabledInputs = $.map(this._disabledInputs, function(value) {
                return value === target ? null : value;
            });
        },
        _disableDatepicker: function(target) {
            var nodeName, inline, $target = $(target), inst = $.data(target, "datepicker");
            if (!$target.hasClass(this.markerClassName)) {
                return;
            }
            nodeName = target.nodeName.toLowerCase();
            if (nodeName === "input") {
                target.disabled = true;
                inst.trigger.filter("button").each(function() {
                    this.disabled = true;
                }).end().filter("img").css({
                    opacity: "0.5",
                    cursor: "default"
                });
            } else if (nodeName === "div" || nodeName === "span") {
                inline = $target.children("." + this._inlineClass);
                inline.children().addClass("ui-state-disabled");
                inline.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled", true);
            }
            this._disabledInputs = $.map(this._disabledInputs, function(value) {
                return value === target ? null : value;
            });
            this._disabledInputs[this._disabledInputs.length] = target;
        },
        _isDisabledDatepicker: function(target) {
            if (!target) {
                return false;
            }
            for (var i = 0; i < this._disabledInputs.length; i++) {
                if (this._disabledInputs[i] === target) {
                    return true;
                }
            }
            return false;
        },
        _getInst: function(target) {
            try {
                return $.data(target, "datepicker");
            } catch (err) {
                throw "Missing instance data for this datepicker";
            }
        },
        _optionDatepicker: function(target, name, value) {
            var settings, date, minDate, maxDate, inst = this._getInst(target);
            if (arguments.length === 2 && typeof name === "string") {
                return name === "defaults" ? $.extend({}, $.datepicker._defaults) : inst ? name === "all" ? $.extend({}, inst.settings) : this._get(inst, name) : null;
            }
            settings = name || {};
            if (typeof name === "string") {
                settings = {};
                settings[name] = value;
            }
            if (inst) {
                if (this._curInst === inst) {
                    this._hideDatepicker();
                }
                date = this._getDateDatepicker(target, true);
                minDate = this._getMinMaxDate(inst, "min");
                maxDate = this._getMinMaxDate(inst, "max");
                datepicker_extendRemove(inst.settings, settings);
                if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) {
                    inst.settings.minDate = this._formatDate(inst, minDate);
                }
                if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) {
                    inst.settings.maxDate = this._formatDate(inst, maxDate);
                }
                if ("disabled" in settings) {
                    if (settings.disabled) {
                        this._disableDatepicker(target);
                    } else {
                        this._enableDatepicker(target);
                    }
                }
                this._attachments($(target), inst);
                this._autoSize(inst);
                this._setDate(inst, date);
                this._updateAlternate(inst);
                this._updateDatepicker(inst);
            }
        },
        _changeDatepicker: function(target, name, value) {
            this._optionDatepicker(target, name, value);
        },
        _refreshDatepicker: function(target) {
            var inst = this._getInst(target);
            if (inst) {
                this._updateDatepicker(inst);
            }
        },
        _setDateDatepicker: function(target, date) {
            var inst = this._getInst(target);
            if (inst) {
                this._setDate(inst, date);
                this._updateDatepicker(inst);
                this._updateAlternate(inst);
            }
        },
        _getDateDatepicker: function(target, noDefault) {
            var inst = this._getInst(target);
            if (inst && !inst.inline) {
                this._setDateFromField(inst, noDefault);
            }
            return inst ? this._getDate(inst) : null;
        },
        _doKeyDown: function(event) {
            var onSelect, dateStr, sel, inst = $.datepicker._getInst(event.target), handled = true, isRTL = inst.dpDiv.is(".ui-datepicker-rtl");
            inst._keyEvent = true;
            if ($.datepicker._datepickerShowing) {
                switch (event.keyCode) {
                  case 9:
                    $.datepicker._hideDatepicker();
                    handled = false;
                    break;

                  case 13:
                    sel = $("td." + $.datepicker._dayOverClass + ":not(." + $.datepicker._currentClass + ")", inst.dpDiv);
                    if (sel[0]) {
                        $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
                    }
                    onSelect = $.datepicker._get(inst, "onSelect");
                    if (onSelect) {
                        dateStr = $.datepicker._formatDate(inst);
                        onSelect.apply(inst.input ? inst.input[0] : null, [ dateStr, inst ]);
                    } else {
                        $.datepicker._hideDatepicker();
                    }
                    return false;

                  case 27:
                    $.datepicker._hideDatepicker();
                    break;

                  case 33:
                    $.datepicker._adjustDate(event.target, event.ctrlKey ? -$.datepicker._get(inst, "stepBigMonths") : -$.datepicker._get(inst, "stepMonths"), "M");
                    break;

                  case 34:
                    $.datepicker._adjustDate(event.target, event.ctrlKey ? +$.datepicker._get(inst, "stepBigMonths") : +$.datepicker._get(inst, "stepMonths"), "M");
                    break;

                  case 35:
                    if (event.ctrlKey || event.metaKey) {
                        $.datepicker._clearDate(event.target);
                    }
                    handled = event.ctrlKey || event.metaKey;
                    break;

                  case 36:
                    if (event.ctrlKey || event.metaKey) {
                        $.datepicker._gotoToday(event.target);
                    }
                    handled = event.ctrlKey || event.metaKey;
                    break;

                  case 37:
                    if (event.ctrlKey || event.metaKey) {
                        $.datepicker._adjustDate(event.target, isRTL ? +1 : -1, "D");
                    }
                    handled = event.ctrlKey || event.metaKey;
                    if (event.originalEvent.altKey) {
                        $.datepicker._adjustDate(event.target, event.ctrlKey ? -$.datepicker._get(inst, "stepBigMonths") : -$.datepicker._get(inst, "stepMonths"), "M");
                    }
                    break;

                  case 38:
                    if (event.ctrlKey || event.metaKey) {
                        $.datepicker._adjustDate(event.target, -7, "D");
                    }
                    handled = event.ctrlKey || event.metaKey;
                    break;

                  case 39:
                    if (event.ctrlKey || event.metaKey) {
                        $.datepicker._adjustDate(event.target, isRTL ? -1 : +1, "D");
                    }
                    handled = event.ctrlKey || event.metaKey;
                    if (event.originalEvent.altKey) {
                        $.datepicker._adjustDate(event.target, event.ctrlKey ? +$.datepicker._get(inst, "stepBigMonths") : +$.datepicker._get(inst, "stepMonths"), "M");
                    }
                    break;

                  case 40:
                    if (event.ctrlKey || event.metaKey) {
                        $.datepicker._adjustDate(event.target, +7, "D");
                    }
                    handled = event.ctrlKey || event.metaKey;
                    break;

                  default:
                    handled = false;
                }
            } else if (event.keyCode === 36 && event.ctrlKey) {
                $.datepicker._showDatepicker(this);
            } else {
                handled = false;
            }
            if (handled) {
                event.preventDefault();
                event.stopPropagation();
            }
        },
        _doKeyPress: function(event) {
            var chars, chr, inst = $.datepicker._getInst(event.target);
            if ($.datepicker._get(inst, "constrainInput")) {
                chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat"));
                chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode);
                return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1);
            }
        },
        _doKeyUp: function(event) {
            var date, inst = $.datepicker._getInst(event.target);
            if (inst.input.val() !== inst.lastVal) {
                try {
                    date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"), inst.input ? inst.input.val() : null, $.datepicker._getFormatConfig(inst));
                    if (date) {
                        $.datepicker._setDateFromField(inst);
                        $.datepicker._updateAlternate(inst);
                        $.datepicker._updateDatepicker(inst);
                    }
                } catch (err) {}
            }
            return true;
        },
        _showDatepicker: function(input) {
            input = input.target || input;
            if (input.nodeName.toLowerCase() !== "input") {
                input = $("input", input.parentNode)[0];
            }
            if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) {
                return;
            }
            var inst, beforeShow, beforeShowSettings, isFixed, offset, showAnim, duration;
            inst = $.datepicker._getInst(input);
            if ($.datepicker._curInst && $.datepicker._curInst !== inst) {
                $.datepicker._curInst.dpDiv.stop(true, true);
                if (inst && $.datepicker._datepickerShowing) {
                    $.datepicker._hideDatepicker($.datepicker._curInst.input[0]);
                }
            }
            beforeShow = $.datepicker._get(inst, "beforeShow");
            beforeShowSettings = beforeShow ? beforeShow.apply(input, [ input, inst ]) : {};
            if (beforeShowSettings === false) {
                return;
            }
            datepicker_extendRemove(inst.settings, beforeShowSettings);
            inst.lastVal = null;
            $.datepicker._lastInput = input;
            $.datepicker._setDateFromField(inst);
            if ($.datepicker._inDialog) {
                input.value = "";
            }
            if (!$.datepicker._pos) {
                $.datepicker._pos = $.datepicker._findPos(input);
                $.datepicker._pos[1] += input.offsetHeight;
            }
            isFixed = false;
            $(input).parents().each(function() {
                isFixed |= $(this).css("position") === "fixed";
                return !isFixed;
            });
            offset = {
                left: $.datepicker._pos[0],
                top: $.datepicker._pos[1]
            };
            $.datepicker._pos = null;
            inst.dpDiv.empty();
            inst.dpDiv.css({
                position: "absolute",
                display: "block",
                top: "-1000px"
            });
            $.datepicker._updateDatepicker(inst);
            offset = $.datepicker._checkOffset(inst, offset, isFixed);
            inst.dpDiv.css({
                position: $.datepicker._inDialog && $.blockUI ? "static" : isFixed ? "fixed" : "absolute",
                display: "none",
                left: offset.left + "px",
                top: offset.top + "px"
            });
            if (!inst.inline) {
                showAnim = $.datepicker._get(inst, "showAnim");
                duration = $.datepicker._get(inst, "duration");
                inst.dpDiv.css("z-index", datepicker_getZindex($(input)) + 1);
                $.datepicker._datepickerShowing = true;
                if ($.effects && $.effects.effect[showAnim]) {
                    inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration);
                } else {
                    inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
                }
                if ($.datepicker._shouldFocusInput(inst)) {
                    inst.input.trigger("focus");
                }
                $.datepicker._curInst = inst;
            }
        },
        _updateDatepicker: function(inst) {
            this.maxRows = 4;
            datepicker_instActive = inst;
            inst.dpDiv.empty().append(this._generateHTML(inst));
            this._attachHandlers(inst);
            var origyearshtml, numMonths = this._getNumberOfMonths(inst), cols = numMonths[1], width = 17, activeCell = inst.dpDiv.find("." + this._dayOverClass + " a"), onUpdateDatepicker = $.datepicker._get(inst, "onUpdateDatepicker");
            if (activeCell.length > 0) {
                datepicker_handleMouseover.apply(activeCell.get(0));
            }
            inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");
            if (cols > 1) {
                inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", width * cols + "em");
            }
            inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") + "Class"]("ui-datepicker-multi");
            inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") + "Class"]("ui-datepicker-rtl");
            if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput(inst)) {
                inst.input.trigger("focus");
            }
            if (inst.yearshtml) {
                origyearshtml = inst.yearshtml;
                setTimeout(function() {
                    if (origyearshtml === inst.yearshtml && inst.yearshtml) {
                        inst.dpDiv.find("select.ui-datepicker-year").first().replaceWith(inst.yearshtml);
                    }
                    origyearshtml = inst.yearshtml = null;
                }, 0);
            }
            if (onUpdateDatepicker) {
                onUpdateDatepicker.apply(inst.input ? inst.input[0] : null, [ inst ]);
            }
        },
        _shouldFocusInput: function(inst) {
            return inst.input && inst.input.is(":visible") && !inst.input.is(":disabled") && !inst.input.is(":focus");
        },
        _checkOffset: function(inst, offset, isFixed) {
            var dpWidth = inst.dpDiv.outerWidth(), dpHeight = inst.dpDiv.outerHeight(), inputWidth = inst.input ? inst.input.outerWidth() : 0, inputHeight = inst.input ? inst.input.outerHeight() : 0, viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()), viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
            offset.left -= this._get(inst, "isRTL") ? dpWidth - inputWidth : 0;
            offset.left -= isFixed && offset.left === inst.input.offset().left ? $(document).scrollLeft() : 0;
            offset.top -= isFixed && offset.top === inst.input.offset().top + inputHeight ? $(document).scrollTop() : 0;
            offset.left -= Math.min(offset.left, offset.left + dpWidth > viewWidth && viewWidth > dpWidth ? Math.abs(offset.left + dpWidth - viewWidth) : 0);
            offset.top -= Math.min(offset.top, offset.top + dpHeight > viewHeight && viewHeight > dpHeight ? Math.abs(dpHeight + inputHeight) : 0);
            return offset;
        },
        _findPos: function(obj) {
            var position, inst = this._getInst(obj), isRTL = this._get(inst, "isRTL");
            while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.pseudos.hidden(obj))) {
                obj = obj[isRTL ? "previousSibling" : "nextSibling"];
            }
            position = $(obj).offset();
            return [ position.left, position.top ];
        },
        _hideDatepicker: function(input) {
            var showAnim, duration, postProcess, onClose, inst = this._curInst;
            if (!inst || input && inst !== $.data(input, "datepicker")) {
                return;
            }
            if (this._datepickerShowing) {
                showAnim = this._get(inst, "showAnim");
                duration = this._get(inst, "duration");
                postProcess = function() {
                    $.datepicker._tidyDialog(inst);
                };
                if ($.effects && ($.effects.effect[showAnim] || $.effects[showAnim])) {
                    inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess);
                } else {
                    inst.dpDiv[showAnim === "slideDown" ? "slideUp" : showAnim === "fadeIn" ? "fadeOut" : "hide"](showAnim ? duration : null, postProcess);
                }
                if (!showAnim) {
                    postProcess();
                }
                this._datepickerShowing = false;
                onClose = this._get(inst, "onClose");
                if (onClose) {
                    onClose.apply(inst.input ? inst.input[0] : null, [ inst.input ? inst.input.val() : "", inst ]);
                }
                this._lastInput = null;
                if (this._inDialog) {
                    this._dialogInput.css({
                        position: "absolute",
                        left: "0",
                        top: "-100px"
                    });
                    if ($.blockUI) {
                        $.unblockUI();
                        $("body").append(this.dpDiv);
                    }
                }
                this._inDialog = false;
            }
        },
        _tidyDialog: function(inst) {
            inst.dpDiv.removeClass(this._dialogClass).off(".ui-datepicker-calendar");
        },
        _checkExternalClick: function(event) {
            if (!$.datepicker._curInst) {
                return;
            }
            var $target = $(event.target), inst = $.datepicker._getInst($target[0]);
            if ($target[0].id !== $.datepicker._mainDivId && $target.parents("#" + $.datepicker._mainDivId).length === 0 && !$target.hasClass($.datepicker.markerClassName) && !$target.closest("." + $.datepicker._triggerClass).length && $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) || $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst) {
                $.datepicker._hideDatepicker();
            }
        },
        _adjustDate: function(id, offset, period) {
            var target = $(id), inst = this._getInst(target[0]);
            if (this._isDisabledDatepicker(target[0])) {
                return;
            }
            this._adjustInstDate(inst, offset, period);
            this._updateDatepicker(inst);
        },
        _gotoToday: function(id) {
            var date, target = $(id), inst = this._getInst(target[0]);
            if (this._get(inst, "gotoCurrent") && inst.currentDay) {
                inst.selectedDay = inst.currentDay;
                inst.drawMonth = inst.selectedMonth = inst.currentMonth;
                inst.drawYear = inst.selectedYear = inst.currentYear;
            } else {
                date = new Date();
                inst.selectedDay = date.getDate();
                inst.drawMonth = inst.selectedMonth = date.getMonth();
                inst.drawYear = inst.selectedYear = date.getFullYear();
            }
            this._notifyChange(inst);
            this._adjustDate(target);
        },
        _selectMonthYear: function(id, select, period) {
            var target = $(id), inst = this._getInst(target[0]);
            inst["selected" + (period === "M" ? "Month" : "Year")] = inst["draw" + (period === "M" ? "Month" : "Year")] = parseInt(select.options[select.selectedIndex].value, 10);
            this._notifyChange(inst);
            this._adjustDate(target);
        },
        _selectDay: function(id, month, year, td) {
            var inst, target = $(id);
            if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
                return;
            }
            inst = this._getInst(target[0]);
            inst.selectedDay = inst.currentDay = parseInt($("a", td).attr("data-date"));
            inst.selectedMonth = inst.currentMonth = month;
            inst.selectedYear = inst.currentYear = year;
            this._selectDate(id, this._formatDate(inst, inst.currentDay, inst.currentMonth, inst.currentYear));
        },
        _clearDate: function(id) {
            var target = $(id);
            this._selectDate(target, "");
        },
        _selectDate: function(id, dateStr) {
            var onSelect, target = $(id), inst = this._getInst(target[0]);
            dateStr = dateStr != null ? dateStr : this._formatDate(inst);
            if (inst.input) {
                inst.input.val(dateStr);
            }
            this._updateAlternate(inst);
            onSelect = this._get(inst, "onSelect");
            if (onSelect) {
                onSelect.apply(inst.input ? inst.input[0] : null, [ dateStr, inst ]);
            } else if (inst.input) {
                inst.input.trigger("change");
            }
            if (inst.inline) {
                this._updateDatepicker(inst);
            } else {
                this._hideDatepicker();
                this._lastInput = inst.input[0];
                if (typeof inst.input[0] !== "object") {
                    inst.input.trigger("focus");
                }
                this._lastInput = null;
            }
        },
        _updateAlternate: function(inst) {
            var altFormat, date, dateStr, altField = this._get(inst, "altField");
            if (altField) {
                altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat");
                date = this._getDate(inst);
                dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
                $(document).find(altField).val(dateStr);
            }
        },
        noWeekends: function(date) {
            var day = date.getDay();
            return [ day > 0 && day < 6, "" ];
        },
        iso8601Week: function(date) {
            var time, checkDate = new Date(date.getTime());
            checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
            time = checkDate.getTime();
            checkDate.setMonth(0);
            checkDate.setDate(1);
            return Math.floor(Math.round((time - checkDate) / 864e5) / 7) + 1;
        },
        parseDate: function(format, value, settings) {
            if (format == null || value == null) {
                throw "Invalid arguments";
            }
            value = typeof value === "object" ? value.toString() : value + "";
            if (value === "") {
                return null;
            }
            var iFormat, dim, extra, iValue = 0, shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff, shortYearCutoff = typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp : new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10), dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort, dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames, monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort, monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames, year = -1, month = -1, day = -1, doy = -1, literal = false, date, lookAhead = function(match) {
                var matches = iFormat + 1 < format.length && format.charAt(iFormat + 1) === match;
                if (matches) {
                    iFormat++;
                }
                return matches;
            }, getNumber = function(match) {
                var isDoubled = lookAhead(match), size = match === "@" ? 14 : match === "!" ? 20 : match === "y" && isDoubled ? 4 : match === "o" ? 3 : 2, minSize = match === "y" ? size : 1, digits = new RegExp("^\\d{" + minSize + "," + size + "}"), num = value.substring(iValue).match(digits);
                if (!num) {
                    throw "Missing number at position " + iValue;
                }
                iValue += num[0].length;
                return parseInt(num[0], 10);
            }, getName = function(match, shortNames, longNames) {
                var index = -1, names = $.map(lookAhead(match) ? longNames : shortNames, function(v, k) {
                    return [ [ k, v ] ];
                }).sort(function(a, b) {
                    return -(a[1].length - b[1].length);
                });
                $.each(names, function(i, pair) {
                    var name = pair[1];
                    if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) {
                        index = pair[0];
                        iValue += name.length;
                        return false;
                    }
                });
                if (index !== -1) {
                    return index + 1;
                } else {
                    throw "Unknown name at position " + iValue;
                }
            }, checkLiteral = function() {
                if (value.charAt(iValue) !== format.charAt(iFormat)) {
                    throw "Unexpected literal at position " + iValue;
                }
                iValue++;
            };
            for (iFormat = 0; iFormat < format.length; iFormat++) {
                if (literal) {
                    if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
                        literal = false;
                    } else {
                        checkLiteral();
                    }
                } else {
                    switch (format.charAt(iFormat)) {
                      case "d":
                        day = getNumber("d");
                        break;

                      case "D":
                        getName("D", dayNamesShort, dayNames);
                        break;

                      case "o":
                        doy = getNumber("o");
                        break;

                      case "m":
                        month = getNumber("m");
                        break;

                      case "M":
                        month = getName("M", monthNamesShort, monthNames);
                        break;

                      case "y":
                        year = getNumber("y");
                        break;

                      case "@":
                        date = new Date(getNumber("@"));
                        year = date.getFullYear();
                        month = date.getMonth() + 1;
                        day = date.getDate();
                        break;

                      case "!":
                        date = new Date((getNumber("!") - this._ticksTo1970) / 1e4);
                        year = date.getFullYear();
                        month = date.getMonth() + 1;
                        day = date.getDate();
                        break;

                      case "'":
                        if (lookAhead("'")) {
                            checkLiteral();
                        } else {
                            literal = true;
                        }
                        break;

                      default:
                        checkLiteral();
                    }
                }
            }
            if (iValue < value.length) {
                extra = value.substr(iValue);
                if (!/^\s+/.test(extra)) {
                    throw "Extra/unparsed characters found in date: " + extra;
                }
            }
            if (year === -1) {
                year = new Date().getFullYear();
            } else if (year < 100) {
                year += new Date().getFullYear() - new Date().getFullYear() % 100 + (year <= shortYearCutoff ? 0 : -100);
            }
            if (doy > -1) {
                month = 1;
                day = doy;
                do {
                    dim = this._getDaysInMonth(year, month - 1);
                    if (day <= dim) {
                        break;
                    }
                    month++;
                    day -= dim;
                } while (true);
            }
            date = this._daylightSavingAdjust(new Date(year, month - 1, day));
            if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {
                throw "Invalid date";
            }
            return date;
        },
        ATOM: "yy-mm-dd",
        COOKIE: "D, dd M yy",
        ISO_8601: "yy-mm-dd",
        RFC_822: "D, d M y",
        RFC_850: "DD, dd-M-y",
        RFC_1036: "D, d M y",
        RFC_1123: "D, d M yy",
        RFC_2822: "D, d M yy",
        RSS: "D, d M y",
        TICKS: "!",
        TIMESTAMP: "@",
        W3C: "yy-mm-dd",
        _ticksTo1970: ((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) + Math.floor(1970 / 400)) * 24 * 60 * 60 * 1e7,
        formatDate: function(format, date, settings) {
            if (!date) {
                return "";
            }
            var iFormat, dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort, dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames, monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort, monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames, lookAhead = function(match) {
                var matches = iFormat + 1 < format.length && format.charAt(iFormat + 1) === match;
                if (matches) {
                    iFormat++;
                }
                return matches;
            }, formatNumber = function(match, value, len) {
                var num = "" + value;
                if (lookAhead(match)) {
                    while (num.length < len) {
                        num = "0" + num;
                    }
                }
                return num;
            }, formatName = function(match, value, shortNames, longNames) {
                return lookAhead(match) ? longNames[value] : shortNames[value];
            }, output = "", literal = false;
            if (date) {
                for (iFormat = 0; iFormat < format.length; iFormat++) {
                    if (literal) {
                        if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
                            literal = false;
                        } else {
                            output += format.charAt(iFormat);
                        }
                    } else {
                        switch (format.charAt(iFormat)) {
                          case "d":
                            output += formatNumber("d", date.getDate(), 2);
                            break;

                          case "D":
                            output += formatName("D", date.getDay(), dayNamesShort, dayNames);
                            break;

                          case "o":
                            output += formatNumber("o", Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 864e5), 3);
                            break;

                          case "m":
                            output += formatNumber("m", date.getMonth() + 1, 2);
                            break;

                          case "M":
                            output += formatName("M", date.getMonth(), monthNamesShort, monthNames);
                            break;

                          case "y":
                            output += lookAhead("y") ? date.getFullYear() : (date.getFullYear() % 100 < 10 ? "0" : "") + date.getFullYear() % 100;
                            break;

                          case "@":
                            output += date.getTime();
                            break;

                          case "!":
                            output += date.getTime() * 1e4 + this._ticksTo1970;
                            break;

                          case "'":
                            if (lookAhead("'")) {
                                output += "'";
                            } else {
                                literal = true;
                            }
                            break;

                          default:
                            output += format.charAt(iFormat);
                        }
                    }
                }
            }
            return output;
        },
        _possibleChars: function(format) {
            var iFormat, chars = "", literal = false, lookAhead = function(match) {
                var matches = iFormat + 1 < format.length && format.charAt(iFormat + 1) === match;
                if (matches) {
                    iFormat++;
                }
                return matches;
            };
            for (iFormat = 0; iFormat < format.length; iFormat++) {
                if (literal) {
                    if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
                        literal = false;
                    } else {
                        chars += format.charAt(iFormat);
                    }
                } else {
                    switch (format.charAt(iFormat)) {
                      case "d":
                      case "m":
                      case "y":
                      case "@":
                        chars += "0123456789";
                        break;

                      case "D":
                      case "M":
                        return null;

                      case "'":
                        if (lookAhead("'")) {
                            chars += "'";
                        } else {
                            literal = true;
                        }
                        break;

                      default:
                        chars += format.charAt(iFormat);
                    }
                }
            }
            return chars;
        },
        _get: function(inst, name) {
            return inst.settings[name] !== undefined ? inst.settings[name] : this._defaults[name];
        },
        _setDateFromField: function(inst, noDefault) {
            if (inst.input.val() === inst.lastVal) {
                return;
            }
            var dateFormat = this._get(inst, "dateFormat"), dates = inst.lastVal = inst.input ? inst.input.val() : null, defaultDate = this._getDefaultDate(inst), date = defaultDate, settings = this._getFormatConfig(inst);
            try {
                date = this.parseDate(dateFormat, dates, settings) || defaultDate;
            } catch (event) {
                dates = noDefault ? "" : dates;
            }
            inst.selectedDay = date.getDate();
            inst.drawMonth = inst.selectedMonth = date.getMonth();
            inst.drawYear = inst.selectedYear = date.getFullYear();
            inst.currentDay = dates ? date.getDate() : 0;
            inst.currentMonth = dates ? date.getMonth() : 0;
            inst.currentYear = dates ? date.getFullYear() : 0;
            this._adjustInstDate(inst);
        },
        _getDefaultDate: function(inst) {
            return this._restrictMinMax(inst, this._determineDate(inst, this._get(inst, "defaultDate"), new Date()));
        },
        _determineDate: function(inst, date, defaultDate) {
            var offsetNumeric = function(offset) {
                var date = new Date();
                date.setDate(date.getDate() + offset);
                return date;
            }, offsetString = function(offset) {
                try {
                    return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"), offset, $.datepicker._getFormatConfig(inst));
                } catch (e) {}
                var date = (offset.toLowerCase().match(/^c/) ? $.datepicker._getDate(inst) : null) || new Date(), year = date.getFullYear(), month = date.getMonth(), day = date.getDate(), pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g, matches = pattern.exec(offset);
                while (matches) {
                    switch (matches[2] || "d") {
                      case "d":
                      case "D":
                        day += parseInt(matches[1], 10);
                        break;

                      case "w":
                      case "W":
                        day += parseInt(matches[1], 10) * 7;
                        break;

                      case "m":
                      case "M":
                        month += parseInt(matches[1], 10);
                        day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
                        break;

                      case "y":
                      case "Y":
                        year += parseInt(matches[1], 10);
                        day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
                        break;
                    }
                    matches = pattern.exec(offset);
                }
                return new Date(year, month, day);
            }, newDate = date == null || date === "" ? defaultDate : typeof date === "string" ? offsetString(date) : typeof date === "number" ? isNaN(date) ? defaultDate : offsetNumeric(date) : new Date(date.getTime());
            newDate = newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate;
            if (newDate) {
                newDate.setHours(0);
                newDate.setMinutes(0);
                newDate.setSeconds(0);
                newDate.setMilliseconds(0);
            }
            return this._daylightSavingAdjust(newDate);
        },
        _daylightSavingAdjust: function(date) {
            if (!date) {
                return null;
            }
            date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
            return date;
        },
        _setDate: function(inst, date, noChange) {
            var clear = !date, origMonth = inst.selectedMonth, origYear = inst.selectedYear, newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
            inst.selectedDay = inst.currentDay = newDate.getDate();
            inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
            inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
            if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) {
                this._notifyChange(inst);
            }
            this._adjustInstDate(inst);
            if (inst.input) {
                inst.input.val(clear ? "" : this._formatDate(inst));
            }
        },
        _getDate: function(inst) {
            var startDate = !inst.currentYear || inst.input && inst.input.val() === "" ? null : this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay));
            return startDate;
        },
        _attachHandlers: function(inst) {
            var stepMonths = this._get(inst, "stepMonths"), id = "#" + inst.id.replace(/\\\\/g, "\\");
            inst.dpDiv.find("[data-handler]").map(function() {
                var handler = {
                    prev: function() {
                        $.datepicker._adjustDate(id, -stepMonths, "M");
                    },
                    next: function() {
                        $.datepicker._adjustDate(id, +stepMonths, "M");
                    },
                    hide: function() {
                        $.datepicker._hideDatepicker();
                    },
                    today: function() {
                        $.datepicker._gotoToday(id);
                    },
                    selectDay: function() {
                        $.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);
                        return false;
                    },
                    selectMonth: function() {
                        $.datepicker._selectMonthYear(id, this, "M");
                        return false;
                    },
                    selectYear: function() {
                        $.datepicker._selectMonthYear(id, this, "Y");
                        return false;
                    }
                };
                $(this).on(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);
            });
        },
        _generateHTML: function(inst) {
            var maxDraw, prevText, prev, nextText, next, currentText, gotoDate, controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin, monthNames, monthNamesShort, beforeShowDay, showOtherMonths, selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate, cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows, printDate, dRow, tbody, daySettings, otherMonth, unselectable, tempDate = new Date(), today = this._daylightSavingAdjust(new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), isRTL = this._get(inst, "isRTL"), showButtonPanel = this._get(inst, "showButtonPanel"), hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"), navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"), numMonths = this._getNumberOfMonths(inst), showCurrentAtPos = this._get(inst, "showCurrentAtPos"), stepMonths = this._get(inst, "stepMonths"), isMultiMonth = numMonths[0] !== 1 || numMonths[1] !== 1, currentDate = this._daylightSavingAdjust(!inst.currentDay ? new Date(9999, 9, 9) : new Date(inst.currentYear, inst.currentMonth, inst.currentDay)), minDate = this._getMinMaxDate(inst, "min"), maxDate = this._getMinMaxDate(inst, "max"), drawMonth = inst.drawMonth - showCurrentAtPos, drawYear = inst.drawYear;
            if (drawMonth < 0) {
                drawMonth += 12;
                drawYear--;
            }
            if (maxDate) {
                maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(), maxDate.getMonth() - numMonths[0] * numMonths[1] + 1, maxDate.getDate()));
                maxDraw = minDate && maxDraw < minDate ? minDate : maxDraw;
                while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
                    drawMonth--;
                    if (drawMonth < 0) {
                        drawMonth = 11;
                        drawYear--;
                    }
                }
            }
            inst.drawMonth = drawMonth;
            inst.drawYear = drawYear;
            prevText = this._get(inst, "prevText");
            prevText = !navigationAsDateFormat ? prevText : this.formatDate(prevText, this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)), this._getFormatConfig(inst));
            if (this._canAdjustMonth(inst, -1, drawYear, drawMonth)) {
                prev = $("<a>").attr({
                    class: "ui-datepicker-prev ui-corner-all",
                    "data-handler": "prev",
                    "data-event": "click",
                    title: prevText
                }).append($("<span>").addClass("ui-icon ui-icon-circle-triangle-" + (isRTL ? "e" : "w")).text(prevText))[0].outerHTML;
            } else if (hideIfNoPrevNext) {
                prev = "";
            } else {
                prev = $("<a>").attr({
                    class: "ui-datepicker-prev ui-corner-all ui-state-disabled",
                    title: prevText
                }).append($("<span>").addClass("ui-icon ui-icon-circle-triangle-" + (isRTL ? "e" : "w")).text(prevText))[0].outerHTML;
            }
            nextText = this._get(inst, "nextText");
            nextText = !navigationAsDateFormat ? nextText : this.formatDate(nextText, this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)), this._getFormatConfig(inst));
            if (this._canAdjustMonth(inst, +1, drawYear, drawMonth)) {
                next = $("<a>").attr({
                    class: "ui-datepicker-next ui-corner-all",
                    "data-handler": "next",
                    "data-event": "click",
                    title: nextText
                }).append($("<span>").addClass("ui-icon ui-icon-circle-triangle-" + (isRTL ? "w" : "e")).text(nextText))[0].outerHTML;
            } else if (hideIfNoPrevNext) {
                next = "";
            } else {
                next = $("<a>").attr({
                    class: "ui-datepicker-next ui-corner-all ui-state-disabled",
                    title: nextText
                }).append($("<span>").attr("class", "ui-icon ui-icon-circle-triangle-" + (isRTL ? "w" : "e")).text(nextText))[0].outerHTML;
            }
            currentText = this._get(inst, "currentText");
            gotoDate = this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today;
            currentText = !navigationAsDateFormat ? currentText : this.formatDate(currentText, gotoDate, this._getFormatConfig(inst));
            controls = "";
            if (!inst.inline) {
                controls = $("<button>").attr({
                    type: "button",
                    class: "ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all",
                    "data-handler": "hide",
                    "data-event": "click"
                }).text(this._get(inst, "closeText"))[0].outerHTML;
            }
            buttonPanel = "";
            if (showButtonPanel) {
                buttonPanel = $("<div class='ui-datepicker-buttonpane ui-widget-content'>").append(isRTL ? controls : "").append(this._isInRange(inst, gotoDate) ? $("<button>").attr({
                    type: "button",
                    class: "ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all",
                    "data-handler": "today",
                    "data-event": "click"
                }).text(currentText) : "").append(isRTL ? "" : controls)[0].outerHTML;
            }
            firstDay = parseInt(this._get(inst, "firstDay"), 10);
            firstDay = isNaN(firstDay) ? 0 : firstDay;
            showWeek = this._get(inst, "showWeek");
            dayNames = this._get(inst, "dayNames");
            dayNamesMin = this._get(inst, "dayNamesMin");
            monthNames = this._get(inst, "monthNames");
            monthNamesShort = this._get(inst, "monthNamesShort");
            beforeShowDay = this._get(inst, "beforeShowDay");
            showOtherMonths = this._get(inst, "showOtherMonths");
            selectOtherMonths = this._get(inst, "selectOtherMonths");
            defaultDate = this._getDefaultDate(inst);
            html = "";
            for (row = 0; row < numMonths[0]; row++) {
                group = "";
                this.maxRows = 4;
                for (col = 0; col < numMonths[1]; col++) {
                    selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
                    cornerClass = " ui-corner-all";
                    calender = "";
                    if (isMultiMonth) {
                        calender += "<div class='ui-datepicker-group";
                        if (numMonths[1] > 1) {
                            switch (col) {
                              case 0:
                                calender += " ui-datepicker-group-first";
                                cornerClass = " ui-corner-" + (isRTL ? "right" : "left");
                                break;

                              case numMonths[1] - 1:
                                calender += " ui-datepicker-group-last";
                                cornerClass = " ui-corner-" + (isRTL ? "left" : "right");
                                break;

                              default:
                                calender += " ui-datepicker-group-middle";
                                cornerClass = "";
                                break;
                            }
                        }
                        calender += "'>";
                    }
                    calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" + (/all|left/.test(cornerClass) && row === 0 ? isRTL ? next : prev : "") + (/all|right/.test(cornerClass) && row === 0 ? isRTL ? prev : next : "") + this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate, row > 0 || col > 0, monthNames, monthNamesShort) + "</div><table class='ui-datepicker-calendar'><thead>" + "<tr>";
                    thead = showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : "";
                    for (dow = 0; dow < 7; dow++) {
                        day = (dow + firstDay) % 7;
                        thead += "<th scope='col'" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" + "<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>";
                    }
                    calender += thead + "</tr></thead><tbody>";
                    daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
                    if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {
                        inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
                    }
                    leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
                    curRows = Math.ceil((leadDays + daysInMonth) / 7);
                    numRows = isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows;
                    this.maxRows = numRows;
                    printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
                    for (dRow = 0; dRow < numRows; dRow++) {
                        calender += "<tr>";
                        tbody = !showWeek ? "" : "<td class='ui-datepicker-week-col'>" + this._get(inst, "calculateWeek")(printDate) + "</td>";
                        for (dow = 0; dow < 7; dow++) {
                            daySettings = beforeShowDay ? beforeShowDay.apply(inst.input ? inst.input[0] : null, [ printDate ]) : [ true, "" ];
                            otherMonth = printDate.getMonth() !== drawMonth;
                            unselectable = otherMonth && !selectOtherMonths || !daySettings[0] || minDate && printDate < minDate || maxDate && printDate > maxDate;
                            tbody += "<td class='" + ((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + (otherMonth ? " ui-datepicker-other-month" : "") + (printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent || defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ? " " + this._dayOverClass : "") + (unselectable ? " " + this._unselectableClass + " ui-state-disabled" : "") + (otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + (printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + (printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + ((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2].replace(/'/g, "&#39;") + "'" : "") + (unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + (otherMonth && !showOtherMonths ? "&#xa0;" : unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" + (printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") + (printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + (otherMonth ? " ui-priority-secondary" : "") + "' href='#' aria-current='" + (printDate.getTime() === currentDate.getTime() ? "true" : "false") + "' data-date='" + printDate.getDate() + "'>" + printDate.getDate() + "</a>") + "</td>";
                            printDate.setDate(printDate.getDate() + 1);
                            printDate = this._daylightSavingAdjust(printDate);
                        }
                        calender += tbody + "</tr>";
                    }
                    drawMonth++;
                    if (drawMonth > 11) {
                        drawMonth = 0;
                        drawYear++;
                    }
                    calender += "</tbody></table>" + (isMultiMonth ? "</div>" + (numMonths[0] > 0 && col === numMonths[1] - 1 ? "<div class='ui-datepicker-row-break'></div>" : "") : "");
                    group += calender;
                }
                html += group;
            }
            html += buttonPanel;
            inst._keyEvent = false;
            return html;
        },
        _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate, secondary, monthNames, monthNamesShort) {
            var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear, changeMonth = this._get(inst, "changeMonth"), changeYear = this._get(inst, "changeYear"), showMonthAfterYear = this._get(inst, "showMonthAfterYear"), selectMonthLabel = this._get(inst, "selectMonthLabel"), selectYearLabel = this._get(inst, "selectYearLabel"), html = "<div class='ui-datepicker-title'>", monthHtml = "";
            if (secondary || !changeMonth) {
                monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>";
            } else {
                inMinYear = minDate && minDate.getFullYear() === drawYear;
                inMaxYear = maxDate && maxDate.getFullYear() === drawYear;
                monthHtml += "<select class='ui-datepicker-month' aria-label='" + selectMonthLabel + "' data-handler='selectMonth' data-event='change'>";
                for (month = 0; month < 12; month++) {
                    if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) {
                        monthHtml += "<option value='" + month + "'" + (month === drawMonth ? " selected='selected'" : "") + ">" + monthNamesShort[month] + "</option>";
                    }
                }
                monthHtml += "</select>";
            }
            if (!showMonthAfterYear) {
                html += monthHtml + (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "");
            }
            if (!inst.yearshtml) {
                inst.yearshtml = "";
                if (secondary || !changeYear) {
                    html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
                } else {
                    years = this._get(inst, "yearRange").split(":");
                    thisYear = new Date().getFullYear();
                    determineYear = function(value) {
                        var year = value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) : value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) : parseInt(value, 10);
                        return isNaN(year) ? thisYear : year;
                    };
                    year = determineYear(years[0]);
                    endYear = Math.max(year, determineYear(years[1] || ""));
                    year = minDate ? Math.max(year, minDate.getFullYear()) : year;
                    endYear = maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear;
                    inst.yearshtml += "<select class='ui-datepicker-year' aria-label='" + selectYearLabel + "' data-handler='selectYear' data-event='change'>";
                    for (;year <= endYear; year++) {
                        inst.yearshtml += "<option value='" + year + "'" + (year === drawYear ? " selected='selected'" : "") + ">" + year + "</option>";
                    }
                    inst.yearshtml += "</select>";
                    html += inst.yearshtml;
                    inst.yearshtml = null;
                }
            }
            html += this._get(inst, "yearSuffix");
            if (showMonthAfterYear) {
                html += (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "") + monthHtml;
            }
            html += "</div>";
            return html;
        },
        _adjustInstDate: function(inst, offset, period) {
            var year = inst.selectedYear + (period === "Y" ? offset : 0), month = inst.selectedMonth + (period === "M" ? offset : 0), day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0), date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day)));
            inst.selectedDay = date.getDate();
            inst.drawMonth = inst.selectedMonth = date.getMonth();
            inst.drawYear = inst.selectedYear = date.getFullYear();
            if (period === "M" || period === "Y") {
                this._notifyChange(inst);
            }
        },
        _restrictMinMax: function(inst, date) {
            var minDate = this._getMinMaxDate(inst, "min"), maxDate = this._getMinMaxDate(inst, "max"), newDate = minDate && date < minDate ? minDate : date;
            return maxDate && newDate > maxDate ? maxDate : newDate;
        },
        _notifyChange: function(inst) {
            var onChange = this._get(inst, "onChangeMonthYear");
            if (onChange) {
                onChange.apply(inst.input ? inst.input[0] : null, [ inst.selectedYear, inst.selectedMonth + 1, inst ]);
            }
        },
        _getNumberOfMonths: function(inst) {
            var numMonths = this._get(inst, "numberOfMonths");
            return numMonths == null ? [ 1, 1 ] : typeof numMonths === "number" ? [ 1, numMonths ] : numMonths;
        },
        _getMinMaxDate: function(inst, minMax) {
            return this._determineDate(inst, this._get(inst, minMax + "Date"), null);
        },
        _getDaysInMonth: function(year, month) {
            return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
        },
        _getFirstDayOfMonth: function(year, month) {
            return new Date(year, month, 1).getDay();
        },
        _canAdjustMonth: function(inst, offset, curYear, curMonth) {
            var numMonths = this._getNumberOfMonths(inst), date = this._daylightSavingAdjust(new Date(curYear, curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
            if (offset < 0) {
                date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
            }
            return this._isInRange(inst, date);
        },
        _isInRange: function(inst, date) {
            var yearSplit, currentYear, minDate = this._getMinMaxDate(inst, "min"), maxDate = this._getMinMaxDate(inst, "max"), minYear = null, maxYear = null, years = this._get(inst, "yearRange");
            if (years) {
                yearSplit = years.split(":");
                currentYear = new Date().getFullYear();
                minYear = parseInt(yearSplit[0], 10);
                maxYear = parseInt(yearSplit[1], 10);
                if (yearSplit[0].match(/[+\-].*/)) {
                    minYear += currentYear;
                }
                if (yearSplit[1].match(/[+\-].*/)) {
                    maxYear += currentYear;
                }
            }
            return (!minDate || date.getTime() >= minDate.getTime()) && (!maxDate || date.getTime() <= maxDate.getTime()) && (!minYear || date.getFullYear() >= minYear) && (!maxYear || date.getFullYear() <= maxYear);
        },
        _getFormatConfig: function(inst) {
            var shortYearCutoff = this._get(inst, "shortYearCutoff");
            shortYearCutoff = typeof shortYearCutoff !== "string" ? shortYearCutoff : new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10);
            return {
                shortYearCutoff: shortYearCutoff,
                dayNamesShort: this._get(inst, "dayNamesShort"),
                dayNames: this._get(inst, "dayNames"),
                monthNamesShort: this._get(inst, "monthNamesShort"),
                monthNames: this._get(inst, "monthNames")
            };
        },
        _formatDate: function(inst, day, month, year) {
            if (!day) {
                inst.currentDay = inst.selectedDay;
                inst.currentMonth = inst.selectedMonth;
                inst.currentYear = inst.selectedYear;
            }
            var date = day ? typeof day === "object" ? day : this._daylightSavingAdjust(new Date(year, month, day)) : this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay));
            return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst));
        }
    });
    function datepicker_bindHover(dpDiv) {
        var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
        return dpDiv.on("mouseout", selector, function() {
            $(this).removeClass("ui-state-hover");
            if (this.className.indexOf("ui-datepicker-prev") !== -1) {
                $(this).removeClass("ui-datepicker-prev-hover");
            }
            if (this.className.indexOf("ui-datepicker-next") !== -1) {
                $(this).removeClass("ui-datepicker-next-hover");
            }
        }).on("mouseover", selector, datepicker_handleMouseover);
    }
    function datepicker_handleMouseover() {
        if (!$.datepicker._isDisabledDatepicker(datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[0] : datepicker_instActive.input[0])) {
            $(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");
            $(this).addClass("ui-state-hover");
            if (this.className.indexOf("ui-datepicker-prev") !== -1) {
                $(this).addClass("ui-datepicker-prev-hover");
            }
            if (this.className.indexOf("ui-datepicker-next") !== -1) {
                $(this).addClass("ui-datepicker-next-hover");
            }
        }
    }
    function datepicker_extendRemove(target, props) {
        $.extend(target, props);
        for (var name in props) {
            if (props[name] == null) {
                target[name] = props[name];
            }
        }
        return target;
    }
    $.fn.datepicker = function(options) {
        if (!this.length) {
            return this;
        }
        if (!$.datepicker.initialized) {
            $(document).on("mousedown", $.datepicker._checkExternalClick);
            $.datepicker.initialized = true;
        }
        if ($("#" + $.datepicker._mainDivId).length === 0) {
            $("body").append($.datepicker.dpDiv);
        }
        var otherArgs = Array.prototype.slice.call(arguments, 1);
        if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) {
            return $.datepicker["_" + options + "Datepicker"].apply($.datepicker, [ this[0] ].concat(otherArgs));
        }
        if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") {
            return $.datepicker["_" + options + "Datepicker"].apply($.datepicker, [ this[0] ].concat(otherArgs));
        }
        return this.each(function() {
            if (typeof options === "string") {
                $.datepicker["_" + options + "Datepicker"].apply($.datepicker, [ this ].concat(otherArgs));
            } else {
                $.datepicker._attachDatepicker(this, options);
            }
        });
    };
    $.datepicker = new Datepicker();
    $.datepicker.initialized = false;
    $.datepicker.uuid = new Date().getTime();
    $.datepicker.version = "1.13.1";
    var widgetsDatepicker = $.datepicker;
    var ie = $.ui.ie = !!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase());
    var mouseHandled = false;
    $(document).on("mouseup", function() {
        mouseHandled = false;
    });
    var widgetsMouse = $.widget("ui.mouse", {
        version: "1.13.1",
        options: {
            cancel: "input, textarea, button, select, option",
            distance: 1,
            delay: 0
        },
        _mouseInit: function() {
            var that = this;
            this.element.on("mousedown." + this.widgetName, function(event) {
                return that._mouseDown(event);
            }).on("click." + this.widgetName, function(event) {
                if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
                    $.removeData(event.target, that.widgetName + ".preventClickEvent");
                    event.stopImmediatePropagation();
                    return false;
                }
            });
            this.started = false;
        },
        _mouseDestroy: function() {
            this.element.off("." + this.widgetName);
            if (this._mouseMoveDelegate) {
                this.document.off("mousemove." + this.widgetName, this._mouseMoveDelegate).off("mouseup." + this.widgetName, this._mouseUpDelegate);
            }
        },
        _mouseDown: function(event) {
            if (mouseHandled) {
                return;
            }
            this._mouseMoved = false;
            if (this._mouseStarted) {
                this._mouseUp(event);
            }
            this._mouseDownEvent = event;
            var that = this, btnIsLeft = event.which === 1, elIsCancel = typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false;
            if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
                return true;
            }
            this.mouseDelayMet = !this.options.delay;
            if (!this.mouseDelayMet) {
                this._mouseDelayTimer = setTimeout(function() {
                    that.mouseDelayMet = true;
                }, this.options.delay);
            }
            if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
                this._mouseStarted = this._mouseStart(event) !== false;
                if (!this._mouseStarted) {
                    event.preventDefault();
                    return true;
                }
            }
            if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
                $.removeData(event.target, this.widgetName + ".preventClickEvent");
            }
            this._mouseMoveDelegate = function(event) {
                return that._mouseMove(event);
            };
            this._mouseUpDelegate = function(event) {
                return that._mouseUp(event);
            };
            this.document.on("mousemove." + this.widgetName, this._mouseMoveDelegate).on("mouseup." + this.widgetName, this._mouseUpDelegate);
            event.preventDefault();
            mouseHandled = true;
            return true;
        },
        _mouseMove: function(event) {
            if (this._mouseMoved) {
                if ($.ui.ie && (!document.documentMode || document.documentMode < 9) && !event.button) {
                    return this._mouseUp(event);
                } else if (!event.which) {
                    if (event.originalEvent.altKey || event.originalEvent.ctrlKey || event.originalEvent.metaKey || event.originalEvent.shiftKey) {
                        this.ignoreMissingWhich = true;
                    } else if (!this.ignoreMissingWhich) {
                        return this._mouseUp(event);
                    }
                }
            }
            if (event.which || event.button) {
                this._mouseMoved = true;
            }
            if (this._mouseStarted) {
                this._mouseDrag(event);
                return event.preventDefault();
            }
            if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
                this._mouseStarted = this._mouseStart(this._mouseDownEvent, event) !== false;
                if (this._mouseStarted) {
                    this._mouseDrag(event);
                } else {
                    this._mouseUp(event);
                }
            }
            return !this._mouseStarted;
        },
        _mouseUp: function(event) {
            this.document.off("mousemove." + this.widgetName, this._mouseMoveDelegate).off("mouseup." + this.widgetName, this._mouseUpDelegate);
            if (this._mouseStarted) {
                this._mouseStarted = false;
                if (event.target === this._mouseDownEvent.target) {
                    $.data(event.target, this.widgetName + ".preventClickEvent", true);
                }
                this._mouseStop(event);
            }
            if (this._mouseDelayTimer) {
                clearTimeout(this._mouseDelayTimer);
                delete this._mouseDelayTimer;
            }
            this.ignoreMissingWhich = false;
            mouseHandled = false;
            event.preventDefault();
        },
        _mouseDistanceMet: function(event) {
            return Math.max(Math.abs(this._mouseDownEvent.pageX - event.pageX), Math.abs(this._mouseDownEvent.pageY - event.pageY)) >= this.options.distance;
        },
        _mouseDelayMet: function() {
            return this.mouseDelayMet;
        },
        _mouseStart: function() {},
        _mouseDrag: function() {},
        _mouseStop: function() {},
        _mouseCapture: function() {
            return true;
        }
    });
    var plugin = $.ui.plugin = {
        add: function(module, option, set) {
            var i, proto = $.ui[module].prototype;
            for (i in set) {
                proto.plugins[i] = proto.plugins[i] || [];
                proto.plugins[i].push([ option, set[i] ]);
            }
        },
        call: function(instance, name, args, allowDisconnected) {
            var i, set = instance.plugins[name];
            if (!set) {
                return;
            }
            if (!allowDisconnected && (!instance.element[0].parentNode || instance.element[0].parentNode.nodeType === 11)) {
                return;
            }
            for (i = 0; i < set.length; i++) {
                if (instance.options[set[i][0]]) {
                    set[i][1].apply(instance.element, args);
                }
            }
        }
    };
    var safeBlur = $.ui.safeBlur = function(element) {
        if (element && element.nodeName.toLowerCase() !== "body") {
            $(element).trigger("blur");
        }
    };
    $.widget("ui.draggable", $.ui.mouse, {
        version: "1.13.1",
        widgetEventPrefix: "drag",
        options: {
            addClasses: true,
            appendTo: "parent",
            axis: false,
            connectToSortable: false,
            containment: false,
            cursor: "auto",
            cursorAt: false,
            grid: false,
            handle: false,
            helper: "original",
            iframeFix: false,
            opacity: false,
            refreshPositions: false,
            revert: false,
            revertDuration: 500,
            scope: "default",
            scroll: true,
            scrollSensitivity: 20,
            scrollSpeed: 20,
            snap: false,
            snapMode: "both",
            snapTolerance: 20,
            stack: false,
            zIndex: false,
            drag: null,
            start: null,
            stop: null
        },
        _create: function() {
            if (this.options.helper === "original") {
                this._setPositionRelative();
            }
            if (this.options.addClasses) {
                this._addClass("ui-draggable");
            }
            this._setHandleClassName();
            this._mouseInit();
        },
        _setOption: function(key, value) {
            this._super(key, value);
            if (key === "handle") {
                this._removeHandleClassName();
                this._setHandleClassName();
            }
        },
        _destroy: function() {
            if ((this.helper || this.element).is(".ui-draggable-dragging")) {
                this.destroyOnClear = true;
                return;
            }
            this._removeHandleClassName();
            this._mouseDestroy();
        },
        _mouseCapture: function(event) {
            var o = this.options;
            if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) {
                return false;
            }
            this.handle = this._getHandle(event);
            if (!this.handle) {
                return false;
            }
            this._blurActiveElement(event);
            this._blockFrames(o.iframeFix === true ? "iframe" : o.iframeFix);
            return true;
        },
        _blockFrames: function(selector) {
            this.iframeBlocks = this.document.find(selector).map(function() {
                var iframe = $(this);
                return $("<div>").css("position", "absolute").appendTo(iframe.parent()).outerWidth(iframe.outerWidth()).outerHeight(iframe.outerHeight()).offset(iframe.offset())[0];
            });
        },
        _unblockFrames: function() {
            if (this.iframeBlocks) {
                this.iframeBlocks.remove();
                delete this.iframeBlocks;
            }
        },
        _blurActiveElement: function(event) {
            var activeElement = $.ui.safeActiveElement(this.document[0]), target = $(event.target);
            if (target.closest(activeElement).length) {
                return;
            }
            $.ui.safeBlur(activeElement);
        },
        _mouseStart: function(event) {
            var o = this.options;
            this.helper = this._createHelper(event);
            this._addClass(this.helper, "ui-draggable-dragging");
            this._cacheHelperProportions();
            if ($.ui.ddmanager) {
                $.ui.ddmanager.current = this;
            }
            this._cacheMargins();
            this.cssPosition = this.helper.css("position");
            this.scrollParent = this.helper.scrollParent(true);
            this.offsetParent = this.helper.offsetParent();
            this.hasFixedAncestor = this.helper.parents().filter(function() {
                return $(this).css("position") === "fixed";
            }).length > 0;
            this.positionAbs = this.element.offset();
            this._refreshOffsets(event);
            this.originalPosition = this.position = this._generatePosition(event, false);
            this.originalPageX = event.pageX;
            this.originalPageY = event.pageY;
            if (o.cursorAt) {
                this._adjustOffsetFromHelper(o.cursorAt);
            }
            this._setContainment();
            if (this._trigger("start", event) === false) {
                this._clear();
                return false;
            }
            this._cacheHelperProportions();
            if ($.ui.ddmanager && !o.dropBehaviour) {
                $.ui.ddmanager.prepareOffsets(this, event);
            }
            this._mouseDrag(event, true);
            if ($.ui.ddmanager) {
                $.ui.ddmanager.dragStart(this, event);
            }
            return true;
        },
        _refreshOffsets: function(event) {
            this.offset = {
                top: this.positionAbs.top - this.margins.top,
                left: this.positionAbs.left - this.margins.left,
                scroll: false,
                parent: this._getParentOffset(),
                relative: this._getRelativeOffset()
            };
            this.offset.click = {
                left: event.pageX - this.offset.left,
                top: event.pageY - this.offset.top
            };
        },
        _mouseDrag: function(event, noPropagation) {
            if (this.hasFixedAncestor) {
                this.offset.parent = this._getParentOffset();
            }
            this.position = this._generatePosition(event, true);
            this.positionAbs = this._convertPositionTo("absolute");
            if (!noPropagation) {
                var ui = this._uiHash();
                if (this._trigger("drag", event, ui) === false) {
                    this._mouseUp(new $.Event("mouseup", event));
                    return false;
                }
                this.position = ui.position;
            }
            this.helper[0].style.left = this.position.left + "px";
            this.helper[0].style.top = this.position.top + "px";
            if ($.ui.ddmanager) {
                $.ui.ddmanager.drag(this, event);
            }
            return false;
        },
        _mouseStop: function(event) {
            var that = this, dropped = false;
            if ($.ui.ddmanager && !this.options.dropBehaviour) {
                dropped = $.ui.ddmanager.drop(this, event);
            }
            if (this.dropped) {
                dropped = this.dropped;
                this.dropped = false;
            }
            if (this.options.revert === "invalid" && !dropped || this.options.revert === "valid" && dropped || this.options.revert === true || typeof this.options.revert === "function" && this.options.revert.call(this.element, dropped)) {
                $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
                    if (that._trigger("stop", event) !== false) {
                        that._clear();
                    }
                });
            } else {
                if (this._trigger("stop", event) !== false) {
                    this._clear();
                }
            }
            return false;
        },
        _mouseUp: function(event) {
            this._unblockFrames();
            if ($.ui.ddmanager) {
                $.ui.ddmanager.dragStop(this, event);
            }
            if (this.handleElement.is(event.target)) {
                this.element.trigger("focus");
            }
            return $.ui.mouse.prototype._mouseUp.call(this, event);
        },
        cancel: function() {
            if (this.helper.is(".ui-draggable-dragging")) {
                this._mouseUp(new $.Event("mouseup", {
                    target: this.element[0]
                }));
            } else {
                this._clear();
            }
            return this;
        },
        _getHandle: function(event) {
            return this.options.handle ? !!$(event.target).closest(this.element.find(this.options.handle)).length : true;
        },
        _setHandleClassName: function() {
            this.handleElement = this.options.handle ? this.element.find(this.options.handle) : this.element;
            this._addClass(this.handleElement, "ui-draggable-handle");
        },
        _removeHandleClassName: function() {
            this._removeClass(this.handleElement, "ui-draggable-handle");
        },
        _createHelper: function(event) {
            var o = this.options, helperIsFunction = typeof o.helper === "function", helper = helperIsFunction ? $(o.helper.apply(this.element[0], [ event ])) : o.helper === "clone" ? this.element.clone().removeAttr("id") : this.element;
            if (!helper.parents("body").length) {
                helper.appendTo(o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo);
            }
            if (helperIsFunction && helper[0] === this.element[0]) {
                this._setPositionRelative();
            }
            if (helper[0] !== this.element[0] && !/(fixed|absolute)/.test(helper.css("position"))) {
                helper.css("position", "absolute");
            }
            return helper;
        },
        _setPositionRelative: function() {
            if (!/^(?:r|a|f)/.test(this.element.css("position"))) {
                this.element[0].style.position = "relative";
            }
        },
        _adjustOffsetFromHelper: function(obj) {
            if (typeof obj === "string") {
                obj = obj.split(" ");
            }
            if (Array.isArray(obj)) {
                obj = {
                    left: +obj[0],
                    top: +obj[1] || 0
                };
            }
            if ("left" in obj) {
                this.offset.click.left = obj.left + this.margins.left;
            }
            if ("right" in obj) {
                this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
            }
            if ("top" in obj) {
                this.offset.click.top = obj.top + this.margins.top;
            }
            if ("bottom" in obj) {
                this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
            }
        },
        _isRootNode: function(element) {
            return /(html|body)/i.test(element.tagName) || element === this.document[0];
        },
        _getParentOffset: function() {
            var po = this.offsetParent.offset(), document = this.document[0];
            if (this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
                po.left += this.scrollParent.scrollLeft();
                po.top += this.scrollParent.scrollTop();
            }
            if (this._isRootNode(this.offsetParent[0])) {
                po = {
                    top: 0,
                    left: 0
                };
            }
            return {
                top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0),
                left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0)
            };
        },
        _getRelativeOffset: function() {
            if (this.cssPosition !== "relative") {
                return {
                    top: 0,
                    left: 0
                };
            }
            var p = this.element.position(), scrollIsRootNode = this._isRootNode(this.scrollParent[0]);
            return {
                top: p.top - (parseInt(this.helper.css("top"), 10) || 0) + (!scrollIsRootNode ? this.scrollParent.scrollTop() : 0),
                left: p.left - (parseInt(this.helper.css("left"), 10) || 0) + (!scrollIsRootNode ? this.scrollParent.scrollLeft() : 0)
            };
        },
        _cacheMargins: function() {
            this.margins = {
                left: parseInt(this.element.css("marginLeft"), 10) || 0,
                top: parseInt(this.element.css("marginTop"), 10) || 0,
                right: parseInt(this.element.css("marginRight"), 10) || 0,
                bottom: parseInt(this.element.css("marginBottom"), 10) || 0
            };
        },
        _cacheHelperProportions: function() {
            this.helperProportions = {
                width: this.helper.outerWidth(),
                height: this.helper.outerHeight()
            };
        },
        _setContainment: function() {
            var isUserScrollable, c, ce, o = this.options, document = this.document[0];
            this.relativeContainer = null;
            if (!o.containment) {
                this.containment = null;
                return;
            }
            if (o.containment === "window") {
                this.containment = [ $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left, $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top, $(window).scrollLeft() + $(window).width() - this.helperProportions.width - this.margins.left, $(window).scrollTop() + ($(window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top ];
                return;
            }
            if (o.containment === "document") {
                this.containment = [ 0, 0, $(document).width() - this.helperProportions.width - this.margins.left, ($(document).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top ];
                return;
            }
            if (o.containment.constructor === Array) {
                this.containment = o.containment;
                return;
            }
            if (o.containment === "parent") {
                o.containment = this.helper[0].parentNode;
            }
            c = $(o.containment);
            ce = c[0];
            if (!ce) {
                return;
            }
            isUserScrollable = /(scroll|auto)/.test(c.css("overflow"));
            this.containment = [ (parseInt(c.css("borderLeftWidth"), 10) || 0) + (parseInt(c.css("paddingLeft"), 10) || 0), (parseInt(c.css("borderTopWidth"), 10) || 0) + (parseInt(c.css("paddingTop"), 10) || 0), (isUserScrollable ? Math.max(ce.scrollWidth, ce.offsetWidth) : ce.offsetWidth) - (parseInt(c.css("borderRightWidth"), 10) || 0) - (parseInt(c.css("paddingRight"), 10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right, (isUserScrollable ? Math.max(ce.scrollHeight, ce.offsetHeight) : ce.offsetHeight) - (parseInt(c.css("borderBottomWidth"), 10) || 0) - (parseInt(c.css("paddingBottom"), 10) || 0) - this.helperProportions.height - this.margins.top - this.margins.bottom ];
            this.relativeContainer = c;
        },
        _convertPositionTo: function(d, pos) {
            if (!pos) {
                pos = this.position;
            }
            var mod = d === "absolute" ? 1 : -1, scrollIsRootNode = this._isRootNode(this.scrollParent[0]);
            return {
                top: pos.top + this.offset.relative.top * mod + this.offset.parent.top * mod - (this.cssPosition === "fixed" ? -this.offset.scroll.top : scrollIsRootNode ? 0 : this.offset.scroll.top) * mod,
                left: pos.left + this.offset.relative.left * mod + this.offset.parent.left * mod - (this.cssPosition === "fixed" ? -this.offset.scroll.left : scrollIsRootNode ? 0 : this.offset.scroll.left) * mod
            };
        },
        _generatePosition: function(event, constrainPosition) {
            var containment, co, top, left, o = this.options, scrollIsRootNode = this._isRootNode(this.scrollParent[0]), pageX = event.pageX, pageY = event.pageY;
            if (!scrollIsRootNode || !this.offset.scroll) {
                this.offset.scroll = {
                    top: this.scrollParent.scrollTop(),
                    left: this.scrollParent.scrollLeft()
                };
            }
            if (constrainPosition) {
                if (this.containment) {
                    if (this.relativeContainer) {
                        co = this.relativeContainer.offset();
                        containment = [ this.containment[0] + co.left, this.containment[1] + co.top, this.containment[2] + co.left, this.containment[3] + co.top ];
                    } else {
                        containment = this.containment;
                    }
                    if (event.pageX - this.offset.click.left < containment[0]) {
                        pageX = containment[0] + this.offset.click.left;
                    }
                    if (event.pageY - this.offset.click.top < containment[1]) {
                        pageY = containment[1] + this.offset.click.top;
                    }
                    if (event.pageX - this.offset.click.left > containment[2]) {
                        pageX = containment[2] + this.offset.click.left;
                    }
                    if (event.pageY - this.offset.click.top > containment[3]) {
                        pageY = containment[3] + this.offset.click.top;
                    }
                }
                if (o.grid) {
                    top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
                    pageY = containment ? top - this.offset.click.top >= containment[1] || top - this.offset.click.top > containment[3] ? top : top - this.offset.click.top >= containment[1] ? top - o.grid[1] : top + o.grid[1] : top;
                    left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
                    pageX = containment ? left - this.offset.click.left >= containment[0] || left - this.offset.click.left > containment[2] ? left : left - this.offset.click.left >= containment[0] ? left - o.grid[0] : left + o.grid[0] : left;
                }
                if (o.axis === "y") {
                    pageX = this.originalPageX;
                }
                if (o.axis === "x") {
                    pageY = this.originalPageY;
                }
            }
            return {
                top: pageY - this.offset.click.top - this.offset.relative.top - this.offset.parent.top + (this.cssPosition === "fixed" ? -this.offset.scroll.top : scrollIsRootNode ? 0 : this.offset.scroll.top),
                left: pageX - this.offset.click.left - this.offset.relative.left - this.offset.parent.left + (this.cssPosition === "fixed" ? -this.offset.scroll.left : scrollIsRootNode ? 0 : this.offset.scroll.left)
            };
        },
        _clear: function() {
            this._removeClass(this.helper, "ui-draggable-dragging");
            if (this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) {
                this.helper.remove();
            }
            this.helper = null;
            this.cancelHelperRemoval = false;
            if (this.destroyOnClear) {
                this.destroy();
            }
        },
        _trigger: function(type, event, ui) {
            ui = ui || this._uiHash();
            $.ui.plugin.call(this, type, [ event, ui, this ], true);
            if (/^(drag|start|stop)/.test(type)) {
                this.positionAbs = this._convertPositionTo("absolute");
                ui.offset = this.positionAbs;
            }
            return $.Widget.prototype._trigger.call(this, type, event, ui);
        },
        plugins: {},
        _uiHash: function() {
            return {
                helper: this.helper,
                position: this.position,
                originalPosition: this.originalPosition,
                offset: this.positionAbs
            };
        }
    });
    $.ui.plugin.add("draggable", "connectToSortable", {
        start: function(event, ui, draggable) {
            var uiSortable = $.extend({}, ui, {
                item: draggable.element
            });
            draggable.sortables = [];
            $(draggable.options.connectToSortable).each(function() {
                var sortable = $(this).sortable("instance");
                if (sortable && !sortable.options.disabled) {
                    draggable.sortables.push(sortable);
                    sortable.refreshPositions();
                    sortable._trigger("activate", event, uiSortable);
                }
            });
        },
        stop: function(event, ui, draggable) {
            var uiSortable = $.extend({}, ui, {
                item: draggable.element
            });
            draggable.cancelHelperRemoval = false;
            $.each(draggable.sortables, function() {
                var sortable = this;
                if (sortable.isOver) {
                    sortable.isOver = 0;
                    draggable.cancelHelperRemoval = true;
                    sortable.cancelHelperRemoval = false;
                    sortable._storedCSS = {
                        position: sortable.placeholder.css("position"),
                        top: sortable.placeholder.css("top"),
                        left: sortable.placeholder.css("left")
                    };
                    sortable._mouseStop(event);
                    sortable.options.helper = sortable.options._helper;
                } else {
                    sortable.cancelHelperRemoval = true;
                    sortable._trigger("deactivate", event, uiSortable);
                }
            });
        },
        drag: function(event, ui, draggable) {
            $.each(draggable.sortables, function() {
                var innermostIntersecting = false, sortable = this;
                sortable.positionAbs = draggable.positionAbs;
                sortable.helperProportions = draggable.helperProportions;
                sortable.offset.click = draggable.offset.click;
                if (sortable._intersectsWith(sortable.containerCache)) {
                    innermostIntersecting = true;
                    $.each(draggable.sortables, function() {
                        this.positionAbs = draggable.positionAbs;
                        this.helperProportions = draggable.helperProportions;
                        this.offset.click = draggable.offset.click;
                        if (this !== sortable && this._intersectsWith(this.containerCache) && $.contains(sortable.element[0], this.element[0])) {
                            innermostIntersecting = false;
                        }
                        return innermostIntersecting;
                    });
                }
                if (innermostIntersecting) {
                    if (!sortable.isOver) {
                        sortable.isOver = 1;
                        draggable._parent = ui.helper.parent();
                        sortable.currentItem = ui.helper.appendTo(sortable.element).data("ui-sortable-item", true);
                        sortable.options._helper = sortable.options.helper;
                        sortable.options.helper = function() {
                            return ui.helper[0];
                        };
                        event.target = sortable.currentItem[0];
                        sortable._mouseCapture(event, true);
                        sortable._mouseStart(event, true, true);
                        sortable.offset.click.top = draggable.offset.click.top;
                        sortable.offset.click.left = draggable.offset.click.left;
                        sortable.offset.parent.left -= draggable.offset.parent.left - sortable.offset.parent.left;
                        sortable.offset.parent.top -= draggable.offset.parent.top - sortable.offset.parent.top;
                        draggable._trigger("toSortable", event);
                        draggable.dropped = sortable.element;
                        $.each(draggable.sortables, function() {
                            this.refreshPositions();
                        });
                        draggable.currentItem = draggable.element;
                        sortable.fromOutside = draggable;
                    }
                    if (sortable.currentItem) {
                        sortable._mouseDrag(event);
                        ui.position = sortable.position;
                    }
                } else {
                    if (sortable.isOver) {
                        sortable.isOver = 0;
                        sortable.cancelHelperRemoval = true;
                        sortable.options._revert = sortable.options.revert;
                        sortable.options.revert = false;
                        sortable._trigger("out", event, sortable._uiHash(sortable));
                        sortable._mouseStop(event, true);
                        sortable.options.revert = sortable.options._revert;
                        sortable.options.helper = sortable.options._helper;
                        if (sortable.placeholder) {
                            sortable.placeholder.remove();
                        }
                        ui.helper.appendTo(draggable._parent);
                        draggable._refreshOffsets(event);
                        ui.position = draggable._generatePosition(event, true);
                        draggable._trigger("fromSortable", event);
                        draggable.dropped = false;
                        $.each(draggable.sortables, function() {
                            this.refreshPositions();
                        });
                    }
                }
            });
        }
    });
    $.ui.plugin.add("draggable", "cursor", {
        start: function(event, ui, instance) {
            var t = $("body"), o = instance.options;
            if (t.css("cursor")) {
                o._cursor = t.css("cursor");
            }
            t.css("cursor", o.cursor);
        },
        stop: function(event, ui, instance) {
            var o = instance.options;
            if (o._cursor) {
                $("body").css("cursor", o._cursor);
            }
        }
    });
    $.ui.plugin.add("draggable", "opacity", {
        start: function(event, ui, instance) {
            var t = $(ui.helper), o = instance.options;
            if (t.css("opacity")) {
                o._opacity = t.css("opacity");
            }
            t.css("opacity", o.opacity);
        },
        stop: function(event, ui, instance) {
            var o = instance.options;
            if (o._opacity) {
                $(ui.helper).css("opacity", o._opacity);
            }
        }
    });
    $.ui.plugin.add("draggable", "scroll", {
        start: function(event, ui, i) {
            if (!i.scrollParentNotHidden) {
                i.scrollParentNotHidden = i.helper.scrollParent(false);
            }
            if (i.scrollParentNotHidden[0] !== i.document[0] && i.scrollParentNotHidden[0].tagName !== "HTML") {
                i.overflowOffset = i.scrollParentNotHidden.offset();
            }
        },
        drag: function(event, ui, i) {
            var o = i.options, scrolled = false, scrollParent = i.scrollParentNotHidden[0], document = i.document[0];
            if (scrollParent !== document && scrollParent.tagName !== "HTML") {
                if (!o.axis || o.axis !== "x") {
                    if (i.overflowOffset.top + scrollParent.offsetHeight - event.pageY < o.scrollSensitivity) {
                        scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;
                    } else if (event.pageY - i.overflowOffset.top < o.scrollSensitivity) {
                        scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;
                    }
                }
                if (!o.axis || o.axis !== "y") {
                    if (i.overflowOffset.left + scrollParent.offsetWidth - event.pageX < o.scrollSensitivity) {
                        scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;
                    } else if (event.pageX - i.overflowOffset.left < o.scrollSensitivity) {
                        scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;
                    }
                }
            } else {
                if (!o.axis || o.axis !== "x") {
                    if (event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
                        scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
                    } else if ($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
                        scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
                    }
                }
                if (!o.axis || o.axis !== "y") {
                    if (event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
                        scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
                    } else if ($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
                        scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
                    }
                }
            }
            if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
                $.ui.ddmanager.prepareOffsets(i, event);
            }
        }
    });
    $.ui.plugin.add("draggable", "snap", {
        start: function(event, ui, i) {
            var o = i.options;
            i.snapElements = [];
            $(o.snap.constructor !== String ? o.snap.items || ":data(ui-draggable)" : o.snap).each(function() {
                var $t = $(this), $o = $t.offset();
                if (this !== i.element[0]) {
                    i.snapElements.push({
                        item: this,
                        width: $t.outerWidth(),
                        height: $t.outerHeight(),
                        top: $o.top,
                        left: $o.left
                    });
                }
            });
        },
        drag: function(event, ui, inst) {
            var ts, bs, ls, rs, l, r, t, b, i, first, o = inst.options, d = o.snapTolerance, x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width, y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
            for (i = inst.snapElements.length - 1; i >= 0; i--) {
                l = inst.snapElements[i].left - inst.margins.left;
                r = l + inst.snapElements[i].width;
                t = inst.snapElements[i].top - inst.margins.top;
                b = t + inst.snapElements[i].height;
                if (x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains(inst.snapElements[i].item.ownerDocument, inst.snapElements[i].item)) {
                    if (inst.snapElements[i].snapping) {
                        if (inst.options.snap.release) {
                            inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), {
                                snapItem: inst.snapElements[i].item
                            }));
                        }
                    }
                    inst.snapElements[i].snapping = false;
                    continue;
                }
                if (o.snapMode !== "inner") {
                    ts = Math.abs(t - y2) <= d;
                    bs = Math.abs(b - y1) <= d;
                    ls = Math.abs(l - x2) <= d;
                    rs = Math.abs(r - x1) <= d;
                    if (ts) {
                        ui.position.top = inst._convertPositionTo("relative", {
                            top: t - inst.helperProportions.height,
                            left: 0
                        }).top;
                    }
                    if (bs) {
                        ui.position.top = inst._convertPositionTo("relative", {
                            top: b,
                            left: 0
                        }).top;
                    }
                    if (ls) {
                        ui.position.left = inst._convertPositionTo("relative", {
                            top: 0,
                            left: l - inst.helperProportions.width
                        }).left;
                    }
                    if (rs) {
                        ui.position.left = inst._convertPositionTo("relative", {
                            top: 0,
                            left: r
                        }).left;
                    }
                }
                first = ts || bs || ls || rs;
                if (o.snapMode !== "outer") {
                    ts = Math.abs(t - y1) <= d;
                    bs = Math.abs(b - y2) <= d;
                    ls = Math.abs(l - x1) <= d;
                    rs = Math.abs(r - x2) <= d;
                    if (ts) {
                        ui.position.top = inst._convertPositionTo("relative", {
                            top: t,
                            left: 0
                        }).top;
                    }
                    if (bs) {
                        ui.position.top = inst._convertPositionTo("relative", {
                            top: b - inst.helperProportions.height,
                            left: 0
                        }).top;
                    }
                    if (ls) {
                        ui.position.left = inst._convertPositionTo("relative", {
                            top: 0,
                            left: l
                        }).left;
                    }
                    if (rs) {
                        ui.position.left = inst._convertPositionTo("relative", {
                            top: 0,
                            left: r - inst.helperProportions.width
                        }).left;
                    }
                }
                if (!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) {
                    if (inst.options.snap.snap) {
                        inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), {
                            snapItem: inst.snapElements[i].item
                        }));
                    }
                }
                inst.snapElements[i].snapping = ts || bs || ls || rs || first;
            }
        }
    });
    $.ui.plugin.add("draggable", "stack", {
        start: function(event, ui, instance) {
            var min, o = instance.options, group = $.makeArray($(o.stack)).sort(function(a, b) {
                return (parseInt($(a).css("zIndex"), 10) || 0) - (parseInt($(b).css("zIndex"), 10) || 0);
            });
            if (!group.length) {
                return;
            }
            min = parseInt($(group[0]).css("zIndex"), 10) || 0;
            $(group).each(function(i) {
                $(this).css("zIndex", min + i);
            });
            this.css("zIndex", min + group.length);
        }
    });
    $.ui.plugin.add("draggable", "zIndex", {
        start: function(event, ui, instance) {
            var t = $(ui.helper), o = instance.options;
            if (t.css("zIndex")) {
                o._zIndex = t.css("zIndex");
            }
            t.css("zIndex", o.zIndex);
        },
        stop: function(event, ui, instance) {
            var o = instance.options;
            if (o._zIndex) {
                $(ui.helper).css("zIndex", o._zIndex);
            }
        }
    });
    var widgetsDraggable = $.ui.draggable;
    $.widget("ui.resizable", $.ui.mouse, {
        version: "1.13.1",
        widgetEventPrefix: "resize",
        options: {
            alsoResize: false,
            animate: false,
            animateDuration: "slow",
            animateEasing: "swing",
            aspectRatio: false,
            autoHide: false,
            classes: {
                "ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se"
            },
            containment: false,
            ghost: false,
            grid: false,
            handles: "e,s,se",
            helper: false,
            maxHeight: null,
            maxWidth: null,
            minHeight: 10,
            minWidth: 10,
            zIndex: 90,
            resize: null,
            start: null,
            stop: null
        },
        _num: function(value) {
            return parseFloat(value) || 0;
        },
        _isNumber: function(value) {
            return !isNaN(parseFloat(value));
        },
        _hasScroll: function(el, a) {
            if ($(el).css("overflow") === "hidden") {
                return false;
            }
            var scroll = a && a === "left" ? "scrollLeft" : "scrollTop", has = false;
            if (el[scroll] > 0) {
                return true;
            }
            try {
                el[scroll] = 1;
                has = el[scroll] > 0;
                el[scroll] = 0;
            } catch (e) {}
            return has;
        },
        _create: function() {
            var margins, o = this.options, that = this;
            this._addClass("ui-resizable");
            $.extend(this, {
                _aspectRatio: !!o.aspectRatio,
                aspectRatio: o.aspectRatio,
                originalElement: this.element,
                _proportionallyResizeElements: [],
                _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
            });
            if (this.element[0].nodeName.match(/^(canvas|textarea|input|select|button|img)$/i)) {
                this.element.wrap($("<div class='ui-wrapper'></div>").css({
                    overflow: "hidden",
                    position: this.element.css("position"),
                    width: this.element.outerWidth(),
                    height: this.element.outerHeight(),
                    top: this.element.css("top"),
                    left: this.element.css("left")
                }));
                this.element = this.element.parent().data("ui-resizable", this.element.resizable("instance"));
                this.elementIsWrapper = true;
                margins = {
                    marginTop: this.originalElement.css("marginTop"),
                    marginRight: this.originalElement.css("marginRight"),
                    marginBottom: this.originalElement.css("marginBottom"),
                    marginLeft: this.originalElement.css("marginLeft")
                };
                this.element.css(margins);
                this.originalElement.css("margin", 0);
                this.originalResizeStyle = this.originalElement.css("resize");
                this.originalElement.css("resize", "none");
                this._proportionallyResizeElements.push(this.originalElement.css({
                    position: "static",
                    zoom: 1,
                    display: "block"
                }));
                this.originalElement.css(margins);
                this._proportionallyResize();
            }
            this._setupHandles();
            if (o.autoHide) {
                $(this.element).on("mouseenter", function() {
                    if (o.disabled) {
                        return;
                    }
                    that._removeClass("ui-resizable-autohide");
                    that._handles.show();
                }).on("mouseleave", function() {
                    if (o.disabled) {
                        return;
                    }
                    if (!that.resizing) {
                        that._addClass("ui-resizable-autohide");
                        that._handles.hide();
                    }
                });
            }
            this._mouseInit();
        },
        _destroy: function() {
            this._mouseDestroy();
            this._addedHandles.remove();
            var wrapper, _destroy = function(exp) {
                $(exp).removeData("resizable").removeData("ui-resizable").off(".resizable");
            };
            if (this.elementIsWrapper) {
                _destroy(this.element);
                wrapper = this.element;
                this.originalElement.css({
                    position: wrapper.css("position"),
                    width: wrapper.outerWidth(),
                    height: wrapper.outerHeight(),
                    top: wrapper.css("top"),
                    left: wrapper.css("left")
                }).insertAfter(wrapper);
                wrapper.remove();
            }
            this.originalElement.css("resize", this.originalResizeStyle);
            _destroy(this.originalElement);
            return this;
        },
        _setOption: function(key, value) {
            this._super(key, value);
            switch (key) {
              case "handles":
                this._removeHandles();
                this._setupHandles();
                break;

              case "aspectRatio":
                this._aspectRatio = !!value;
                break;

              default:
                break;
            }
        },
        _setupHandles: function() {
            var o = this.options, handle, i, n, hname, axis, that = this;
            this.handles = o.handles || (!$(".ui-resizable-handle", this.element).length ? "e,s,se" : {
                n: ".ui-resizable-n",
                e: ".ui-resizable-e",
                s: ".ui-resizable-s",
                w: ".ui-resizable-w",
                se: ".ui-resizable-se",
                sw: ".ui-resizable-sw",
                ne: ".ui-resizable-ne",
                nw: ".ui-resizable-nw"
            });
            this._handles = $();
            this._addedHandles = $();
            if (this.handles.constructor === String) {
                if (this.handles === "all") {
                    this.handles = "n,e,s,w,se,sw,ne,nw";
                }
                n = this.handles.split(",");
                this.handles = {};
                for (i = 0; i < n.length; i++) {
                    handle = String.prototype.trim.call(n[i]);
                    hname = "ui-resizable-" + handle;
                    axis = $("<div>");
                    this._addClass(axis, "ui-resizable-handle " + hname);
                    axis.css({
                        zIndex: o.zIndex
                    });
                    this.handles[handle] = ".ui-resizable-" + handle;
                    if (!this.element.children(this.handles[handle]).length) {
                        this.element.append(axis);
                        this._addedHandles = this._addedHandles.add(axis);
                    }
                }
            }
            this._renderAxis = function(target) {
                var i, axis, padPos, padWrapper;
                target = target || this.element;
                for (i in this.handles) {
                    if (this.handles[i].constructor === String) {
                        this.handles[i] = this.element.children(this.handles[i]).first().show();
                    } else if (this.handles[i].jquery || this.handles[i].nodeType) {
                        this.handles[i] = $(this.handles[i]);
                        this._on(this.handles[i], {
                            mousedown: that._mouseDown
                        });
                    }
                    if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/^(textarea|input|select|button)$/i)) {
                        axis = $(this.handles[i], this.element);
                        padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
                        padPos = [ "padding", /ne|nw|n/.test(i) ? "Top" : /se|sw|s/.test(i) ? "Bottom" : /^e$/.test(i) ? "Right" : "Left" ].join("");
                        target.css(padPos, padWrapper);
                        this._proportionallyResize();
                    }
                    this._handles = this._handles.add(this.handles[i]);
                }
            };
            this._renderAxis(this.element);
            this._handles = this._handles.add(this.element.find(".ui-resizable-handle"));
            this._handles.disableSelection();
            this._handles.on("mouseover", function() {
                if (!that.resizing) {
                    if (this.className) {
                        axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
                    }
                    that.axis = axis && axis[1] ? axis[1] : "se";
                }
            });
            if (o.autoHide) {
                this._handles.hide();
                this._addClass("ui-resizable-autohide");
            }
        },
        _removeHandles: function() {
            this._addedHandles.remove();
        },
        _mouseCapture: function(event) {
            var i, handle, capture = false;
            for (i in this.handles) {
                handle = $(this.handles[i])[0];
                if (handle === event.target || $.contains(handle, event.target)) {
                    capture = true;
                }
            }
            return !this.options.disabled && capture;
        },
        _mouseStart: function(event) {
            var curleft, curtop, cursor, o = this.options, el = this.element;
            this.resizing = true;
            this._renderProxy();
            curleft = this._num(this.helper.css("left"));
            curtop = this._num(this.helper.css("top"));
            if (o.containment) {
                curleft += $(o.containment).scrollLeft() || 0;
                curtop += $(o.containment).scrollTop() || 0;
            }
            this.offset = this.helper.offset();
            this.position = {
                left: curleft,
                top: curtop
            };
            this.size = this._helper ? {
                width: this.helper.width(),
                height: this.helper.height()
            } : {
                width: el.width(),
                height: el.height()
            };
            this.originalSize = this._helper ? {
                width: el.outerWidth(),
                height: el.outerHeight()
            } : {
                width: el.width(),
                height: el.height()
            };
            this.sizeDiff = {
                width: el.outerWidth() - el.width(),
                height: el.outerHeight() - el.height()
            };
            this.originalPosition = {
                left: curleft,
                top: curtop
            };
            this.originalMousePosition = {
                left: event.pageX,
                top: event.pageY
            };
            this.aspectRatio = typeof o.aspectRatio === "number" ? o.aspectRatio : this.originalSize.width / this.originalSize.height || 1;
            cursor = $(".ui-resizable-" + this.axis).css("cursor");
            $("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor);
            this._addClass("ui-resizable-resizing");
            this._propagate("start", event);
            return true;
        },
        _mouseDrag: function(event) {
            var data, props, smp = this.originalMousePosition, a = this.axis, dx = event.pageX - smp.left || 0, dy = event.pageY - smp.top || 0, trigger = this._change[a];
            this._updatePrevProperties();
            if (!trigger) {
                return false;
            }
            data = trigger.apply(this, [ event, dx, dy ]);
            this._updateVirtualBoundaries(event.shiftKey);
            if (this._aspectRatio || event.shiftKey) {
                data = this._updateRatio(data, event);
            }
            data = this._respectSize(data, event);
            this._updateCache(data);
            this._propagate("resize", event);
            props = this._applyChanges();
            if (!this._helper && this._proportionallyResizeElements.length) {
                this._proportionallyResize();
            }
            if (!$.isEmptyObject(props)) {
                this._updatePrevProperties();
                this._trigger("resize", event, this.ui());
                this._applyChanges();
            }
            return false;
        },
        _mouseStop: function(event) {
            this.resizing = false;
            var pr, ista, soffseth, soffsetw, s, left, top, o = this.options, that = this;
            if (this._helper) {
                pr = this._proportionallyResizeElements;
                ista = pr.length && /textarea/i.test(pr[0].nodeName);
                soffseth = ista && this._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height;
                soffsetw = ista ? 0 : that.sizeDiff.width;
                s = {
                    width: that.helper.width() - soffsetw,
                    height: that.helper.height() - soffseth
                };
                left = parseFloat(that.element.css("left")) + (that.position.left - that.originalPosition.left) || null;
                top = parseFloat(that.element.css("top")) + (that.position.top - that.originalPosition.top) || null;
                if (!o.animate) {
                    this.element.css($.extend(s, {
                        top: top,
                        left: left
                    }));
                }
                that.helper.height(that.size.height);
                that.helper.width(that.size.width);
                if (this._helper && !o.animate) {
                    this._proportionallyResize();
                }
            }
            $("body").css("cursor", "auto");
            this._removeClass("ui-resizable-resizing");
            this._propagate("stop", event);
            if (this._helper) {
                this.helper.remove();
            }
            return false;
        },
        _updatePrevProperties: function() {
            this.prevPosition = {
                top: this.position.top,
                left: this.position.left
            };
            this.prevSize = {
                width: this.size.width,
                height: this.size.height
            };
        },
        _applyChanges: function() {
            var props = {};
            if (this.position.top !== this.prevPosition.top) {
                props.top = this.position.top + "px";
            }
            if (this.position.left !== this.prevPosition.left) {
                props.left = this.position.left + "px";
            }
            if (this.size.width !== this.prevSize.width) {
                props.width = this.size.width + "px";
            }
            if (this.size.height !== this.prevSize.height) {
                props.height = this.size.height + "px";
            }
            this.helper.css(props);
            return props;
        },
        _updateVirtualBoundaries: function(forceAspectRatio) {
            var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b, o = this.options;
            b = {
                minWidth: this._isNumber(o.minWidth) ? o.minWidth : 0,
                maxWidth: this._isNumber(o.maxWidth) ? o.maxWidth : Infinity,
                minHeight: this._isNumber(o.minHeight) ? o.minHeight : 0,
                maxHeight: this._isNumber(o.maxHeight) ? o.maxHeight : Infinity
            };
            if (this._aspectRatio || forceAspectRatio) {
                pMinWidth = b.minHeight * this.aspectRatio;
                pMinHeight = b.minWidth / this.aspectRatio;
                pMaxWidth = b.maxHeight * this.aspectRatio;
                pMaxHeight = b.maxWidth / this.aspectRatio;
                if (pMinWidth > b.minWidth) {
                    b.minWidth = pMinWidth;
                }
                if (pMinHeight > b.minHeight) {
                    b.minHeight = pMinHeight;
                }
                if (pMaxWidth < b.maxWidth) {
                    b.maxWidth = pMaxWidth;
                }
                if (pMaxHeight < b.maxHeight) {
                    b.maxHeight = pMaxHeight;
                }
            }
            this._vBoundaries = b;
        },
        _updateCache: function(data) {
            this.offset = this.helper.offset();
            if (this._isNumber(data.left)) {
                this.position.left = data.left;
            }
            if (this._isNumber(data.top)) {
                this.position.top = data.top;
            }
            if (this._isNumber(data.height)) {
                this.size.height = data.height;
            }
            if (this._isNumber(data.width)) {
                this.size.width = data.width;
            }
        },
        _updateRatio: function(data) {
            var cpos = this.position, csize = this.size, a = this.axis;
            if (this._isNumber(data.height)) {
                data.width = data.height * this.aspectRatio;
            } else if (this._isNumber(data.width)) {
                data.height = data.width / this.aspectRatio;
            }
            if (a === "sw") {
                data.left = cpos.left + (csize.width - data.width);
                data.top = null;
            }
            if (a === "nw") {
                data.top = cpos.top + (csize.height - data.height);
                data.left = cpos.left + (csize.width - data.width);
            }
            return data;
        },
        _respectSize: function(data) {
            var o = this._vBoundaries, a = this.axis, ismaxw = this._isNumber(data.width) && o.maxWidth && o.maxWidth < data.width, ismaxh = this._isNumber(data.height) && o.maxHeight && o.maxHeight < data.height, isminw = this._isNumber(data.width) && o.minWidth && o.minWidth > data.width, isminh = this._isNumber(data.height) && o.minHeight && o.minHeight > data.height, dw = this.originalPosition.left + this.originalSize.width, dh = this.originalPosition.top + this.originalSize.height, cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
            if (isminw) {
                data.width = o.minWidth;
            }
            if (isminh) {
                data.height = o.minHeight;
            }
            if (ismaxw) {
                data.width = o.maxWidth;
            }
            if (ismaxh) {
                data.height = o.maxHeight;
            }
            if (isminw && cw) {
                data.left = dw - o.minWidth;
            }
            if (ismaxw && cw) {
                data.left = dw - o.maxWidth;
            }
            if (isminh && ch) {
                data.top = dh - o.minHeight;
            }
            if (ismaxh && ch) {
                data.top = dh - o.maxHeight;
            }
            if (!data.width && !data.height && !data.left && data.top) {
                data.top = null;
            } else if (!data.width && !data.height && !data.top && data.left) {
                data.left = null;
            }
            return data;
        },
        _getPaddingPlusBorderDimensions: function(element) {
            var i = 0, widths = [], borders = [ element.css("borderTopWidth"), element.css("borderRightWidth"), element.css("borderBottomWidth"), element.css("borderLeftWidth") ], paddings = [ element.css("paddingTop"), element.css("paddingRight"), element.css("paddingBottom"), element.css("paddingLeft") ];
            for (;i < 4; i++) {
                widths[i] = parseFloat(borders[i]) || 0;
                widths[i] += parseFloat(paddings[i]) || 0;
            }
            return {
                height: widths[0] + widths[2],
                width: widths[1] + widths[3]
            };
        },
        _proportionallyResize: function() {
            if (!this._proportionallyResizeElements.length) {
                return;
            }
            var prel, i = 0, element = this.helper || this.element;
            for (;i < this._proportionallyResizeElements.length; i++) {
                prel = this._proportionallyResizeElements[i];
                if (!this.outerDimensions) {
                    this.outerDimensions = this._getPaddingPlusBorderDimensions(prel);
                }
                prel.css({
                    height: element.height() - this.outerDimensions.height || 0,
                    width: element.width() - this.outerDimensions.width || 0
                });
            }
        },
        _renderProxy: function() {
            var el = this.element, o = this.options;
            this.elementOffset = el.offset();
            if (this._helper) {
                this.helper = this.helper || $("<div></div>").css({
                    overflow: "hidden"
                });
                this._addClass(this.helper, this._helper);
                this.helper.css({
                    width: this.element.outerWidth(),
                    height: this.element.outerHeight(),
                    position: "absolute",
                    left: this.elementOffset.left + "px",
                    top: this.elementOffset.top + "px",
                    zIndex: ++o.zIndex
                });
                this.helper.appendTo("body").disableSelection();
            } else {
                this.helper = this.element;
            }
        },
        _change: {
            e: function(event, dx) {
                return {
                    width: this.originalSize.width + dx
                };
            },
            w: function(event, dx) {
                var cs = this.originalSize, sp = this.originalPosition;
                return {
                    left: sp.left + dx,
                    width: cs.width - dx
                };
            },
            n: function(event, dx, dy) {
                var cs = this.originalSize, sp = this.originalPosition;
                return {
                    top: sp.top + dy,
                    height: cs.height - dy
                };
            },
            s: function(event, dx, dy) {
                return {
                    height: this.originalSize.height + dy
                };
            },
            se: function(event, dx, dy) {
                return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [ event, dx, dy ]));
            },
            sw: function(event, dx, dy) {
                return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [ event, dx, dy ]));
            },
            ne: function(event, dx, dy) {
                return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [ event, dx, dy ]));
            },
            nw: function(event, dx, dy) {
                return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [ event, dx, dy ]));
            }
        },
        _propagate: function(n, event) {
            $.ui.plugin.call(this, n, [ event, this.ui() ]);
            if (n !== "resize") {
                this._trigger(n, event, this.ui());
            }
        },
        plugins: {},
        ui: function() {
            return {
                originalElement: this.originalElement,
                element: this.element,
                helper: this.helper,
                position: this.position,
                size: this.size,
                originalSize: this.originalSize,
                originalPosition: this.originalPosition
            };
        }
    });
    $.ui.plugin.add("resizable", "animate", {
        stop: function(event) {
            var that = $(this).resizable("instance"), o = that.options, pr = that._proportionallyResizeElements, ista = pr.length && /textarea/i.test(pr[0].nodeName), soffseth = ista && that._hasScroll(pr[0], "left") ? 0 : that.sizeDiff.height, soffsetw = ista ? 0 : that.sizeDiff.width, style = {
                width: that.size.width - soffsetw,
                height: that.size.height - soffseth
            }, left = parseFloat(that.element.css("left")) + (that.position.left - that.originalPosition.left) || null, top = parseFloat(that.element.css("top")) + (that.position.top - that.originalPosition.top) || null;
            that.element.animate($.extend(style, top && left ? {
                top: top,
                left: left
            } : {}), {
                duration: o.animateDuration,
                easing: o.animateEasing,
                step: function() {
                    var data = {
                        width: parseFloat(that.element.css("width")),
                        height: parseFloat(that.element.css("height")),
                        top: parseFloat(that.element.css("top")),
                        left: parseFloat(that.element.css("left"))
                    };
                    if (pr && pr.length) {
                        $(pr[0]).css({
                            width: data.width,
                            height: data.height
                        });
                    }
                    that._updateCache(data);
                    that._propagate("resize", event);
                }
            });
        }
    });
    $.ui.plugin.add("resizable", "containment", {
        start: function() {
            var element, p, co, ch, cw, width, height, that = $(this).resizable("instance"), o = that.options, el = that.element, oc = o.containment, ce = oc instanceof $ ? oc.get(0) : /parent/.test(oc) ? el.parent().get(0) : oc;
            if (!ce) {
                return;
            }
            that.containerElement = $(ce);
            if (/document/.test(oc) || oc === document) {
                that.containerOffset = {
                    left: 0,
                    top: 0
                };
                that.containerPosition = {
                    left: 0,
                    top: 0
                };
                that.parentData = {
                    element: $(document),
                    left: 0,
                    top: 0,
                    width: $(document).width(),
                    height: $(document).height() || document.body.parentNode.scrollHeight
                };
            } else {
                element = $(ce);
                p = [];
                $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) {
                    p[i] = that._num(element.css("padding" + name));
                });
                that.containerOffset = element.offset();
                that.containerPosition = element.position();
                that.containerSize = {
                    height: element.innerHeight() - p[3],
                    width: element.innerWidth() - p[1]
                };
                co = that.containerOffset;
                ch = that.containerSize.height;
                cw = that.containerSize.width;
                width = that._hasScroll(ce, "left") ? ce.scrollWidth : cw;
                height = that._hasScroll(ce) ? ce.scrollHeight : ch;
                that.parentData = {
                    element: ce,
                    left: co.left,
                    top: co.top,
                    width: width,
                    height: height
                };
            }
        },
        resize: function(event) {
            var woset, hoset, isParent, isOffsetRelative, that = $(this).resizable("instance"), o = that.options, co = that.containerOffset, cp = that.position, pRatio = that._aspectRatio || event.shiftKey, cop = {
                top: 0,
                left: 0
            }, ce = that.containerElement, continueResize = true;
            if (ce[0] !== document && /static/.test(ce.css("position"))) {
                cop = co;
            }
            if (cp.left < (that._helper ? co.left : 0)) {
                that.size.width = that.size.width + (that._helper ? that.position.left - co.left : that.position.left - cop.left);
                if (pRatio) {
                    that.size.height = that.size.width / that.aspectRatio;
                    continueResize = false;
                }
                that.position.left = o.helper ? co.left : 0;
            }
            if (cp.top < (that._helper ? co.top : 0)) {
                that.size.height = that.size.height + (that._helper ? that.position.top - co.top : that.position.top);
                if (pRatio) {
                    that.size.width = that.size.height * that.aspectRatio;
                    continueResize = false;
                }
                that.position.top = that._helper ? co.top : 0;
            }
            isParent = that.containerElement.get(0) === that.element.parent().get(0);
            isOffsetRelative = /relative|absolute/.test(that.containerElement.css("position"));
            if (isParent && isOffsetRelative) {
                that.offset.left = that.parentData.left + that.position.left;
                that.offset.top = that.parentData.top + that.position.top;
            } else {
                that.offset.left = that.element.offset().left;
                that.offset.top = that.element.offset().top;
            }
            woset = Math.abs(that.sizeDiff.width + (that._helper ? that.offset.left - cop.left : that.offset.left - co.left));
            hoset = Math.abs(that.sizeDiff.height + (that._helper ? that.offset.top - cop.top : that.offset.top - co.top));
            if (woset + that.size.width >= that.parentData.width) {
                that.size.width = that.parentData.width - woset;
                if (pRatio) {
                    that.size.height = that.size.width / that.aspectRatio;
                    continueResize = false;
                }
            }
            if (hoset + that.size.height >= that.parentData.height) {
                that.size.height = that.parentData.height - hoset;
                if (pRatio) {
                    that.size.width = that.size.height * that.aspectRatio;
                    continueResize = false;
                }
            }
            if (!continueResize) {
                that.position.left = that.prevPosition.left;
                that.position.top = that.prevPosition.top;
                that.size.width = that.prevSize.width;
                that.size.height = that.prevSize.height;
            }
        },
        stop: function() {
            var that = $(this).resizable("instance"), o = that.options, co = that.containerOffset, cop = that.containerPosition, ce = that.containerElement, helper = $(that.helper), ho = helper.offset(), w = helper.outerWidth() - that.sizeDiff.width, h = helper.outerHeight() - that.sizeDiff.height;
            if (that._helper && !o.animate && /relative/.test(ce.css("position"))) {
                $(this).css({
                    left: ho.left - cop.left - co.left,
                    width: w,
                    height: h
                });
            }
            if (that._helper && !o.animate && /static/.test(ce.css("position"))) {
                $(this).css({
                    left: ho.left - cop.left - co.left,
                    width: w,
                    height: h
                });
            }
        }
    });
    $.ui.plugin.add("resizable", "alsoResize", {
        start: function() {
            var that = $(this).resizable("instance"), o = that.options;
            $(o.alsoResize).each(function() {
                var el = $(this);
                el.data("ui-resizable-alsoresize", {
                    width: parseFloat(el.width()),
                    height: parseFloat(el.height()),
                    left: parseFloat(el.css("left")),
                    top: parseFloat(el.css("top"))
                });
            });
        },
        resize: function(event, ui) {
            var that = $(this).resizable("instance"), o = that.options, os = that.originalSize, op = that.originalPosition, delta = {
                height: that.size.height - os.height || 0,
                width: that.size.width - os.width || 0,
                top: that.position.top - op.top || 0,
                left: that.position.left - op.left || 0
            };
            $(o.alsoResize).each(function() {
                var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {}, css = el.parents(ui.originalElement[0]).length ? [ "width", "height" ] : [ "width", "height", "top", "left" ];
                $.each(css, function(i, prop) {
                    var sum = (start[prop] || 0) + (delta[prop] || 0);
                    if (sum && sum >= 0) {
                        style[prop] = sum || null;
                    }
                });
                el.css(style);
            });
        },
        stop: function() {
            $(this).removeData("ui-resizable-alsoresize");
        }
    });
    $.ui.plugin.add("resizable", "ghost", {
        start: function() {
            var that = $(this).resizable("instance"), cs = that.size;
            that.ghost = that.originalElement.clone();
            that.ghost.css({
                opacity: .25,
                display: "block",
                position: "relative",
                height: cs.height,
                width: cs.width,
                margin: 0,
                left: 0,
                top: 0
            });
            that._addClass(that.ghost, "ui-resizable-ghost");
            if ($.uiBackCompat !== false && typeof that.options.ghost === "string") {
                that.ghost.addClass(this.options.ghost);
            }
            that.ghost.appendTo(that.helper);
        },
        resize: function() {
            var that = $(this).resizable("instance");
            if (that.ghost) {
                that.ghost.css({
                    position: "relative",
                    height: that.size.height,
                    width: that.size.width
                });
            }
        },
        stop: function() {
            var that = $(this).resizable("instance");
            if (that.ghost && that.helper) {
                that.helper.get(0).removeChild(that.ghost.get(0));
            }
        }
    });
    $.ui.plugin.add("resizable", "grid", {
        resize: function() {
            var outerDimensions, that = $(this).resizable("instance"), o = that.options, cs = that.size, os = that.originalSize, op = that.originalPosition, a = that.axis, grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid, gridX = grid[0] || 1, gridY = grid[1] || 1, ox = Math.round((cs.width - os.width) / gridX) * gridX, oy = Math.round((cs.height - os.height) / gridY) * gridY, newWidth = os.width + ox, newHeight = os.height + oy, isMaxWidth = o.maxWidth && o.maxWidth < newWidth, isMaxHeight = o.maxHeight && o.maxHeight < newHeight, isMinWidth = o.minWidth && o.minWidth > newWidth, isMinHeight = o.minHeight && o.minHeight > newHeight;
            o.grid = grid;
            if (isMinWidth) {
                newWidth += gridX;
            }
            if (isMinHeight) {
                newHeight += gridY;
            }
            if (isMaxWidth) {
                newWidth -= gridX;
            }
            if (isMaxHeight) {
                newHeight -= gridY;
            }
            if (/^(se|s|e)$/.test(a)) {
                that.size.width = newWidth;
                that.size.height = newHeight;
            } else if (/^(ne)$/.test(a)) {
                that.size.width = newWidth;
                that.size.height = newHeight;
                that.position.top = op.top - oy;
            } else if (/^(sw)$/.test(a)) {
                that.size.width = newWidth;
                that.size.height = newHeight;
                that.position.left = op.left - ox;
            } else {
                if (newHeight - gridY <= 0 || newWidth - gridX <= 0) {
                    outerDimensions = that._getPaddingPlusBorderDimensions(this);
                }
                if (newHeight - gridY > 0) {
                    that.size.height = newHeight;
                    that.position.top = op.top - oy;
                } else {
                    newHeight = gridY - outerDimensions.height;
                    that.size.height = newHeight;
                    that.position.top = op.top + os.height - newHeight;
                }
                if (newWidth - gridX > 0) {
                    that.size.width = newWidth;
                    that.position.left = op.left - ox;
                } else {
                    newWidth = gridX - outerDimensions.width;
                    that.size.width = newWidth;
                    that.position.left = op.left + os.width - newWidth;
                }
            }
        }
    });
    var widgetsResizable = $.ui.resizable;
    $.widget("ui.dialog", {
        version: "1.13.1",
        options: {
            appendTo: "body",
            autoOpen: true,
            buttons: [],
            classes: {
                "ui-dialog": "ui-corner-all",
                "ui-dialog-titlebar": "ui-corner-all"
            },
            closeOnEscape: true,
            closeText: "Close",
            draggable: true,
            hide: null,
            height: "auto",
            maxHeight: null,
            maxWidth: null,
            minHeight: 150,
            minWidth: 150,
            modal: false,
            position: {
                my: "center",
                at: "center",
                of: window,
                collision: "fit",
                using: function(pos) {
                    var topOffset = $(this).css(pos).offset().top;
                    if (topOffset < 0) {
                        $(this).css("top", pos.top - topOffset);
                    }
                }
            },
            resizable: true,
            show: null,
            title: null,
            width: 300,
            beforeClose: null,
            close: null,
            drag: null,
            dragStart: null,
            dragStop: null,
            focus: null,
            open: null,
            resize: null,
            resizeStart: null,
            resizeStop: null
        },
        sizeRelatedOptions: {
            buttons: true,
            height: true,
            maxHeight: true,
            maxWidth: true,
            minHeight: true,
            minWidth: true,
            width: true
        },
        resizableRelatedOptions: {
            maxHeight: true,
            maxWidth: true,
            minHeight: true,
            minWidth: true
        },
        _create: function() {
            this.originalCss = {
                display: this.element[0].style.display,
                width: this.element[0].style.width,
                minHeight: this.element[0].style.minHeight,
                maxHeight: this.element[0].style.maxHeight,
                height: this.element[0].style.height
            };
            this.originalPosition = {
                parent: this.element.parent(),
                index: this.element.parent().children().index(this.element)
            };
            this.originalTitle = this.element.attr("title");
            if (this.options.title == null && this.originalTitle != null) {
                this.options.title = this.originalTitle;
            }
            if (this.options.disabled) {
                this.options.disabled = false;
            }
            this._createWrapper();
            this.element.show().removeAttr("title").appendTo(this.uiDialog);
            this._addClass("ui-dialog-content", "ui-widget-content");
            this._createTitlebar();
            this._createButtonPane();
            if (this.options.draggable && $.fn.draggable) {
                this._makeDraggable();
            }
            if (this.options.resizable && $.fn.resizable) {
                this._makeResizable();
            }
            this._isOpen = false;
            this._trackFocus();
        },
        _init: function() {
            if (this.options.autoOpen) {
                this.open();
            }
        },
        _appendTo: function() {
            var element = this.options.appendTo;
            if (element && (element.jquery || element.nodeType)) {
                return $(element);
            }
            return this.document.find(element || "body").eq(0);
        },
        _destroy: function() {
            var next, originalPosition = this.originalPosition;
            this._untrackInstance();
            this._destroyOverlay();
            this.element.removeUniqueId().css(this.originalCss).detach();
            this.uiDialog.remove();
            if (this.originalTitle) {
                this.element.attr("title", this.originalTitle);
            }
            next = originalPosition.parent.children().eq(originalPosition.index);
            if (next.length && next[0] !== this.element[0]) {
                next.before(this.element);
            } else {
                originalPosition.parent.append(this.element);
            }
        },
        widget: function() {
            return this.uiDialog;
        },
        disable: $.noop,
        enable: $.noop,
        close: function(event) {
            var that = this;
            if (!this._isOpen || this._trigger("beforeClose", event) === false) {
                return;
            }
            this._isOpen = false;
            this._focusedElement = null;
            this._destroyOverlay();
            this._untrackInstance();
            if (!this.opener.filter(":focusable").trigger("focus").length) {
                $.ui.safeBlur($.ui.safeActiveElement(this.document[0]));
            }
            this._hide(this.uiDialog, this.options.hide, function() {
                that._trigger("close", event);
            });
        },
        isOpen: function() {
            return this._isOpen;
        },
        moveToTop: function() {
            this._moveToTop();
        },
        _moveToTop: function(event, silent) {
            var moved = false, zIndices = this.uiDialog.siblings(".ui-front:visible").map(function() {
                return +$(this).css("z-index");
            }).get(), zIndexMax = Math.max.apply(null, zIndices);
            if (zIndexMax >= +this.uiDialog.css("z-index")) {
                this.uiDialog.css("z-index", zIndexMax + 1);
                moved = true;
            }
            if (moved && !silent) {
                this._trigger("focus", event);
            }
            return moved;
        },
        open: function() {
            var that = this;
            if (this._isOpen) {
                if (this._moveToTop()) {
                    this._focusTabbable();
                }
                return;
            }
            this._isOpen = true;
            this.opener = $($.ui.safeActiveElement(this.document[0]));
            this._size();
            this._position();
            this._createOverlay();
            this._moveToTop(null, true);
            if (this.overlay) {
                this.overlay.css("z-index", this.uiDialog.css("z-index") - 1);
            }
            this._show(this.uiDialog, this.options.show, function() {
                that._focusTabbable();
                that._trigger("focus");
            });
            this._makeFocusTarget();
            this._trigger("open");
        },
        _focusTabbable: function() {
            var hasFocus = this._focusedElement;
            if (!hasFocus) {
                hasFocus = this.element.find("[autofocus]");
            }
            if (!hasFocus.length) {
                hasFocus = this.element.find(":tabbable");
            }
            if (!hasFocus.length) {
                hasFocus = this.uiDialogButtonPane.find(":tabbable");
            }
            if (!hasFocus.length) {
                hasFocus = this.uiDialogTitlebarClose.filter(":tabbable");
            }
            if (!hasFocus.length) {
                hasFocus = this.uiDialog;
            }
            hasFocus.eq(0).trigger("focus");
        },
        _restoreTabbableFocus: function() {
            var activeElement = $.ui.safeActiveElement(this.document[0]), isActive = this.uiDialog[0] === activeElement || $.contains(this.uiDialog[0], activeElement);
            if (!isActive) {
                this._focusTabbable();
            }
        },
        _keepFocus: function(event) {
            event.preventDefault();
            this._restoreTabbableFocus();
            this._delay(this._restoreTabbableFocus);
        },
        _createWrapper: function() {
            this.uiDialog = $("<div>").hide().attr({
                tabIndex: -1,
                role: "dialog"
            }).appendTo(this._appendTo());
            this._addClass(this.uiDialog, "ui-dialog", "ui-widget ui-widget-content ui-front");
            this._on(this.uiDialog, {
                keydown: function(event) {
                    if (this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode && event.keyCode === $.ui.keyCode.ESCAPE) {
                        event.preventDefault();
                        this.close(event);
                        return;
                    }
                    if (event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented()) {
                        return;
                    }
                    var tabbables = this.uiDialog.find(":tabbable"), first = tabbables.first(), last = tabbables.last();
                    if ((event.target === last[0] || event.target === this.uiDialog[0]) && !event.shiftKey) {
                        this._delay(function() {
                            first.trigger("focus");
                        });
                        event.preventDefault();
                    } else if ((event.target === first[0] || event.target === this.uiDialog[0]) && event.shiftKey) {
                        this._delay(function() {
                            last.trigger("focus");
                        });
                        event.preventDefault();
                    }
                },
                mousedown: function(event) {
                    if (this._moveToTop(event)) {
                        this._focusTabbable();
                    }
                }
            });
            if (!this.element.find("[aria-describedby]").length) {
                this.uiDialog.attr({
                    "aria-describedby": this.element.uniqueId().attr("id")
                });
            }
        },
        _createTitlebar: function() {
            var uiDialogTitle;
            this.uiDialogTitlebar = $("<div>");
            this._addClass(this.uiDialogTitlebar, "ui-dialog-titlebar", "ui-widget-header ui-helper-clearfix");
            this._on(this.uiDialogTitlebar, {
                mousedown: function(event) {
                    if (!$(event.target).closest(".ui-dialog-titlebar-close")) {
                        this.uiDialog.trigger("focus");
                    }
                }
            });
            this.uiDialogTitlebarClose = $("<button type='button'></button>").button({
                label: $("<a>").text(this.options.closeText).html(),
                icon: "ui-icon-closethick",
                showLabel: false
            }).appendTo(this.uiDialogTitlebar);
            this._addClass(this.uiDialogTitlebarClose, "ui-dialog-titlebar-close");
            this._on(this.uiDialogTitlebarClose, {
                click: function(event) {
                    event.preventDefault();
                    this.close(event);
                }
            });
            uiDialogTitle = $("<span>").uniqueId().prependTo(this.uiDialogTitlebar);
            this._addClass(uiDialogTitle, "ui-dialog-title");
            this._title(uiDialogTitle);
            this.uiDialogTitlebar.prependTo(this.uiDialog);
            this.uiDialog.attr({
                "aria-labelledby": uiDialogTitle.attr("id")
            });
        },
        _title: function(title) {
            if (this.options.title) {
                title.text(this.options.title);
            } else {
                title.html("&#160;");
            }
        },
        _createButtonPane: function() {
            this.uiDialogButtonPane = $("<div>");
            this._addClass(this.uiDialogButtonPane, "ui-dialog-buttonpane", "ui-widget-content ui-helper-clearfix");
            this.uiButtonSet = $("<div>").appendTo(this.uiDialogButtonPane);
            this._addClass(this.uiButtonSet, "ui-dialog-buttonset");
            this._createButtons();
        },
        _createButtons: function() {
            var that = this, buttons = this.options.buttons;
            this.uiDialogButtonPane.remove();
            this.uiButtonSet.empty();
            if ($.isEmptyObject(buttons) || Array.isArray(buttons) && !buttons.length) {
                this._removeClass(this.uiDialog, "ui-dialog-buttons");
                return;
            }
            $.each(buttons, function(name, props) {
                var click, buttonOptions;
                props = typeof props === "function" ? {
                    click: props,
                    text: name
                } : props;
                props = $.extend({
                    type: "button"
                }, props);
                click = props.click;
                buttonOptions = {
                    icon: props.icon,
                    iconPosition: props.iconPosition,
                    showLabel: props.showLabel,
                    icons: props.icons,
                    text: props.text
                };
                delete props.click;
                delete props.icon;
                delete props.iconPosition;
                delete props.showLabel;
                delete props.icons;
                if (typeof props.text === "boolean") {
                    delete props.text;
                }
                $("<button></button>", props).button(buttonOptions).appendTo(that.uiButtonSet).on("click", function() {
                    click.apply(that.element[0], arguments);
                });
            });
            this._addClass(this.uiDialog, "ui-dialog-buttons");
            this.uiDialogButtonPane.appendTo(this.uiDialog);
        },
        _makeDraggable: function() {
            var that = this, options = this.options;
            function filteredUi(ui) {
                return {
                    position: ui.position,
                    offset: ui.offset
                };
            }
            this.uiDialog.draggable({
                cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
                handle: ".ui-dialog-titlebar",
                containment: "document",
                start: function(event, ui) {
                    that._addClass($(this), "ui-dialog-dragging");
                    that._blockFrames();
                    that._trigger("dragStart", event, filteredUi(ui));
                },
                drag: function(event, ui) {
                    that._trigger("drag", event, filteredUi(ui));
                },
                stop: function(event, ui) {
                    var left = ui.offset.left - that.document.scrollLeft(), top = ui.offset.top - that.document.scrollTop();
                    options.position = {
                        my: "left top",
                        at: "left" + (left >= 0 ? "+" : "") + left + " " + "top" + (top >= 0 ? "+" : "") + top,
                        of: that.window
                    };
                    that._removeClass($(this), "ui-dialog-dragging");
                    that._unblockFrames();
                    that._trigger("dragStop", event, filteredUi(ui));
                }
            });
        },
        _makeResizable: function() {
            var that = this, options = this.options, handles = options.resizable, position = this.uiDialog.css("position"), resizeHandles = typeof handles === "string" ? handles : "n,e,s,w,se,sw,ne,nw";
            function filteredUi(ui) {
                return {
                    originalPosition: ui.originalPosition,
                    originalSize: ui.originalSize,
                    position: ui.position,
                    size: ui.size
                };
            }
            this.uiDialog.resizable({
                cancel: ".ui-dialog-content",
                containment: "document",
                alsoResize: this.element,
                maxWidth: options.maxWidth,
                maxHeight: options.maxHeight,
                minWidth: options.minWidth,
                minHeight: this._minHeight(),
                handles: resizeHandles,
                start: function(event, ui) {
                    that._addClass($(this), "ui-dialog-resizing");
                    that._blockFrames();
                    that._trigger("resizeStart", event, filteredUi(ui));
                },
                resize: function(event, ui) {
                    that._trigger("resize", event, filteredUi(ui));
                },
                stop: function(event, ui) {
                    var offset = that.uiDialog.offset(), left = offset.left - that.document.scrollLeft(), top = offset.top - that.document.scrollTop();
                    options.height = that.uiDialog.height();
                    options.width = that.uiDialog.width();
                    options.position = {
                        my: "left top",
                        at: "left" + (left >= 0 ? "+" : "") + left + " " + "top" + (top >= 0 ? "+" : "") + top,
                        of: that.window
                    };
                    that._removeClass($(this), "ui-dialog-resizing");
                    that._unblockFrames();
                    that._trigger("resizeStop", event, filteredUi(ui));
                }
            }).css("position", position);
        },
        _trackFocus: function() {
            this._on(this.widget(), {
                focusin: function(event) {
                    this._makeFocusTarget();
                    this._focusedElement = $(event.target);
                }
            });
        },
        _makeFocusTarget: function() {
            this._untrackInstance();
            this._trackingInstances().unshift(this);
        },
        _untrackInstance: function() {
            var instances = this._trackingInstances(), exists = $.inArray(this, instances);
            if (exists !== -1) {
                instances.splice(exists, 1);
            }
        },
        _trackingInstances: function() {
            var instances = this.document.data("ui-dialog-instances");
            if (!instances) {
                instances = [];
                this.document.data("ui-dialog-instances", instances);
            }
            return instances;
        },
        _minHeight: function() {
            var options = this.options;
            return options.height === "auto" ? options.minHeight : Math.min(options.minHeight, options.height);
        },
        _position: function() {
            var isVisible = this.uiDialog.is(":visible");
            if (!isVisible) {
                this.uiDialog.show();
            }
            this.uiDialog.position(this.options.position);
            if (!isVisible) {
                this.uiDialog.hide();
            }
        },
        _setOptions: function(options) {
            var that = this, resize = false, resizableOptions = {};
            $.each(options, function(key, value) {
                that._setOption(key, value);
                if (key in that.sizeRelatedOptions) {
                    resize = true;
                }
                if (key in that.resizableRelatedOptions) {
                    resizableOptions[key] = value;
                }
            });
            if (resize) {
                this._size();
                this._position();
            }
            if (this.uiDialog.is(":data(ui-resizable)")) {
                this.uiDialog.resizable("option", resizableOptions);
            }
        },
        _setOption: function(key, value) {
            var isDraggable, isResizable, uiDialog = this.uiDialog;
            if (key === "disabled") {
                return;
            }
            this._super(key, value);
            if (key === "appendTo") {
                this.uiDialog.appendTo(this._appendTo());
            }
            if (key === "buttons") {
                this._createButtons();
            }
            if (key === "closeText") {
                this.uiDialogTitlebarClose.button({
                    label: $("<a>").text("" + this.options.closeText).html()
                });
            }
            if (key === "draggable") {
                isDraggable = uiDialog.is(":data(ui-draggable)");
                if (isDraggable && !value) {
                    uiDialog.draggable("destroy");
                }
                if (!isDraggable && value) {
                    this._makeDraggable();
                }
            }
            if (key === "position") {
                this._position();
            }
            if (key === "resizable") {
                isResizable = uiDialog.is(":data(ui-resizable)");
                if (isResizable && !value) {
                    uiDialog.resizable("destroy");
                }
                if (isResizable && typeof value === "string") {
                    uiDialog.resizable("option", "handles", value);
                }
                if (!isResizable && value !== false) {
                    this._makeResizable();
                }
            }
            if (key === "title") {
                this._title(this.uiDialogTitlebar.find(".ui-dialog-title"));
            }
        },
        _size: function() {
            var nonContentHeight, minContentHeight, maxContentHeight, options = this.options;
            this.element.show().css({
                width: "auto",
                minHeight: 0,
                maxHeight: "none",
                height: 0
            });
            if (options.minWidth > options.width) {
                options.width = options.minWidth;
            }
            nonContentHeight = this.uiDialog.css({
                height: "auto",
                width: options.width
            }).outerHeight();
            minContentHeight = Math.max(0, options.minHeight - nonContentHeight);
            maxContentHeight = typeof options.maxHeight === "number" ? Math.max(0, options.maxHeight - nonContentHeight) : "none";
            if (options.height === "auto") {
                this.element.css({
                    minHeight: minContentHeight,
                    maxHeight: maxContentHeight,
                    height: "auto"
                });
            } else {
                this.element.height(Math.max(0, options.height - nonContentHeight));
            }
            if (this.uiDialog.is(":data(ui-resizable)")) {
                this.uiDialog.resizable("option", "minHeight", this._minHeight());
            }
        },
        _blockFrames: function() {
            this.iframeBlocks = this.document.find("iframe").map(function() {
                var iframe = $(this);
                return $("<div>").css({
                    position: "absolute",
                    width: iframe.outerWidth(),
                    height: iframe.outerHeight()
                }).appendTo(iframe.parent()).offset(iframe.offset())[0];
            });
        },
        _unblockFrames: function() {
            if (this.iframeBlocks) {
                this.iframeBlocks.remove();
                delete this.iframeBlocks;
            }
        },
        _allowInteraction: function(event) {
            if ($(event.target).closest(".ui-dialog").length) {
                return true;
            }
            return !!$(event.target).closest(".ui-datepicker").length;
        },
        _createOverlay: function() {
            if (!this.options.modal) {
                return;
            }
            var jqMinor = $.fn.jquery.substring(0, 4);
            var isOpening = true;
            this._delay(function() {
                isOpening = false;
            });
            if (!this.document.data("ui-dialog-overlays")) {
                this.document.on("focusin.ui-dialog", function(event) {
                    if (isOpening) {
                        return;
                    }
                    var instance = this._trackingInstances()[0];
                    if (!instance._allowInteraction(event)) {
                        event.preventDefault();
                        instance._focusTabbable();
                        if (jqMinor === "3.4." || jqMinor === "3.5.") {
                            instance._delay(instance._restoreTabbableFocus);
                        }
                    }
                }.bind(this));
            }
            this.overlay = $("<div>").appendTo(this._appendTo());
            this._addClass(this.overlay, null, "ui-widget-overlay ui-front");
            this._on(this.overlay, {
                mousedown: "_keepFocus"
            });
            this.document.data("ui-dialog-overlays", (this.document.data("ui-dialog-overlays") || 0) + 1);
        },
        _destroyOverlay: function() {
            if (!this.options.modal) {
                return;
            }
            if (this.overlay) {
                var overlays = this.document.data("ui-dialog-overlays") - 1;
                if (!overlays) {
                    this.document.off("focusin.ui-dialog");
                    this.document.removeData("ui-dialog-overlays");
                } else {
                    this.document.data("ui-dialog-overlays", overlays);
                }
                this.overlay.remove();
                this.overlay = null;
            }
        }
    });
    if ($.uiBackCompat !== false) {
        $.widget("ui.dialog", $.ui.dialog, {
            options: {
                dialogClass: ""
            },
            _createWrapper: function() {
                this._super();
                this.uiDialog.addClass(this.options.dialogClass);
            },
            _setOption: function(key, value) {
                if (key === "dialogClass") {
                    this.uiDialog.removeClass(this.options.dialogClass).addClass(value);
                }
                this._superApply(arguments);
            }
        });
    }
    var widgetsDialog = $.ui.dialog;
    $.widget("ui.droppable", {
        version: "1.13.1",
        widgetEventPrefix: "drop",
        options: {
            accept: "*",
            addClasses: true,
            greedy: false,
            scope: "default",
            tolerance: "intersect",
            activate: null,
            deactivate: null,
            drop: null,
            out: null,
            over: null
        },
        _create: function() {
            var proportions, o = this.options, accept = o.accept;
            this.isover = false;
            this.isout = true;
            this.accept = typeof accept === "function" ? accept : function(d) {
                return d.is(accept);
            };
            this.proportions = function() {
                if (arguments.length) {
                    proportions = arguments[0];
                } else {
                    return proportions ? proportions : proportions = {
                        width: this.element[0].offsetWidth,
                        height: this.element[0].offsetHeight
                    };
                }
            };
            this._addToManager(o.scope);
            if (o.addClasses) {
                this._addClass("ui-droppable");
            }
        },
        _addToManager: function(scope) {
            $.ui.ddmanager.droppables[scope] = $.ui.ddmanager.droppables[scope] || [];
            $.ui.ddmanager.droppables[scope].push(this);
        },
        _splice: function(drop) {
            var i = 0;
            for (;i < drop.length; i++) {
                if (drop[i] === this) {
                    drop.splice(i, 1);
                }
            }
        },
        _destroy: function() {
            var drop = $.ui.ddmanager.droppables[this.options.scope];
            this._splice(drop);
        },
        _setOption: function(key, value) {
            if (key === "accept") {
                this.accept = typeof value === "function" ? value : function(d) {
                    return d.is(value);
                };
            } else if (key === "scope") {
                var drop = $.ui.ddmanager.droppables[this.options.scope];
                this._splice(drop);
                this._addToManager(value);
            }
            this._super(key, value);
        },
        _activate: function(event) {
            var draggable = $.ui.ddmanager.current;
            this._addActiveClass();
            if (draggable) {
                this._trigger("activate", event, this.ui(draggable));
            }
        },
        _deactivate: function(event) {
            var draggable = $.ui.ddmanager.current;
            this._removeActiveClass();
            if (draggable) {
                this._trigger("deactivate", event, this.ui(draggable));
            }
        },
        _over: function(event) {
            var draggable = $.ui.ddmanager.current;
            if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
                return;
            }
            if (this.accept.call(this.element[0], draggable.currentItem || draggable.element)) {
                this._addHoverClass();
                this._trigger("over", event, this.ui(draggable));
            }
        },
        _out: function(event) {
            var draggable = $.ui.ddmanager.current;
            if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
                return;
            }
            if (this.accept.call(this.element[0], draggable.currentItem || draggable.element)) {
                this._removeHoverClass();
                this._trigger("out", event, this.ui(draggable));
            }
        },
        _drop: function(event, custom) {
            var draggable = custom || $.ui.ddmanager.current, childrenIntersection = false;
            if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
                return false;
            }
            this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function() {
                var inst = $(this).droppable("instance");
                if (inst.options.greedy && !inst.options.disabled && inst.options.scope === draggable.options.scope && inst.accept.call(inst.element[0], draggable.currentItem || draggable.element) && $.ui.intersect(draggable, $.extend(inst, {
                    offset: inst.element.offset()
                }), inst.options.tolerance, event)) {
                    childrenIntersection = true;
                    return false;
                }
            });
            if (childrenIntersection) {
                return false;
            }
            if (this.accept.call(this.element[0], draggable.currentItem || draggable.element)) {
                this._removeActiveClass();
                this._removeHoverClass();
                this._trigger("drop", event, this.ui(draggable));
                return this.element;
            }
            return false;
        },
        ui: function(c) {
            return {
                draggable: c.currentItem || c.element,
                helper: c.helper,
                position: c.position,
                offset: c.positionAbs
            };
        },
        _addHoverClass: function() {
            this._addClass("ui-droppable-hover");
        },
        _removeHoverClass: function() {
            this._removeClass("ui-droppable-hover");
        },
        _addActiveClass: function() {
            this._addClass("ui-droppable-active");
        },
        _removeActiveClass: function() {
            this._removeClass("ui-droppable-active");
        }
    });
    $.ui.intersect = function() {
        function isOverAxis(x, reference, size) {
            return x >= reference && x < reference + size;
        }
        return function(draggable, droppable, toleranceMode, event) {
            if (!droppable.offset) {
                return false;
            }
            var x1 = (draggable.positionAbs || draggable.position.absolute).left + draggable.margins.left, y1 = (draggable.positionAbs || draggable.position.absolute).top + draggable.margins.top, x2 = x1 + draggable.helperProportions.width, y2 = y1 + draggable.helperProportions.height, l = droppable.offset.left, t = droppable.offset.top, r = l + droppable.proportions().width, b = t + droppable.proportions().height;
            switch (toleranceMode) {
              case "fit":
                return l <= x1 && x2 <= r && t <= y1 && y2 <= b;

              case "intersect":
                return l < x1 + draggable.helperProportions.width / 2 && x2 - draggable.helperProportions.width / 2 < r && t < y1 + draggable.helperProportions.height / 2 && y2 - draggable.helperProportions.height / 2 < b;

              case "pointer":
                return isOverAxis(event.pageY, t, droppable.proportions().height) && isOverAxis(event.pageX, l, droppable.proportions().width);

              case "touch":
                return (y1 >= t && y1 <= b || y2 >= t && y2 <= b || y1 < t && y2 > b) && (x1 >= l && x1 <= r || x2 >= l && x2 <= r || x1 < l && x2 > r);

              default:
                return false;
            }
        };
    }();
    $.ui.ddmanager = {
        current: null,
        droppables: {
            default: []
        },
        prepareOffsets: function(t, event) {
            var i, j, m = $.ui.ddmanager.droppables[t.options.scope] || [], type = event ? event.type : null, list = (t.currentItem || t.element).find(":data(ui-droppable)").addBack();
            droppablesLoop: for (i = 0; i < m.length; i++) {
                if (m[i].options.disabled || t && !m[i].accept.call(m[i].element[0], t.currentItem || t.element)) {
                    continue;
                }
                for (j = 0; j < list.length; j++) {
                    if (list[j] === m[i].element[0]) {
                        m[i].proportions().height = 0;
                        continue droppablesLoop;
                    }
                }
                m[i].visible = m[i].element.css("display") !== "none";
                if (!m[i].visible) {
                    continue;
                }
                if (type === "mousedown") {
                    m[i]._activate.call(m[i], event);
                }
                m[i].offset = m[i].element.offset();
                m[i].proportions({
                    width: m[i].element[0].offsetWidth,
                    height: m[i].element[0].offsetHeight
                });
            }
        },
        drop: function(draggable, event) {
            var dropped = false;
            $.each(($.ui.ddmanager.droppables[draggable.options.scope] || []).slice(), function() {
                if (!this.options) {
                    return;
                }
                if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance, event)) {
                    dropped = this._drop.call(this, event) || dropped;
                }
                if (!this.options.disabled && this.visible && this.accept.call(this.element[0], draggable.currentItem || draggable.element)) {
                    this.isout = true;
                    this.isover = false;
                    this._deactivate.call(this, event);
                }
            });
            return dropped;
        },
        dragStart: function(draggable, event) {
            draggable.element.parentsUntil("body").on("scroll.droppable", function() {
                if (!draggable.options.refreshPositions) {
                    $.ui.ddmanager.prepareOffsets(draggable, event);
                }
            });
        },
        drag: function(draggable, event) {
            if (draggable.options.refreshPositions) {
                $.ui.ddmanager.prepareOffsets(draggable, event);
            }
            $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
                if (this.options.disabled || this.greedyChild || !this.visible) {
                    return;
                }
                var parentInstance, scope, parent, intersects = $.ui.intersect(draggable, this, this.options.tolerance, event), c = !intersects && this.isover ? "isout" : intersects && !this.isover ? "isover" : null;
                if (!c) {
                    return;
                }
                if (this.options.greedy) {
                    scope = this.options.scope;
                    parent = this.element.parents(":data(ui-droppable)").filter(function() {
                        return $(this).droppable("instance").options.scope === scope;
                    });
                    if (parent.length) {
                        parentInstance = $(parent[0]).droppable("instance");
                        parentInstance.greedyChild = c === "isover";
                    }
                }
                if (parentInstance && c === "isover") {
                    parentInstance.isover = false;
                    parentInstance.isout = true;
                    parentInstance._out.call(parentInstance, event);
                }
                this[c] = true;
                this[c === "isout" ? "isover" : "isout"] = false;
                this[c === "isover" ? "_over" : "_out"].call(this, event);
                if (parentInstance && c === "isout") {
                    parentInstance.isout = false;
                    parentInstance.isover = true;
                    parentInstance._over.call(parentInstance, event);
                }
            });
        },
        dragStop: function(draggable, event) {
            draggable.element.parentsUntil("body").off("scroll.droppable");
            if (!draggable.options.refreshPositions) {
                $.ui.ddmanager.prepareOffsets(draggable, event);
            }
        }
    };
    if ($.uiBackCompat !== false) {
        $.widget("ui.droppable", $.ui.droppable, {
            options: {
                hoverClass: false,
                activeClass: false
            },
            _addActiveClass: function() {
                this._super();
                if (this.options.activeClass) {
                    this.element.addClass(this.options.activeClass);
                }
            },
            _removeActiveClass: function() {
                this._super();
                if (this.options.activeClass) {
                    this.element.removeClass(this.options.activeClass);
                }
            },
            _addHoverClass: function() {
                this._super();
                if (this.options.hoverClass) {
                    this.element.addClass(this.options.hoverClass);
                }
            },
            _removeHoverClass: function() {
                this._super();
                if (this.options.hoverClass) {
                    this.element.removeClass(this.options.hoverClass);
                }
            }
        });
    }
    var widgetsDroppable = $.ui.droppable;
    var widgetsProgressbar = $.widget("ui.progressbar", {
        version: "1.13.1",
        options: {
            classes: {
                "ui-progressbar": "ui-corner-all",
                "ui-progressbar-value": "ui-corner-left",
                "ui-progressbar-complete": "ui-corner-right"
            },
            max: 100,
            value: 0,
            change: null,
            complete: null
        },
        min: 0,
        _create: function() {
            this.oldValue = this.options.value = this._constrainedValue();
            this.element.attr({
                role: "progressbar",
                "aria-valuemin": this.min
            });
            this._addClass("ui-progressbar", "ui-widget ui-widget-content");
            this.valueDiv = $("<div>").appendTo(this.element);
            this._addClass(this.valueDiv, "ui-progressbar-value", "ui-widget-header");
            this._refreshValue();
        },
        _destroy: function() {
            this.element.removeAttr("role aria-valuemin aria-valuemax aria-valuenow");
            this.valueDiv.remove();
        },
        value: function(newValue) {
            if (newValue === undefined) {
                return this.options.value;
            }
            this.options.value = this._constrainedValue(newValue);
            this._refreshValue();
        },
        _constrainedValue: function(newValue) {
            if (newValue === undefined) {
                newValue = this.options.value;
            }
            this.indeterminate = newValue === false;
            if (typeof newValue !== "number") {
                newValue = 0;
            }
            return this.indeterminate ? false : Math.min(this.options.max, Math.max(this.min, newValue));
        },
        _setOptions: function(options) {
            var value = options.value;
            delete options.value;
            this._super(options);
            this.options.value = this._constrainedValue(value);
            this._refreshValue();
        },
        _setOption: function(key, value) {
            if (key === "max") {
                value = Math.max(this.min, value);
            }
            this._super(key, value);
        },
        _setOptionDisabled: function(value) {
            this._super(value);
            this.element.attr("aria-disabled", value);
            this._toggleClass(null, "ui-state-disabled", !!value);
        },
        _percentage: function() {
            return this.indeterminate ? 100 : 100 * (this.options.value - this.min) / (this.options.max - this.min);
        },
        _refreshValue: function() {
            var value = this.options.value, percentage = this._percentage();
            this.valueDiv.toggle(this.indeterminate || value > this.min).width(percentage.toFixed(0) + "%");
            this._toggleClass(this.valueDiv, "ui-progressbar-complete", null, value === this.options.max)._toggleClass("ui-progressbar-indeterminate", null, this.indeterminate);
            if (this.indeterminate) {
                this.element.removeAttr("aria-valuenow");
                if (!this.overlayDiv) {
                    this.overlayDiv = $("<div>").appendTo(this.valueDiv);
                    this._addClass(this.overlayDiv, "ui-progressbar-overlay");
                }
            } else {
                this.element.attr({
                    "aria-valuemax": this.options.max,
                    "aria-valuenow": value
                });
                if (this.overlayDiv) {
                    this.overlayDiv.remove();
                    this.overlayDiv = null;
                }
            }
            if (this.oldValue !== value) {
                this.oldValue = value;
                this._trigger("change");
            }
            if (value === this.options.max) {
                this._trigger("complete");
            }
        }
    });
    var widgetsSelectable = $.widget("ui.selectable", $.ui.mouse, {
        version: "1.13.1",
        options: {
            appendTo: "body",
            autoRefresh: true,
            distance: 0,
            filter: "*",
            tolerance: "touch",
            selected: null,
            selecting: null,
            start: null,
            stop: null,
            unselected: null,
            unselecting: null
        },
        _create: function() {
            var that = this;
            this._addClass("ui-selectable");
            this.dragged = false;
            this.refresh = function() {
                that.elementPos = $(that.element[0]).offset();
                that.selectees = $(that.options.filter, that.element[0]);
                that._addClass(that.selectees, "ui-selectee");
                that.selectees.each(function() {
                    var $this = $(this), selecteeOffset = $this.offset(), rect = this.getBoundingClientRect(), pos = {
                        left: selecteeOffset.left - that.elementPos.left,
                        top: selecteeOffset.top - that.elementPos.top
                    };
                    $.data(this, "selectable-item", {
                        element: this,
                        $element: $this,
                        left: pos.left,
                        top: pos.top,
                        right: pos.left + rect.width,
                        bottom: pos.top + rect.height,
                        startselected: false,
                        selected: $this.hasClass("ui-selected"),
                        selecting: $this.hasClass("ui-selecting"),
                        unselecting: $this.hasClass("ui-unselecting")
                    });
                });
            };
            this.refresh();
            this._mouseInit();
            this.helper = $("<div>");
            this._addClass(this.helper, "ui-selectable-helper");
        },
        _destroy: function() {
            this.selectees.removeData("selectable-item");
            this._mouseDestroy();
        },
        _mouseStart: function(event) {
            var that = this, options = this.options;
            this.opos = [ event.pageX, event.pageY ];
            this.elementPos = $(this.element[0]).offset();
            if (this.options.disabled) {
                return;
            }
            this.selectees = $(options.filter, this.element[0]);
            this._trigger("start", event);
            $(options.appendTo).append(this.helper);
            this.helper.css({
                left: event.pageX,
                top: event.pageY,
                width: 0,
                height: 0
            });
            if (options.autoRefresh) {
                this.refresh();
            }
            this.selectees.filter(".ui-selected").each(function() {
                var selectee = $.data(this, "selectable-item");
                selectee.startselected = true;
                if (!event.metaKey && !event.ctrlKey) {
                    that._removeClass(selectee.$element, "ui-selected");
                    selectee.selected = false;
                    that._addClass(selectee.$element, "ui-unselecting");
                    selectee.unselecting = true;
                    that._trigger("unselecting", event, {
                        unselecting: selectee.element
                    });
                }
            });
            $(event.target).parents().addBack().each(function() {
                var doSelect, selectee = $.data(this, "selectable-item");
                if (selectee) {
                    doSelect = !event.metaKey && !event.ctrlKey || !selectee.$element.hasClass("ui-selected");
                    that._removeClass(selectee.$element, doSelect ? "ui-unselecting" : "ui-selected")._addClass(selectee.$element, doSelect ? "ui-selecting" : "ui-unselecting");
                    selectee.unselecting = !doSelect;
                    selectee.selecting = doSelect;
                    selectee.selected = doSelect;
                    if (doSelect) {
                        that._trigger("selecting", event, {
                            selecting: selectee.element
                        });
                    } else {
                        that._trigger("unselecting", event, {
                            unselecting: selectee.element
                        });
                    }
                    return false;
                }
            });
        },
        _mouseDrag: function(event) {
            this.dragged = true;
            if (this.options.disabled) {
                return;
            }
            var tmp, that = this, options = this.options, x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
            if (x1 > x2) {
                tmp = x2;
                x2 = x1;
                x1 = tmp;
            }
            if (y1 > y2) {
                tmp = y2;
                y2 = y1;
                y1 = tmp;
            }
            this.helper.css({
                left: x1,
                top: y1,
                width: x2 - x1,
                height: y2 - y1
            });
            this.selectees.each(function() {
                var selectee = $.data(this, "selectable-item"), hit = false, offset = {};
                if (!selectee || selectee.element === that.element[0]) {
                    return;
                }
                offset.left = selectee.left + that.elementPos.left;
                offset.right = selectee.right + that.elementPos.left;
                offset.top = selectee.top + that.elementPos.top;
                offset.bottom = selectee.bottom + that.elementPos.top;
                if (options.tolerance === "touch") {
                    hit = !(offset.left > x2 || offset.right < x1 || offset.top > y2 || offset.bottom < y1);
                } else if (options.tolerance === "fit") {
                    hit = offset.left > x1 && offset.right < x2 && offset.top > y1 && offset.bottom < y2;
                }
                if (hit) {
                    if (selectee.selected) {
                        that._removeClass(selectee.$element, "ui-selected");
                        selectee.selected = false;
                    }
                    if (selectee.unselecting) {
                        that._removeClass(selectee.$element, "ui-unselecting");
                        selectee.unselecting = false;
                    }
                    if (!selectee.selecting) {
                        that._addClass(selectee.$element, "ui-selecting");
                        selectee.selecting = true;
                        that._trigger("selecting", event, {
                            selecting: selectee.element
                        });
                    }
                } else {
                    if (selectee.selecting) {
                        if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
                            that._removeClass(selectee.$element, "ui-selecting");
                            selectee.selecting = false;
                            that._addClass(selectee.$element, "ui-selected");
                            selectee.selected = true;
                        } else {
                            that._removeClass(selectee.$element, "ui-selecting");
                            selectee.selecting = false;
                            if (selectee.startselected) {
                                that._addClass(selectee.$element, "ui-unselecting");
                                selectee.unselecting = true;
                            }
                            that._trigger("unselecting", event, {
                                unselecting: selectee.element
                            });
                        }
                    }
                    if (selectee.selected) {
                        if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
                            that._removeClass(selectee.$element, "ui-selected");
                            selectee.selected = false;
                            that._addClass(selectee.$element, "ui-unselecting");
                            selectee.unselecting = true;
                            that._trigger("unselecting", event, {
                                unselecting: selectee.element
                            });
                        }
                    }
                }
            });
            return false;
        },
        _mouseStop: function(event) {
            var that = this;
            this.dragged = false;
            $(".ui-unselecting", this.element[0]).each(function() {
                var selectee = $.data(this, "selectable-item");
                that._removeClass(selectee.$element, "ui-unselecting");
                selectee.unselecting = false;
                selectee.startselected = false;
                that._trigger("unselected", event, {
                    unselected: selectee.element
                });
            });
            $(".ui-selecting", this.element[0]).each(function() {
                var selectee = $.data(this, "selectable-item");
                that._removeClass(selectee.$element, "ui-selecting")._addClass(selectee.$element, "ui-selected");
                selectee.selecting = false;
                selectee.selected = true;
                selectee.startselected = true;
                that._trigger("selected", event, {
                    selected: selectee.element
                });
            });
            this._trigger("stop", event);
            this.helper.remove();
            return false;
        }
    });
    var widgetsSelectmenu = $.widget("ui.selectmenu", [ $.ui.formResetMixin, {
        version: "1.13.1",
        defaultElement: "<select>",
        options: {
            appendTo: null,
            classes: {
                "ui-selectmenu-button-open": "ui-corner-top",
                "ui-selectmenu-button-closed": "ui-corner-all"
            },
            disabled: null,
            icons: {
                button: "ui-icon-triangle-1-s"
            },
            position: {
                my: "left top",
                at: "left bottom",
                collision: "none"
            },
            width: false,
            change: null,
            close: null,
            focus: null,
            open: null,
            select: null
        },
        _create: function() {
            var selectmenuId = this.element.uniqueId().attr("id");
            this.ids = {
                element: selectmenuId,
                button: selectmenuId + "-button",
                menu: selectmenuId + "-menu"
            };
            this._drawButton();
            this._drawMenu();
            this._bindFormResetHandler();
            this._rendered = false;
            this.menuItems = $();
        },
        _drawButton: function() {
            var icon, that = this, item = this._parseOption(this.element.find("option:selected"), this.element[0].selectedIndex);
            this.labels = this.element.labels().attr("for", this.ids.button);
            this._on(this.labels, {
                click: function(event) {
                    this.button.trigger("focus");
                    event.preventDefault();
                }
            });
            this.element.hide();
            this.button = $("<span>", {
                tabindex: this.options.disabled ? -1 : 0,
                id: this.ids.button,
                role: "combobox",
                "aria-expanded": "false",
                "aria-autocomplete": "list",
                "aria-owns": this.ids.menu,
                "aria-haspopup": "true",
                title: this.element.attr("title")
            }).insertAfter(this.element);
            this._addClass(this.button, "ui-selectmenu-button ui-selectmenu-button-closed", "ui-button ui-widget");
            icon = $("<span>").appendTo(this.button);
            this._addClass(icon, "ui-selectmenu-icon", "ui-icon " + this.options.icons.button);
            this.buttonItem = this._renderButtonItem(item).appendTo(this.button);
            if (this.options.width !== false) {
                this._resizeButton();
            }
            this._on(this.button, this._buttonEvents);
            this.button.one("focusin", function() {
                if (!that._rendered) {
                    that._refreshMenu();
                }
            });
        },
        _drawMenu: function() {
            var that = this;
            this.menu = $("<ul>", {
                "aria-hidden": "true",
                "aria-labelledby": this.ids.button,
                id: this.ids.menu
            });
            this.menuWrap = $("<div>").append(this.menu);
            this._addClass(this.menuWrap, "ui-selectmenu-menu", "ui-front");
            this.menuWrap.appendTo(this._appendTo());
            this.menuInstance = this.menu.menu({
                classes: {
                    "ui-menu": "ui-corner-bottom"
                },
                role: "listbox",
                select: function(event, ui) {
                    event.preventDefault();
                    that._setSelection();
                    that._select(ui.item.data("ui-selectmenu-item"), event);
                },
                focus: function(event, ui) {
                    var item = ui.item.data("ui-selectmenu-item");
                    if (that.focusIndex != null && item.index !== that.focusIndex) {
                        that._trigger("focus", event, {
                            item: item
                        });
                        if (!that.isOpen) {
                            that._select(item, event);
                        }
                    }
                    that.focusIndex = item.index;
                    that.button.attr("aria-activedescendant", that.menuItems.eq(item.index).attr("id"));
                }
            }).menu("instance");
            this.menuInstance._off(this.menu, "mouseleave");
            this.menuInstance._closeOnDocumentClick = function() {
                return false;
            };
            this.menuInstance._isDivider = function() {
                return false;
            };
        },
        refresh: function() {
            this._refreshMenu();
            this.buttonItem.replaceWith(this.buttonItem = this._renderButtonItem(this._getSelectedItem().data("ui-selectmenu-item") || {}));
            if (this.options.width === null) {
                this._resizeButton();
            }
        },
        _refreshMenu: function() {
            var item, options = this.element.find("option");
            this.menu.empty();
            this._parseOptions(options);
            this._renderMenu(this.menu, this.items);
            this.menuInstance.refresh();
            this.menuItems = this.menu.find("li").not(".ui-selectmenu-optgroup").find(".ui-menu-item-wrapper");
            this._rendered = true;
            if (!options.length) {
                return;
            }
            item = this._getSelectedItem();
            this.menuInstance.focus(null, item);
            this._setAria(item.data("ui-selectmenu-item"));
            this._setOption("disabled", this.element.prop("disabled"));
        },
        open: function(event) {
            if (this.options.disabled) {
                return;
            }
            if (!this._rendered) {
                this._refreshMenu();
            } else {
                this._removeClass(this.menu.find(".ui-state-active"), null, "ui-state-active");
                this.menuInstance.focus(null, this._getSelectedItem());
            }
            if (!this.menuItems.length) {
                return;
            }
            this.isOpen = true;
            this._toggleAttr();
            this._resizeMenu();
            this._position();
            this._on(this.document, this._documentClick);
            this._trigger("open", event);
        },
        _position: function() {
            this.menuWrap.position($.extend({
                of: this.button
            }, this.options.position));
        },
        close: function(event) {
            if (!this.isOpen) {
                return;
            }
            this.isOpen = false;
            this._toggleAttr();
            this.range = null;
            this._off(this.document);
            this._trigger("close", event);
        },
        widget: function() {
            return this.button;
        },
        menuWidget: function() {
            return this.menu;
        },
        _renderButtonItem: function(item) {
            var buttonItem = $("<span>");
            this._setText(buttonItem, item.label);
            this._addClass(buttonItem, "ui-selectmenu-text");
            return buttonItem;
        },
        _renderMenu: function(ul, items) {
            var that = this, currentOptgroup = "";
            $.each(items, function(index, item) {
                var li;
                if (item.optgroup !== currentOptgroup) {
                    li = $("<li>", {
                        text: item.optgroup
                    });
                    that._addClass(li, "ui-selectmenu-optgroup", "ui-menu-divider" + (item.element.parent("optgroup").prop("disabled") ? " ui-state-disabled" : ""));
                    li.appendTo(ul);
                    currentOptgroup = item.optgroup;
                }
                that._renderItemData(ul, item);
            });
        },
        _renderItemData: function(ul, item) {
            return this._renderItem(ul, item).data("ui-selectmenu-item", item);
        },
        _renderItem: function(ul, item) {
            var li = $("<li>"), wrapper = $("<div>", {
                title: item.element.attr("title")
            });
            if (item.disabled) {
                this._addClass(li, null, "ui-state-disabled");
            }
            this._setText(wrapper, item.label);
            return li.append(wrapper).appendTo(ul);
        },
        _setText: function(element, value) {
            if (value) {
                element.text(value);
            } else {
                element.html("&#160;");
            }
        },
        _move: function(direction, event) {
            var item, next, filter = ".ui-menu-item";
            if (this.isOpen) {
                item = this.menuItems.eq(this.focusIndex).parent("li");
            } else {
                item = this.menuItems.eq(this.element[0].selectedIndex).parent("li");
                filter += ":not(.ui-state-disabled)";
            }
            if (direction === "first" || direction === "last") {
                next = item[direction === "first" ? "prevAll" : "nextAll"](filter).eq(-1);
            } else {
                next = item[direction + "All"](filter).eq(0);
            }
            if (next.length) {
                this.menuInstance.focus(event, next);
            }
        },
        _getSelectedItem: function() {
            return this.menuItems.eq(this.element[0].selectedIndex).parent("li");
        },
        _toggle: function(event) {
            this[this.isOpen ? "close" : "open"](event);
        },
        _setSelection: function() {
            var selection;
            if (!this.range) {
                return;
            }
            if (window.getSelection) {
                selection = window.getSelection();
                selection.removeAllRanges();
                selection.addRange(this.range);
            } else {
                this.range.select();
            }
            this.button.focus();
        },
        _documentClick: {
            mousedown: function(event) {
                if (!this.isOpen) {
                    return;
                }
                if (!$(event.target).closest(".ui-selectmenu-menu, #" + $.escapeSelector(this.ids.button)).length) {
                    this.close(event);
                }
            }
        },
        _buttonEvents: {
            mousedown: function() {
                var selection;
                if (window.getSelection) {
                    selection = window.getSelection();
                    if (selection.rangeCount) {
                        this.range = selection.getRangeAt(0);
                    }
                } else {
                    this.range = document.selection.createRange();
                }
            },
            click: function(event) {
                this._setSelection();
                this._toggle(event);
            },
            keydown: function(event) {
                var preventDefault = true;
                switch (event.keyCode) {
                  case $.ui.keyCode.TAB:
                  case $.ui.keyCode.ESCAPE:
                    this.close(event);
                    preventDefault = false;
                    break;

                  case $.ui.keyCode.ENTER:
                    if (this.isOpen) {
                        this._selectFocusedItem(event);
                    }
                    break;

                  case $.ui.keyCode.UP:
                    if (event.altKey) {
                        this._toggle(event);
                    } else {
                        this._move("prev", event);
                    }
                    break;

                  case $.ui.keyCode.DOWN:
                    if (event.altKey) {
                        this._toggle(event);
                    } else {
                        this._move("next", event);
                    }
                    break;

                  case $.ui.keyCode.SPACE:
                    if (this.isOpen) {
                        this._selectFocusedItem(event);
                    } else {
                        this._toggle(event);
                    }
                    break;

                  case $.ui.keyCode.LEFT:
                    this._move("prev", event);
                    break;

                  case $.ui.keyCode.RIGHT:
                    this._move("next", event);
                    break;

                  case $.ui.keyCode.HOME:
                  case $.ui.keyCode.PAGE_UP:
                    this._move("first", event);
                    break;

                  case $.ui.keyCode.END:
                  case $.ui.keyCode.PAGE_DOWN:
                    this._move("last", event);
                    break;

                  default:
                    this.menu.trigger(event);
                    preventDefault = false;
                }
                if (preventDefault) {
                    event.preventDefault();
                }
            }
        },
        _selectFocusedItem: function(event) {
            var item = this.menuItems.eq(this.focusIndex).parent("li");
            if (!item.hasClass("ui-state-disabled")) {
                this._select(item.data("ui-selectmenu-item"), event);
            }
        },
        _select: function(item, event) {
            var oldIndex = this.element[0].selectedIndex;
            this.element[0].selectedIndex = item.index;
            this.buttonItem.replaceWith(this.buttonItem = this._renderButtonItem(item));
            this._setAria(item);
            this._trigger("select", event, {
                item: item
            });
            if (item.index !== oldIndex) {
                this._trigger("change", event, {
                    item: item
                });
            }
            this.close(event);
        },
        _setAria: function(item) {
            var id = this.menuItems.eq(item.index).attr("id");
            this.button.attr({
                "aria-labelledby": id,
                "aria-activedescendant": id
            });
            this.menu.attr("aria-activedescendant", id);
        },
        _setOption: function(key, value) {
            if (key === "icons") {
                var icon = this.button.find("span.ui-icon");
                this._removeClass(icon, null, this.options.icons.button)._addClass(icon, null, value.button);
            }
            this._super(key, value);
            if (key === "appendTo") {
                this.menuWrap.appendTo(this._appendTo());
            }
            if (key === "width") {
                this._resizeButton();
            }
        },
        _setOptionDisabled: function(value) {
            this._super(value);
            this.menuInstance.option("disabled", value);
            this.button.attr("aria-disabled", value);
            this._toggleClass(this.button, null, "ui-state-disabled", value);
            this.element.prop("disabled", value);
            if (value) {
                this.button.attr("tabindex", -1);
                this.close();
            } else {
                this.button.attr("tabindex", 0);
            }
        },
        _appendTo: function() {
            var element = this.options.appendTo;
            if (element) {
                element = element.jquery || element.nodeType ? $(element) : this.document.find(element).eq(0);
            }
            if (!element || !element[0]) {
                element = this.element.closest(".ui-front, dialog");
            }
            if (!element.length) {
                element = this.document[0].body;
            }
            return element;
        },
        _toggleAttr: function() {
            this.button.attr("aria-expanded", this.isOpen);
            this._removeClass(this.button, "ui-selectmenu-button-" + (this.isOpen ? "closed" : "open"))._addClass(this.button, "ui-selectmenu-button-" + (this.isOpen ? "open" : "closed"))._toggleClass(this.menuWrap, "ui-selectmenu-open", null, this.isOpen);
            this.menu.attr("aria-hidden", !this.isOpen);
        },
        _resizeButton: function() {
            var width = this.options.width;
            if (width === false) {
                this.button.css("width", "");
                return;
            }
            if (width === null) {
                width = this.element.show().outerWidth();
                this.element.hide();
            }
            this.button.outerWidth(width);
        },
        _resizeMenu: function() {
            this.menu.outerWidth(Math.max(this.button.outerWidth(), this.menu.width("").outerWidth() + 1));
        },
        _getCreateOptions: function() {
            var options = this._super();
            options.disabled = this.element.prop("disabled");
            return options;
        },
        _parseOptions: function(options) {
            var that = this, data = [];
            options.each(function(index, item) {
                if (item.hidden) {
                    return;
                }
                data.push(that._parseOption($(item), index));
            });
            this.items = data;
        },
        _parseOption: function(option, index) {
            var optgroup = option.parent("optgroup");
            return {
                element: option,
                index: index,
                value: option.val(),
                label: option.text(),
                optgroup: optgroup.attr("label") || "",
                disabled: optgroup.prop("disabled") || option.prop("disabled")
            };
        },
        _destroy: function() {
            this._unbindFormResetHandler();
            this.menuWrap.remove();
            this.button.remove();
            this.element.show();
            this.element.removeUniqueId();
            this.labels.attr("for", this.ids.element);
        }
    } ]);
    var widgetsSlider = $.widget("ui.slider", $.ui.mouse, {
        version: "1.13.1",
        widgetEventPrefix: "slide",
        options: {
            animate: false,
            classes: {
                "ui-slider": "ui-corner-all",
                "ui-slider-handle": "ui-corner-all",
                "ui-slider-range": "ui-corner-all ui-widget-header"
            },
            distance: 0,
            max: 100,
            min: 0,
            orientation: "horizontal",
            range: false,
            step: 1,
            value: 0,
            values: null,
            change: null,
            slide: null,
            start: null,
            stop: null
        },
        numPages: 5,
        _create: function() {
            this._keySliding = false;
            this._mouseSliding = false;
            this._animateOff = true;
            this._handleIndex = null;
            this._detectOrientation();
            this._mouseInit();
            this._calculateNewMax();
            this._addClass("ui-slider ui-slider-" + this.orientation, "ui-widget ui-widget-content");
            this._refresh();
            this._animateOff = false;
        },
        _refresh: function() {
            this._createRange();
            this._createHandles();
            this._setupEvents();
            this._refreshValue();
        },
        _createHandles: function() {
            var i, handleCount, options = this.options, existingHandles = this.element.find(".ui-slider-handle"), handle = "<span tabindex='0'></span>", handles = [];
            handleCount = options.values && options.values.length || 1;
            if (existingHandles.length > handleCount) {
                existingHandles.slice(handleCount).remove();
                existingHandles = existingHandles.slice(0, handleCount);
            }
            for (i = existingHandles.length; i < handleCount; i++) {
                handles.push(handle);
            }
            this.handles = existingHandles.add($(handles.join("")).appendTo(this.element));
            this._addClass(this.handles, "ui-slider-handle", "ui-state-default");
            this.handle = this.handles.eq(0);
            this.handles.each(function(i) {
                $(this).data("ui-slider-handle-index", i).attr("tabIndex", 0);
            });
        },
        _createRange: function() {
            var options = this.options;
            if (options.range) {
                if (options.range === true) {
                    if (!options.values) {
                        options.values = [ this._valueMin(), this._valueMin() ];
                    } else if (options.values.length && options.values.length !== 2) {
                        options.values = [ options.values[0], options.values[0] ];
                    } else if (Array.isArray(options.values)) {
                        options.values = options.values.slice(0);
                    }
                }
                if (!this.range || !this.range.length) {
                    this.range = $("<div>").appendTo(this.element);
                    this._addClass(this.range, "ui-slider-range");
                } else {
                    this._removeClass(this.range, "ui-slider-range-min ui-slider-range-max");
                    this.range.css({
                        left: "",
                        bottom: ""
                    });
                }
                if (options.range === "min" || options.range === "max") {
                    this._addClass(this.range, "ui-slider-range-" + options.range);
                }
            } else {
                if (this.range) {
                    this.range.remove();
                }
                this.range = null;
            }
        },
        _setupEvents: function() {
            this._off(this.handles);
            this._on(this.handles, this._handleEvents);
            this._hoverable(this.handles);
            this._focusable(this.handles);
        },
        _destroy: function() {
            this.handles.remove();
            if (this.range) {
                this.range.remove();
            }
            this._mouseDestroy();
        },
        _mouseCapture: function(event) {
            var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle, that = this, o = this.options;
            if (o.disabled) {
                return false;
            }
            this.elementSize = {
                width: this.element.outerWidth(),
                height: this.element.outerHeight()
            };
            this.elementOffset = this.element.offset();
            position = {
                x: event.pageX,
                y: event.pageY
            };
            normValue = this._normValueFromMouse(position);
            distance = this._valueMax() - this._valueMin() + 1;
            this.handles.each(function(i) {
                var thisDistance = Math.abs(normValue - that.values(i));
                if (distance > thisDistance || distance === thisDistance && (i === that._lastChangedValue || that.values(i) === o.min)) {
                    distance = thisDistance;
                    closestHandle = $(this);
                    index = i;
                }
            });
            allowed = this._start(event, index);
            if (allowed === false) {
                return false;
            }
            this._mouseSliding = true;
            this._handleIndex = index;
            this._addClass(closestHandle, null, "ui-state-active");
            closestHandle.trigger("focus");
            offset = closestHandle.offset();
            mouseOverHandle = !$(event.target).parents().addBack().is(".ui-slider-handle");
            this._clickOffset = mouseOverHandle ? {
                left: 0,
                top: 0
            } : {
                left: event.pageX - offset.left - closestHandle.width() / 2,
                top: event.pageY - offset.top - closestHandle.height() / 2 - (parseInt(closestHandle.css("borderTopWidth"), 10) || 0) - (parseInt(closestHandle.css("borderBottomWidth"), 10) || 0) + (parseInt(closestHandle.css("marginTop"), 10) || 0)
            };
            if (!this.handles.hasClass("ui-state-hover")) {
                this._slide(event, index, normValue);
            }
            this._animateOff = true;
            return true;
        },
        _mouseStart: function() {
            return true;
        },
        _mouseDrag: function(event) {
            var position = {
                x: event.pageX,
                y: event.pageY
            }, normValue = this._normValueFromMouse(position);
            this._slide(event, this._handleIndex, normValue);
            return false;
        },
        _mouseStop: function(event) {
            this._removeClass(this.handles, null, "ui-state-active");
            this._mouseSliding = false;
            this._stop(event, this._handleIndex);
            this._change(event, this._handleIndex);
            this._handleIndex = null;
            this._clickOffset = null;
            this._animateOff = false;
            return false;
        },
        _detectOrientation: function() {
            this.orientation = this.options.orientation === "vertical" ? "vertical" : "horizontal";
        },
        _normValueFromMouse: function(position) {
            var pixelTotal, pixelMouse, percentMouse, valueTotal, valueMouse;
            if (this.orientation === "horizontal") {
                pixelTotal = this.elementSize.width;
                pixelMouse = position.x - this.elementOffset.left - (this._clickOffset ? this._clickOffset.left : 0);
            } else {
                pixelTotal = this.elementSize.height;
                pixelMouse = position.y - this.elementOffset.top - (this._clickOffset ? this._clickOffset.top : 0);
            }
            percentMouse = pixelMouse / pixelTotal;
            if (percentMouse > 1) {
                percentMouse = 1;
            }
            if (percentMouse < 0) {
                percentMouse = 0;
            }
            if (this.orientation === "vertical") {
                percentMouse = 1 - percentMouse;
            }
            valueTotal = this._valueMax() - this._valueMin();
            valueMouse = this._valueMin() + percentMouse * valueTotal;
            return this._trimAlignValue(valueMouse);
        },
        _uiHash: function(index, value, values) {
            var uiHash = {
                handle: this.handles[index],
                handleIndex: index,
                value: value !== undefined ? value : this.value()
            };
            if (this._hasMultipleValues()) {
                uiHash.value = value !== undefined ? value : this.values(index);
                uiHash.values = values || this.values();
            }
            return uiHash;
        },
        _hasMultipleValues: function() {
            return this.options.values && this.options.values.length;
        },
        _start: function(event, index) {
            return this._trigger("start", event, this._uiHash(index));
        },
        _slide: function(event, index, newVal) {
            var allowed, otherVal, currentValue = this.value(), newValues = this.values();
            if (this._hasMultipleValues()) {
                otherVal = this.values(index ? 0 : 1);
                currentValue = this.values(index);
                if (this.options.values.length === 2 && this.options.range === true) {
                    newVal = index === 0 ? Math.min(otherVal, newVal) : Math.max(otherVal, newVal);
                }
                newValues[index] = newVal;
            }
            if (newVal === currentValue) {
                return;
            }
            allowed = this._trigger("slide", event, this._uiHash(index, newVal, newValues));
            if (allowed === false) {
                return;
            }
            if (this._hasMultipleValues()) {
                this.values(index, newVal);
            } else {
                this.value(newVal);
            }
        },
        _stop: function(event, index) {
            this._trigger("stop", event, this._uiHash(index));
        },
        _change: function(event, index) {
            if (!this._keySliding && !this._mouseSliding) {
                this._lastChangedValue = index;
                this._trigger("change", event, this._uiHash(index));
            }
        },
        value: function(newValue) {
            if (arguments.length) {
                this.options.value = this._trimAlignValue(newValue);
                this._refreshValue();
                this._change(null, 0);
                return;
            }
            return this._value();
        },
        values: function(index, newValue) {
            var vals, newValues, i;
            if (arguments.length > 1) {
                this.options.values[index] = this._trimAlignValue(newValue);
                this._refreshValue();
                this._change(null, index);
                return;
            }
            if (arguments.length) {
                if (Array.isArray(arguments[0])) {
                    vals = this.options.values;
                    newValues = arguments[0];
                    for (i = 0; i < vals.length; i += 1) {
                        vals[i] = this._trimAlignValue(newValues[i]);
                        this._change(null, i);
                    }
                    this._refreshValue();
                } else {
                    if (this._hasMultipleValues()) {
                        return this._values(index);
                    } else {
                        return this.value();
                    }
                }
            } else {
                return this._values();
            }
        },
        _setOption: function(key, value) {
            var i, valsLength = 0;
            if (key === "range" && this.options.range === true) {
                if (value === "min") {
                    this.options.value = this._values(0);
                    this.options.values = null;
                } else if (value === "max") {
                    this.options.value = this._values(this.options.values.length - 1);
                    this.options.values = null;
                }
            }
            if (Array.isArray(this.options.values)) {
                valsLength = this.options.values.length;
            }
            this._super(key, value);
            switch (key) {
              case "orientation":
                this._detectOrientation();
                this._removeClass("ui-slider-horizontal ui-slider-vertical")._addClass("ui-slider-" + this.orientation);
                this._refreshValue();
                if (this.options.range) {
                    this._refreshRange(value);
                }
                this.handles.css(value === "horizontal" ? "bottom" : "left", "");
                break;

              case "value":
                this._animateOff = true;
                this._refreshValue();
                this._change(null, 0);
                this._animateOff = false;
                break;

              case "values":
                this._animateOff = true;
                this._refreshValue();
                for (i = valsLength - 1; i >= 0; i--) {
                    this._change(null, i);
                }
                this._animateOff = false;
                break;

              case "step":
              case "min":
              case "max":
                this._animateOff = true;
                this._calculateNewMax();
                this._refreshValue();
                this._animateOff = false;
                break;

              case "range":
                this._animateOff = true;
                this._refresh();
                this._animateOff = false;
                break;
            }
        },
        _setOptionDisabled: function(value) {
            this._super(value);
            this._toggleClass(null, "ui-state-disabled", !!value);
        },
        _value: function() {
            var val = this.options.value;
            val = this._trimAlignValue(val);
            return val;
        },
        _values: function(index) {
            var val, vals, i;
            if (arguments.length) {
                val = this.options.values[index];
                val = this._trimAlignValue(val);
                return val;
            } else if (this._hasMultipleValues()) {
                vals = this.options.values.slice();
                for (i = 0; i < vals.length; i += 1) {
                    vals[i] = this._trimAlignValue(vals[i]);
                }
                return vals;
            } else {
                return [];
            }
        },
        _trimAlignValue: function(val) {
            if (val <= this._valueMin()) {
                return this._valueMin();
            }
            if (val >= this._valueMax()) {
                return this._valueMax();
            }
            var step = this.options.step > 0 ? this.options.step : 1, valModStep = (val - this._valueMin()) % step, alignValue = val - valModStep;
            if (Math.abs(valModStep) * 2 >= step) {
                alignValue += valModStep > 0 ? step : -step;
            }
            return parseFloat(alignValue.toFixed(5));
        },
        _calculateNewMax: function() {
            var max = this.options.max, min = this._valueMin(), step = this.options.step, aboveMin = Math.round((max - min) / step) * step;
            max = aboveMin + min;
            if (max > this.options.max) {
                max -= step;
            }
            this.max = parseFloat(max.toFixed(this._precision()));
        },
        _precision: function() {
            var precision = this._precisionOf(this.options.step);
            if (this.options.min !== null) {
                precision = Math.max(precision, this._precisionOf(this.options.min));
            }
            return precision;
        },
        _precisionOf: function(num) {
            var str = num.toString(), decimal = str.indexOf(".");
            return decimal === -1 ? 0 : str.length - decimal - 1;
        },
        _valueMin: function() {
            return this.options.min;
        },
        _valueMax: function() {
            return this.max;
        },
        _refreshRange: function(orientation) {
            if (orientation === "vertical") {
                this.range.css({
                    width: "",
                    left: ""
                });
            }
            if (orientation === "horizontal") {
                this.range.css({
                    height: "",
                    bottom: ""
                });
            }
        },
        _refreshValue: function() {
            var lastValPercent, valPercent, value, valueMin, valueMax, oRange = this.options.range, o = this.options, that = this, animate = !this._animateOff ? o.animate : false, _set = {};
            if (this._hasMultipleValues()) {
                this.handles.each(function(i) {
                    valPercent = (that.values(i) - that._valueMin()) / (that._valueMax() - that._valueMin()) * 100;
                    _set[that.orientation === "horizontal" ? "left" : "bottom"] = valPercent + "%";
                    $(this).stop(1, 1)[animate ? "animate" : "css"](_set, o.animate);
                    if (that.options.range === true) {
                        if (that.orientation === "horizontal") {
                            if (i === 0) {
                                that.range.stop(1, 1)[animate ? "animate" : "css"]({
                                    left: valPercent + "%"
                                }, o.animate);
                            }
                            if (i === 1) {
                                that.range[animate ? "animate" : "css"]({
                                    width: valPercent - lastValPercent + "%"
                                }, {
                                    queue: false,
                                    duration: o.animate
                                });
                            }
                        } else {
                            if (i === 0) {
                                that.range.stop(1, 1)[animate ? "animate" : "css"]({
                                    bottom: valPercent + "%"
                                }, o.animate);
                            }
                            if (i === 1) {
                                that.range[animate ? "animate" : "css"]({
                                    height: valPercent - lastValPercent + "%"
                                }, {
                                    queue: false,
                                    duration: o.animate
                                });
                            }
                        }
                    }
                    lastValPercent = valPercent;
                });
            } else {
                value = this.value();
                valueMin = this._valueMin();
                valueMax = this._valueMax();
                valPercent = valueMax !== valueMin ? (value - valueMin) / (valueMax - valueMin) * 100 : 0;
                _set[this.orientation === "horizontal" ? "left" : "bottom"] = valPercent + "%";
                this.handle.stop(1, 1)[animate ? "animate" : "css"](_set, o.animate);
                if (oRange === "min" && this.orientation === "horizontal") {
                    this.range.stop(1, 1)[animate ? "animate" : "css"]({
                        width: valPercent + "%"
                    }, o.animate);
                }
                if (oRange === "max" && this.orientation === "horizontal") {
                    this.range.stop(1, 1)[animate ? "animate" : "css"]({
                        width: 100 - valPercent + "%"
                    }, o.animate);
                }
                if (oRange === "min" && this.orientation === "vertical") {
                    this.range.stop(1, 1)[animate ? "animate" : "css"]({
                        height: valPercent + "%"
                    }, o.animate);
                }
                if (oRange === "max" && this.orientation === "vertical") {
                    this.range.stop(1, 1)[animate ? "animate" : "css"]({
                        height: 100 - valPercent + "%"
                    }, o.animate);
                }
            }
        },
        _handleEvents: {
            keydown: function(event) {
                var allowed, curVal, newVal, step, index = $(event.target).data("ui-slider-handle-index");
                switch (event.keyCode) {
                  case $.ui.keyCode.HOME:
                  case $.ui.keyCode.END:
                  case $.ui.keyCode.PAGE_UP:
                  case $.ui.keyCode.PAGE_DOWN:
                  case $.ui.keyCode.UP:
                  case $.ui.keyCode.RIGHT:
                  case $.ui.keyCode.DOWN:
                  case $.ui.keyCode.LEFT:
                    event.preventDefault();
                    if (!this._keySliding) {
                        this._keySliding = true;
                        this._addClass($(event.target), null, "ui-state-active");
                        allowed = this._start(event, index);
                        if (allowed === false) {
                            return;
                        }
                    }
                    break;
                }
                step = this.options.step;
                if (this._hasMultipleValues()) {
                    curVal = newVal = this.values(index);
                } else {
                    curVal = newVal = this.value();
                }
                switch (event.keyCode) {
                  case $.ui.keyCode.HOME:
                    newVal = this._valueMin();
                    break;

                  case $.ui.keyCode.END:
                    newVal = this._valueMax();
                    break;

                  case $.ui.keyCode.PAGE_UP:
                    newVal = this._trimAlignValue(curVal + (this._valueMax() - this._valueMin()) / this.numPages);
                    break;

                  case $.ui.keyCode.PAGE_DOWN:
                    newVal = this._trimAlignValue(curVal - (this._valueMax() - this._valueMin()) / this.numPages);
                    break;

                  case $.ui.keyCode.UP:
                  case $.ui.keyCode.RIGHT:
                    if (curVal === this._valueMax()) {
                        return;
                    }
                    newVal = this._trimAlignValue(curVal + step);
                    break;

                  case $.ui.keyCode.DOWN:
                  case $.ui.keyCode.LEFT:
                    if (curVal === this._valueMin()) {
                        return;
                    }
                    newVal = this._trimAlignValue(curVal - step);
                    break;
                }
                this._slide(event, index, newVal);
            },
            keyup: function(event) {
                var index = $(event.target).data("ui-slider-handle-index");
                if (this._keySliding) {
                    this._keySliding = false;
                    this._stop(event, index);
                    this._change(event, index);
                    this._removeClass($(event.target), null, "ui-state-active");
                }
            }
        }
    });
    var widgetsSortable = $.widget("ui.sortable", $.ui.mouse, {
        version: "1.13.1",
        widgetEventPrefix: "sort",
        ready: false,
        options: {
            appendTo: "parent",
            axis: false,
            connectWith: false,
            containment: false,
            cursor: "auto",
            cursorAt: false,
            dropOnEmpty: true,
            forcePlaceholderSize: false,
            forceHelperSize: false,
            grid: false,
            handle: false,
            helper: "original",
            items: "> *",
            opacity: false,
            placeholder: false,
            revert: false,
            scroll: true,
            scrollSensitivity: 20,
            scrollSpeed: 20,
            scope: "default",
            tolerance: "intersect",
            zIndex: 1e3,
            activate: null,
            beforeStop: null,
            change: null,
            deactivate: null,
            out: null,
            over: null,
            receive: null,
            remove: null,
            sort: null,
            start: null,
            stop: null,
            update: null
        },
        _isOverAxis: function(x, reference, size) {
            return x >= reference && x < reference + size;
        },
        _isFloating: function(item) {
            return /left|right/.test(item.css("float")) || /inline|table-cell/.test(item.css("display"));
        },
        _create: function() {
            this.containerCache = {};
            this._addClass("ui-sortable");
            this.refresh();
            this.offset = this.element.offset();
            this._mouseInit();
            this._setHandleClassName();
            this.ready = true;
        },
        _setOption: function(key, value) {
            this._super(key, value);
            if (key === "handle") {
                this._setHandleClassName();
            }
        },
        _setHandleClassName: function() {
            var that = this;
            this._removeClass(this.element.find(".ui-sortable-handle"), "ui-sortable-handle");
            $.each(this.items, function() {
                that._addClass(this.instance.options.handle ? this.item.find(this.instance.options.handle) : this.item, "ui-sortable-handle");
            });
        },
        _destroy: function() {
            this._mouseDestroy();
            for (var i = this.items.length - 1; i >= 0; i--) {
                this.items[i].item.removeData(this.widgetName + "-item");
            }
            return this;
        },
        _mouseCapture: function(event, overrideHandle) {
            var currentItem = null, validHandle = false, that = this;
            if (this.reverting) {
                return false;
            }
            if (this.options.disabled || this.options.type === "static") {
                return false;
            }
            this._refreshItems(event);
            $(event.target).parents().each(function() {
                if ($.data(this, that.widgetName + "-item") === that) {
                    currentItem = $(this);
                    return false;
                }
            });
            if ($.data(event.target, that.widgetName + "-item") === that) {
                currentItem = $(event.target);
            }
            if (!currentItem) {
                return false;
            }
            if (this.options.handle && !overrideHandle) {
                $(this.options.handle, currentItem).find("*").addBack().each(function() {
                    if (this === event.target) {
                        validHandle = true;
                    }
                });
                if (!validHandle) {
                    return false;
                }
            }
            this.currentItem = currentItem;
            this._removeCurrentsFromItems();
            return true;
        },
        _mouseStart: function(event, overrideHandle, noActivation) {
            var i, body, o = this.options;
            this.currentContainer = this;
            this.refreshPositions();
            this.appendTo = $(o.appendTo !== "parent" ? o.appendTo : this.currentItem.parent());
            this.helper = this._createHelper(event);
            this._cacheHelperProportions();
            this._cacheMargins();
            this.offset = this.currentItem.offset();
            this.offset = {
                top: this.offset.top - this.margins.top,
                left: this.offset.left - this.margins.left
            };
            $.extend(this.offset, {
                click: {
                    left: event.pageX - this.offset.left,
                    top: event.pageY - this.offset.top
                },
                relative: this._getRelativeOffset()
            });
            this.helper.css("position", "absolute");
            this.cssPosition = this.helper.css("position");
            if (o.cursorAt) {
                this._adjustOffsetFromHelper(o.cursorAt);
            }
            this.domPosition = {
                prev: this.currentItem.prev()[0],
                parent: this.currentItem.parent()[0]
            };
            if (this.helper[0] !== this.currentItem[0]) {
                this.currentItem.hide();
            }
            this._createPlaceholder();
            this.scrollParent = this.placeholder.scrollParent();
            $.extend(this.offset, {
                parent: this._getParentOffset()
            });
            if (o.containment) {
                this._setContainment();
            }
            if (o.cursor && o.cursor !== "auto") {
                body = this.document.find("body");
                this.storedCursor = body.css("cursor");
                body.css("cursor", o.cursor);
                this.storedStylesheet = $("<style>*{ cursor: " + o.cursor + " !important; }</style>").appendTo(body);
            }
            if (o.zIndex) {
                if (this.helper.css("zIndex")) {
                    this._storedZIndex = this.helper.css("zIndex");
                }
                this.helper.css("zIndex", o.zIndex);
            }
            if (o.opacity) {
                if (this.helper.css("opacity")) {
                    this._storedOpacity = this.helper.css("opacity");
                }
                this.helper.css("opacity", o.opacity);
            }
            if (this.scrollParent[0] !== this.document[0] && this.scrollParent[0].tagName !== "HTML") {
                this.overflowOffset = this.scrollParent.offset();
            }
            this._trigger("start", event, this._uiHash());
            if (!this._preserveHelperProportions) {
                this._cacheHelperProportions();
            }
            if (!noActivation) {
                for (i = this.containers.length - 1; i >= 0; i--) {
                    this.containers[i]._trigger("activate", event, this._uiHash(this));
                }
            }
            if ($.ui.ddmanager) {
                $.ui.ddmanager.current = this;
            }
            if ($.ui.ddmanager && !o.dropBehaviour) {
                $.ui.ddmanager.prepareOffsets(this, event);
            }
            this.dragging = true;
            this._addClass(this.helper, "ui-sortable-helper");
            if (!this.helper.parent().is(this.appendTo)) {
                this.helper.detach().appendTo(this.appendTo);
                this.offset.parent = this._getParentOffset();
            }
            this.position = this.originalPosition = this._generatePosition(event);
            this.originalPageX = event.pageX;
            this.originalPageY = event.pageY;
            this.lastPositionAbs = this.positionAbs = this._convertPositionTo("absolute");
            this._mouseDrag(event);
            return true;
        },
        _scroll: function(event) {
            var o = this.options, scrolled = false;
            if (this.scrollParent[0] !== this.document[0] && this.scrollParent[0].tagName !== "HTML") {
                if (this.overflowOffset.top + this.scrollParent[0].offsetHeight - event.pageY < o.scrollSensitivity) {
                    this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
                } else if (event.pageY - this.overflowOffset.top < o.scrollSensitivity) {
                    this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
                }
                if (this.overflowOffset.left + this.scrollParent[0].offsetWidth - event.pageX < o.scrollSensitivity) {
                    this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
                } else if (event.pageX - this.overflowOffset.left < o.scrollSensitivity) {
                    this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
                }
            } else {
                if (event.pageY - this.document.scrollTop() < o.scrollSensitivity) {
                    scrolled = this.document.scrollTop(this.document.scrollTop() - o.scrollSpeed);
                } else if (this.window.height() - (event.pageY - this.document.scrollTop()) < o.scrollSensitivity) {
                    scrolled = this.document.scrollTop(this.document.scrollTop() + o.scrollSpeed);
                }
                if (event.pageX - this.document.scrollLeft() < o.scrollSensitivity) {
                    scrolled = this.document.scrollLeft(this.document.scrollLeft() - o.scrollSpeed);
                } else if (this.window.width() - (event.pageX - this.document.scrollLeft()) < o.scrollSensitivity) {
                    scrolled = this.document.scrollLeft(this.document.scrollLeft() + o.scrollSpeed);
                }
            }
            return scrolled;
        },
        _mouseDrag: function(event) {
            var i, item, itemElement, intersection, o = this.options;
            this.position = this._generatePosition(event);
            this.positionAbs = this._convertPositionTo("absolute");
            if (!this.options.axis || this.options.axis !== "y") {
                this.helper[0].style.left = this.position.left + "px";
            }
            if (!this.options.axis || this.options.axis !== "x") {
                this.helper[0].style.top = this.position.top + "px";
            }
            if (o.scroll) {
                if (this._scroll(event) !== false) {
                    this._refreshItemPositions(true);
                    if ($.ui.ddmanager && !o.dropBehaviour) {
                        $.ui.ddmanager.prepareOffsets(this, event);
                    }
                }
            }
            this.dragDirection = {
                vertical: this._getDragVerticalDirection(),
                horizontal: this._getDragHorizontalDirection()
            };
            for (i = this.items.length - 1; i >= 0; i--) {
                item = this.items[i];
                itemElement = item.item[0];
                intersection = this._intersectsWithPointer(item);
                if (!intersection) {
                    continue;
                }
                if (item.instance !== this.currentContainer) {
                    continue;
                }
                if (itemElement !== this.currentItem[0] && this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement && !$.contains(this.placeholder[0], itemElement) && (this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true)) {
                    this.direction = intersection === 1 ? "down" : "up";
                    if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) {
                        this._rearrange(event, item);
                    } else {
                        break;
                    }
                    this._trigger("change", event, this._uiHash());
                    break;
                }
            }
            this._contactContainers(event);
            if ($.ui.ddmanager) {
                $.ui.ddmanager.drag(this, event);
            }
            this._trigger("sort", event, this._uiHash());
            this.lastPositionAbs = this.positionAbs;
            return false;
        },
        _mouseStop: function(event, noPropagation) {
            if (!event) {
                return;
            }
            if ($.ui.ddmanager && !this.options.dropBehaviour) {
                $.ui.ddmanager.drop(this, event);
            }
            if (this.options.revert) {
                var that = this, cur = this.placeholder.offset(), axis = this.options.axis, animation = {};
                if (!axis || axis === "x") {
                    animation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === this.document[0].body ? 0 : this.offsetParent[0].scrollLeft);
                }
                if (!axis || axis === "y") {
                    animation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === this.document[0].body ? 0 : this.offsetParent[0].scrollTop);
                }
                this.reverting = true;
                $(this.helper).animate(animation, parseInt(this.options.revert, 10) || 500, function() {
                    that._clear(event);
                });
            } else {
                this._clear(event, noPropagation);
            }
            return false;
        },
        cancel: function() {
            if (this.dragging) {
                this._mouseUp(new $.Event("mouseup", {
                    target: null
                }));
                if (this.options.helper === "original") {
                    this.currentItem.css(this._storedCSS);
                    this._removeClass(this.currentItem, "ui-sortable-helper");
                } else {
                    this.currentItem.show();
                }
                for (var i = this.containers.length - 1; i >= 0; i--) {
                    this.containers[i]._trigger("deactivate", null, this._uiHash(this));
                    if (this.containers[i].containerCache.over) {
                        this.containers[i]._trigger("out", null, this._uiHash(this));
                        this.containers[i].containerCache.over = 0;
                    }
                }
            }
            if (this.placeholder) {
                if (this.placeholder[0].parentNode) {
                    this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
                }
                if (this.options.helper !== "original" && this.helper && this.helper[0].parentNode) {
                    this.helper.remove();
                }
                $.extend(this, {
                    helper: null,
                    dragging: false,
                    reverting: false,
                    _noFinalSort: null
                });
                if (this.domPosition.prev) {
                    $(this.domPosition.prev).after(this.currentItem);
                } else {
                    $(this.domPosition.parent).prepend(this.currentItem);
                }
            }
            return this;
        },
        serialize: function(o) {
            var items = this._getItemsAsjQuery(o && o.connected), str = [];
            o = o || {};
            $(items).each(function() {
                var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || /(.+)[\-=_](.+)/);
                if (res) {
                    str.push((o.key || res[1] + "[]") + "=" + (o.key && o.expression ? res[1] : res[2]));
                }
            });
            if (!str.length && o.key) {
                str.push(o.key + "=");
            }
            return str.join("&");
        },
        toArray: function(o) {
            var items = this._getItemsAsjQuery(o && o.connected), ret = [];
            o = o || {};
            items.each(function() {
                ret.push($(o.item || this).attr(o.attribute || "id") || "");
            });
            return ret;
        },
        _intersectsWith: function(item) {
            var x1 = this.positionAbs.left, x2 = x1 + this.helperProportions.width, y1 = this.positionAbs.top, y2 = y1 + this.helperProportions.height, l = item.left, r = l + item.width, t = item.top, b = t + item.height, dyClick = this.offset.click.top, dxClick = this.offset.click.left, isOverElementHeight = this.options.axis === "x" || y1 + dyClick > t && y1 + dyClick < b, isOverElementWidth = this.options.axis === "y" || x1 + dxClick > l && x1 + dxClick < r, isOverElement = isOverElementHeight && isOverElementWidth;
            if (this.options.tolerance === "pointer" || this.options.forcePointerForContainers || this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"]) {
                return isOverElement;
            } else {
                return l < x1 + this.helperProportions.width / 2 && x2 - this.helperProportions.width / 2 < r && t < y1 + this.helperProportions.height / 2 && y2 - this.helperProportions.height / 2 < b;
            }
        },
        _intersectsWithPointer: function(item) {
            var verticalDirection, horizontalDirection, isOverElementHeight = this.options.axis === "x" || this._isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height), isOverElementWidth = this.options.axis === "y" || this._isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width), isOverElement = isOverElementHeight && isOverElementWidth;
            if (!isOverElement) {
                return false;
            }
            verticalDirection = this.dragDirection.vertical;
            horizontalDirection = this.dragDirection.horizontal;
            return this.floating ? horizontalDirection === "right" || verticalDirection === "down" ? 2 : 1 : verticalDirection && (verticalDirection === "down" ? 2 : 1);
        },
        _intersectsWithSides: function(item) {
            var isOverBottomHalf = this._isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + item.height / 2, item.height), isOverRightHalf = this._isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + item.width / 2, item.width), verticalDirection = this.dragDirection.vertical, horizontalDirection = this.dragDirection.horizontal;
            if (this.floating && horizontalDirection) {
                return horizontalDirection === "right" && isOverRightHalf || horizontalDirection === "left" && !isOverRightHalf;
            } else {
                return verticalDirection && (verticalDirection === "down" && isOverBottomHalf || verticalDirection === "up" && !isOverBottomHalf);
            }
        },
        _getDragVerticalDirection: function() {
            var delta = this.positionAbs.top - this.lastPositionAbs.top;
            return delta !== 0 && (delta > 0 ? "down" : "up");
        },
        _getDragHorizontalDirection: function() {
            var delta = this.positionAbs.left - this.lastPositionAbs.left;
            return delta !== 0 && (delta > 0 ? "right" : "left");
        },
        refresh: function(event) {
            this._refreshItems(event);
            this._setHandleClassName();
            this.refreshPositions();
            return this;
        },
        _connectWith: function() {
            var options = this.options;
            return options.connectWith.constructor === String ? [ options.connectWith ] : options.connectWith;
        },
        _getItemsAsjQuery: function(connected) {
            var i, j, cur, inst, items = [], queries = [], connectWith = this._connectWith();
            if (connectWith && connected) {
                for (i = connectWith.length - 1; i >= 0; i--) {
                    cur = $(connectWith[i], this.document[0]);
                    for (j = cur.length - 1; j >= 0; j--) {
                        inst = $.data(cur[j], this.widgetFullName);
                        if (inst && inst !== this && !inst.options.disabled) {
                            queries.push([ typeof inst.options.items === "function" ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), inst ]);
                        }
                    }
                }
            }
            queries.push([ typeof this.options.items === "function" ? this.options.items.call(this.element, null, {
                options: this.options,
                item: this.currentItem
            }) : $(this.options.items, this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), this ]);
            function addItems() {
                items.push(this);
            }
            for (i = queries.length - 1; i >= 0; i--) {
                queries[i][0].each(addItems);
            }
            return $(items);
        },
        _removeCurrentsFromItems: function() {
            var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
            this.items = $.grep(this.items, function(item) {
                for (var j = 0; j < list.length; j++) {
                    if (list[j] === item.item[0]) {
                        return false;
                    }
                }
                return true;
            });
        },
        _refreshItems: function(event) {
            this.items = [];
            this.containers = [ this ];
            var i, j, cur, inst, targetData, _queries, item, queriesLength, items = this.items, queries = [ [ typeof this.options.items === "function" ? this.options.items.call(this.element[0], event, {
                item: this.currentItem
            }) : $(this.options.items, this.element), this ] ], connectWith = this._connectWith();
            if (connectWith && this.ready) {
                for (i = connectWith.length - 1; i >= 0; i--) {
                    cur = $(connectWith[i], this.document[0]);
                    for (j = cur.length - 1; j >= 0; j--) {
                        inst = $.data(cur[j], this.widgetFullName);
                        if (inst && inst !== this && !inst.options.disabled) {
                            queries.push([ typeof inst.options.items === "function" ? inst.options.items.call(inst.element[0], event, {
                                item: this.currentItem
                            }) : $(inst.options.items, inst.element), inst ]);
                            this.containers.push(inst);
                        }
                    }
                }
            }
            for (i = queries.length - 1; i >= 0; i--) {
                targetData = queries[i][1];
                _queries = queries[i][0];
                for (j = 0, queriesLength = _queries.length; j < queriesLength; j++) {
                    item = $(_queries[j]);
                    item.data(this.widgetName + "-item", targetData);
                    items.push({
                        item: item,
                        instance: targetData,
                        width: 0,
                        height: 0,
                        left: 0,
                        top: 0
                    });
                }
            }
        },
        _refreshItemPositions: function(fast) {
            var i, item, t, p;
            for (i = this.items.length - 1; i >= 0; i--) {
                item = this.items[i];
                if (this.currentContainer && item.instance !== this.currentContainer && item.item[0] !== this.currentItem[0]) {
                    continue;
                }
                t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
                if (!fast) {
                    item.width = t.outerWidth();
                    item.height = t.outerHeight();
                }
                p = t.offset();
                item.left = p.left;
                item.top = p.top;
            }
        },
        refreshPositions: function(fast) {
            this.floating = this.items.length ? this.options.axis === "x" || this._isFloating(this.items[0].item) : false;
            if (this.offsetParent && this.helper) {
                this.offset.parent = this._getParentOffset();
            }
            this._refreshItemPositions(fast);
            var i, p;
            if (this.options.custom && this.options.custom.refreshContainers) {
                this.options.custom.refreshContainers.call(this);
            } else {
                for (i = this.containers.length - 1; i >= 0; i--) {
                    p = this.containers[i].element.offset();
                    this.containers[i].containerCache.left = p.left;
                    this.containers[i].containerCache.top = p.top;
                    this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
                    this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
                }
            }
            return this;
        },
        _createPlaceholder: function(that) {
            that = that || this;
            var className, nodeName, o = that.options;
            if (!o.placeholder || o.placeholder.constructor === String) {
                className = o.placeholder;
                nodeName = that.currentItem[0].nodeName.toLowerCase();
                o.placeholder = {
                    element: function() {
                        var element = $("<" + nodeName + ">", that.document[0]);
                        that._addClass(element, "ui-sortable-placeholder", className || that.currentItem[0].className)._removeClass(element, "ui-sortable-helper");
                        if (nodeName === "tbody") {
                            that._createTrPlaceholder(that.currentItem.find("tr").eq(0), $("<tr>", that.document[0]).appendTo(element));
                        } else if (nodeName === "tr") {
                            that._createTrPlaceholder(that.currentItem, element);
                        } else if (nodeName === "img") {
                            element.attr("src", that.currentItem.attr("src"));
                        }
                        if (!className) {
                            element.css("visibility", "hidden");
                        }
                        return element;
                    },
                    update: function(container, p) {
                        if (className && !o.forcePlaceholderSize) {
                            return;
                        }
                        if (!p.height() || o.forcePlaceholderSize && (nodeName === "tbody" || nodeName === "tr")) {
                            p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop") || 0, 10) - parseInt(that.currentItem.css("paddingBottom") || 0, 10));
                        }
                        if (!p.width()) {
                            p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft") || 0, 10) - parseInt(that.currentItem.css("paddingRight") || 0, 10));
                        }
                    }
                };
            }
            that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));
            that.currentItem.after(that.placeholder);
            o.placeholder.update(that, that.placeholder);
        },
        _createTrPlaceholder: function(sourceTr, targetTr) {
            var that = this;
            sourceTr.children().each(function() {
                $("<td>&#160;</td>", that.document[0]).attr("colspan", $(this).attr("colspan") || 1).appendTo(targetTr);
            });
        },
        _contactContainers: function(event) {
            var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom, floating, axis, innermostContainer = null, innermostIndex = null;
            for (i = this.containers.length - 1; i >= 0; i--) {
                if ($.contains(this.currentItem[0], this.containers[i].element[0])) {
                    continue;
                }
                if (this._intersectsWith(this.containers[i].containerCache)) {
                    if (innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) {
                        continue;
                    }
                    innermostContainer = this.containers[i];
                    innermostIndex = i;
                } else {
                    if (this.containers[i].containerCache.over) {
                        this.containers[i]._trigger("out", event, this._uiHash(this));
                        this.containers[i].containerCache.over = 0;
                    }
                }
            }
            if (!innermostContainer) {
                return;
            }
            if (this.containers.length === 1) {
                if (!this.containers[innermostIndex].containerCache.over) {
                    this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
                    this.containers[innermostIndex].containerCache.over = 1;
                }
            } else {
                dist = 1e4;
                itemWithLeastDistance = null;
                floating = innermostContainer.floating || this._isFloating(this.currentItem);
                posProperty = floating ? "left" : "top";
                sizeProperty = floating ? "width" : "height";
                axis = floating ? "pageX" : "pageY";
                for (j = this.items.length - 1; j >= 0; j--) {
                    if (!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) {
                        continue;
                    }
                    if (this.items[j].item[0] === this.currentItem[0]) {
                        continue;
                    }
                    cur = this.items[j].item.offset()[posProperty];
                    nearBottom = false;
                    if (event[axis] - cur > this.items[j][sizeProperty] / 2) {
                        nearBottom = true;
                    }
                    if (Math.abs(event[axis] - cur) < dist) {
                        dist = Math.abs(event[axis] - cur);
                        itemWithLeastDistance = this.items[j];
                        this.direction = nearBottom ? "up" : "down";
                    }
                }
                if (!itemWithLeastDistance && !this.options.dropOnEmpty) {
                    return;
                }
                if (this.currentContainer === this.containers[innermostIndex]) {
                    if (!this.currentContainer.containerCache.over) {
                        this.containers[innermostIndex]._trigger("over", event, this._uiHash());
                        this.currentContainer.containerCache.over = 1;
                    }
                    return;
                }
                if (itemWithLeastDistance) {
                    this._rearrange(event, itemWithLeastDistance, null, true);
                } else {
                    this._rearrange(event, null, this.containers[innermostIndex].element, true);
                }
                this._trigger("change", event, this._uiHash());
                this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
                this.currentContainer = this.containers[innermostIndex];
                this.options.placeholder.update(this.currentContainer, this.placeholder);
                this.scrollParent = this.placeholder.scrollParent();
                if (this.scrollParent[0] !== this.document[0] && this.scrollParent[0].tagName !== "HTML") {
                    this.overflowOffset = this.scrollParent.offset();
                }
                this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
                this.containers[innermostIndex].containerCache.over = 1;
            }
        },
        _createHelper: function(event) {
            var o = this.options, helper = typeof o.helper === "function" ? $(o.helper.apply(this.element[0], [ event, this.currentItem ])) : o.helper === "clone" ? this.currentItem.clone() : this.currentItem;
            if (!helper.parents("body").length) {
                this.appendTo[0].appendChild(helper[0]);
            }
            if (helper[0] === this.currentItem[0]) {
                this._storedCSS = {
                    width: this.currentItem[0].style.width,
                    height: this.currentItem[0].style.height,
                    position: this.currentItem.css("position"),
                    top: this.currentItem.css("top"),
                    left: this.currentItem.css("left")
                };
            }
            if (!helper[0].style.width || o.forceHelperSize) {
                helper.width(this.currentItem.width());
            }
            if (!helper[0].style.height || o.forceHelperSize) {
                helper.height(this.currentItem.height());
            }
            return helper;
        },
        _adjustOffsetFromHelper: function(obj) {
            if (typeof obj === "function") {
                obj = obj.call(this);
            }
            if (typeof obj === "string") {
                obj = obj.split(" ");
            }
            if (Array.isArray(obj)) {
                obj = {
                    left: +obj[0],
                    top: +obj[1] || 0
                };
            }
            if ("left" in obj) {
                this.offset.click.left = obj.left + this.margins.left;
            }
            if ("right" in obj) {
                this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
            }
            if ("top" in obj) {
                this.offset.click.top = obj.top + this.margins.top;
            }
            if ("bottom" in obj) {
                this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
            }
        },
        _getParentOffset: function() {
            this.offsetParent = this.helper.offsetParent();
            var po = this.offsetParent.offset();
            if (this.cssPosition === "absolute" && this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) {
                po.left += this.scrollParent.scrollLeft();
                po.top += this.scrollParent.scrollTop();
            }
            if (this.offsetParent[0] === this.document[0].body || this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie) {
                po = {
                    top: 0,
                    left: 0
                };
            }
            return {
                top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"), 10) || 0),
                left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"), 10) || 0)
            };
        },
        _getRelativeOffset: function() {
            if (this.cssPosition === "relative") {
                var p = this.currentItem.position();
                return {
                    top: p.top - (parseInt(this.helper.css("top"), 10) || 0) + this.scrollParent.scrollTop(),
                    left: p.left - (parseInt(this.helper.css("left"), 10) || 0) + this.scrollParent.scrollLeft()
                };
            } else {
                return {
                    top: 0,
                    left: 0
                };
            }
        },
        _cacheMargins: function() {
            this.margins = {
                left: parseInt(this.currentItem.css("marginLeft"), 10) || 0,
                top: parseInt(this.currentItem.css("marginTop"), 10) || 0
            };
        },
        _cacheHelperProportions: function() {
            this.helperProportions = {
                width: this.helper.outerWidth(),
                height: this.helper.outerHeight()
            };
        },
        _setContainment: function() {
            var ce, co, over, o = this.options;
            if (o.containment === "parent") {
                o.containment = this.helper[0].parentNode;
            }
            if (o.containment === "document" || o.containment === "window") {
                this.containment = [ 0 - this.offset.relative.left - this.offset.parent.left, 0 - this.offset.relative.top - this.offset.parent.top, o.containment === "document" ? this.document.width() : this.window.width() - this.helperProportions.width - this.margins.left, (o.containment === "document" ? this.document.height() || document.body.parentNode.scrollHeight : this.window.height() || this.document[0].body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top ];
            }
            if (!/^(document|window|parent)$/.test(o.containment)) {
                ce = $(o.containment)[0];
                co = $(o.containment).offset();
                over = $(ce).css("overflow") !== "hidden";
                this.containment = [ co.left + (parseInt($(ce).css("borderLeftWidth"), 10) || 0) + (parseInt($(ce).css("paddingLeft"), 10) || 0) - this.margins.left, co.top + (parseInt($(ce).css("borderTopWidth"), 10) || 0) + (parseInt($(ce).css("paddingTop"), 10) || 0) - this.margins.top, co.left + (over ? Math.max(ce.scrollWidth, ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"), 10) || 0) - (parseInt($(ce).css("paddingRight"), 10) || 0) - this.helperProportions.width - this.margins.left, co.top + (over ? Math.max(ce.scrollHeight, ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"), 10) || 0) - (parseInt($(ce).css("paddingBottom"), 10) || 0) - this.helperProportions.height - this.margins.top ];
            }
        },
        _convertPositionTo: function(d, pos) {
            if (!pos) {
                pos = this.position;
            }
            var mod = d === "absolute" ? 1 : -1, scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = /(html|body)/i.test(scroll[0].tagName);
            return {
                top: pos.top + this.offset.relative.top * mod + this.offset.parent.top * mod - (this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : scrollIsRootNode ? 0 : scroll.scrollTop()) * mod,
                left: pos.left + this.offset.relative.left * mod + this.offset.parent.left * mod - (this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft()) * mod
            };
        },
        _generatePosition: function(event) {
            var top, left, o = this.options, pageX = event.pageX, pageY = event.pageY, scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== this.document[0] && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = /(html|body)/i.test(scroll[0].tagName);
            if (this.cssPosition === "relative" && !(this.scrollParent[0] !== this.document[0] && this.scrollParent[0] !== this.offsetParent[0])) {
                this.offset.relative = this._getRelativeOffset();
            }
            if (this.originalPosition) {
                if (this.containment) {
                    if (event.pageX - this.offset.click.left < this.containment[0]) {
                        pageX = this.containment[0] + this.offset.click.left;
                    }
                    if (event.pageY - this.offset.click.top < this.containment[1]) {
                        pageY = this.containment[1] + this.offset.click.top;
                    }
                    if (event.pageX - this.offset.click.left > this.containment[2]) {
                        pageX = this.containment[2] + this.offset.click.left;
                    }
                    if (event.pageY - this.offset.click.top > this.containment[3]) {
                        pageY = this.containment[3] + this.offset.click.top;
                    }
                }
                if (o.grid) {
                    top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
                    pageY = this.containment ? top - this.offset.click.top >= this.containment[1] && top - this.offset.click.top <= this.containment[3] ? top : top - this.offset.click.top >= this.containment[1] ? top - o.grid[1] : top + o.grid[1] : top;
                    left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
                    pageX = this.containment ? left - this.offset.click.left >= this.containment[0] && left - this.offset.click.left <= this.containment[2] ? left : left - this.offset.click.left >= this.containment[0] ? left - o.grid[0] : left + o.grid[0] : left;
                }
            }
            return {
                top: pageY - this.offset.click.top - this.offset.relative.top - this.offset.parent.top + (this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : scrollIsRootNode ? 0 : scroll.scrollTop()),
                left: pageX - this.offset.click.left - this.offset.relative.left - this.offset.parent.left + (this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft())
            };
        },
        _rearrange: function(event, i, a, hardRefresh) {
            if (a) {
                a[0].appendChild(this.placeholder[0]);
            } else {
                i.item[0].parentNode.insertBefore(this.placeholder[0], this.direction === "down" ? i.item[0] : i.item[0].nextSibling);
            }
            this.counter = this.counter ? ++this.counter : 1;
            var counter = this.counter;
            this._delay(function() {
                if (counter === this.counter) {
                    this.refreshPositions(!hardRefresh);
                }
            });
        },
        _clear: function(event, noPropagation) {
            this.reverting = false;
            var i, delayedTriggers = [];
            if (!this._noFinalSort && this.currentItem.parent().length) {
                this.placeholder.before(this.currentItem);
            }
            this._noFinalSort = null;
            if (this.helper[0] === this.currentItem[0]) {
                for (i in this._storedCSS) {
                    if (this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") {
                        this._storedCSS[i] = "";
                    }
                }
                this.currentItem.css(this._storedCSS);
                this._removeClass(this.currentItem, "ui-sortable-helper");
            } else {
                this.currentItem.show();
            }
            if (this.fromOutside && !noPropagation) {
                delayedTriggers.push(function(event) {
                    this._trigger("receive", event, this._uiHash(this.fromOutside));
                });
            }
            if ((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) {
                delayedTriggers.push(function(event) {
                    this._trigger("update", event, this._uiHash());
                });
            }
            if (this !== this.currentContainer) {
                if (!noPropagation) {
                    delayedTriggers.push(function(event) {
                        this._trigger("remove", event, this._uiHash());
                    });
                    delayedTriggers.push(function(c) {
                        return function(event) {
                            c._trigger("receive", event, this._uiHash(this));
                        };
                    }.call(this, this.currentContainer));
                    delayedTriggers.push(function(c) {
                        return function(event) {
                            c._trigger("update", event, this._uiHash(this));
                        };
                    }.call(this, this.currentContainer));
                }
            }
            function delayEvent(type, instance, container) {
                return function(event) {
                    container._trigger(type, event, instance._uiHash(instance));
                };
            }
            for (i = this.containers.length - 1; i >= 0; i--) {
                if (!noPropagation) {
                    delayedTriggers.push(delayEvent("deactivate", this, this.containers[i]));
                }
                if (this.containers[i].containerCache.over) {
                    delayedTriggers.push(delayEvent("out", this, this.containers[i]));
                    this.containers[i].containerCache.over = 0;
                }
            }
            if (this.storedCursor) {
                this.document.find("body").css("cursor", this.storedCursor);
                this.storedStylesheet.remove();
            }
            if (this._storedOpacity) {
                this.helper.css("opacity", this._storedOpacity);
            }
            if (this._storedZIndex) {
                this.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex);
            }
            this.dragging = false;
            if (!noPropagation) {
                this._trigger("beforeStop", event, this._uiHash());
            }
            this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
            if (!this.cancelHelperRemoval) {
                if (this.helper[0] !== this.currentItem[0]) {
                    this.helper.remove();
                }
                this.helper = null;
            }
            if (!noPropagation) {
                for (i = 0; i < delayedTriggers.length; i++) {
                    delayedTriggers[i].call(this, event);
                }
                this._trigger("stop", event, this._uiHash());
            }
            this.fromOutside = false;
            return !this.cancelHelperRemoval;
        },
        _trigger: function() {
            if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
                this.cancel();
            }
        },
        _uiHash: function(_inst) {
            var inst = _inst || this;
            return {
                helper: inst.helper,
                placeholder: inst.placeholder || $([]),
                position: inst.position,
                originalPosition: inst.originalPosition,
                offset: inst.positionAbs,
                item: inst.currentItem,
                sender: _inst ? _inst.element : null
            };
        }
    });
    function spinnerModifier(fn) {
        return function() {
            var previous = this.element.val();
            fn.apply(this, arguments);
            this._refresh();
            if (previous !== this.element.val()) {
                this._trigger("change");
            }
        };
    }
    $.widget("ui.spinner", {
        version: "1.13.1",
        defaultElement: "<input>",
        widgetEventPrefix: "spin",
        options: {
            classes: {
                "ui-spinner": "ui-corner-all",
                "ui-spinner-down": "ui-corner-br",
                "ui-spinner-up": "ui-corner-tr"
            },
            culture: null,
            icons: {
                down: "ui-icon-triangle-1-s",
                up: "ui-icon-triangle-1-n"
            },
            incremental: true,
            max: null,
            min: null,
            numberFormat: null,
            page: 10,
            step: 1,
            change: null,
            spin: null,
            start: null,
            stop: null
        },
        _create: function() {
            this._setOption("max", this.options.max);
            this._setOption("min", this.options.min);
            this._setOption("step", this.options.step);
            if (this.value() !== "") {
                this._value(this.element.val(), true);
            }
            this._draw();
            this._on(this._events);
            this._refresh();
            this._on(this.window, {
                beforeunload: function() {
                    this.element.removeAttr("autocomplete");
                }
            });
        },
        _getCreateOptions: function() {
            var options = this._super();
            var element = this.element;
            $.each([ "min", "max", "step" ], function(i, option) {
                var value = element.attr(option);
                if (value != null && value.length) {
                    options[option] = value;
                }
            });
            return options;
        },
        _events: {
            keydown: function(event) {
                if (this._start(event) && this._keydown(event)) {
                    event.preventDefault();
                }
            },
            keyup: "_stop",
            focus: function() {
                this.previous = this.element.val();
            },
            blur: function(event) {
                if (this.cancelBlur) {
                    delete this.cancelBlur;
                    return;
                }
                this._stop();
                this._refresh();
                if (this.previous !== this.element.val()) {
                    this._trigger("change", event);
                }
            },
            mousewheel: function(event, delta) {
                var activeElement = $.ui.safeActiveElement(this.document[0]);
                var isActive = this.element[0] === activeElement;
                if (!isActive || !delta) {
                    return;
                }
                if (!this.spinning && !this._start(event)) {
                    return false;
                }
                this._spin((delta > 0 ? 1 : -1) * this.options.step, event);
                clearTimeout(this.mousewheelTimer);
                this.mousewheelTimer = this._delay(function() {
                    if (this.spinning) {
                        this._stop(event);
                    }
                }, 100);
                event.preventDefault();
            },
            "mousedown .ui-spinner-button": function(event) {
                var previous;
                previous = this.element[0] === $.ui.safeActiveElement(this.document[0]) ? this.previous : this.element.val();
                function checkFocus() {
                    var isActive = this.element[0] === $.ui.safeActiveElement(this.document[0]);
                    if (!isActive) {
                        this.element.trigger("focus");
                        this.previous = previous;
                        this._delay(function() {
                            this.previous = previous;
                        });
                    }
                }
                event.preventDefault();
                checkFocus.call(this);
                this.cancelBlur = true;
                this._delay(function() {
                    delete this.cancelBlur;
                    checkFocus.call(this);
                });
                if (this._start(event) === false) {
                    return;
                }
                this._repeat(null, $(event.currentTarget).hasClass("ui-spinner-up") ? 1 : -1, event);
            },
            "mouseup .ui-spinner-button": "_stop",
            "mouseenter .ui-spinner-button": function(event) {
                if (!$(event.currentTarget).hasClass("ui-state-active")) {
                    return;
                }
                if (this._start(event) === false) {
                    return false;
                }
                this._repeat(null, $(event.currentTarget).hasClass("ui-spinner-up") ? 1 : -1, event);
            },
            "mouseleave .ui-spinner-button": "_stop"
        },
        _enhance: function() {
            this.uiSpinner = this.element.attr("autocomplete", "off").wrap("<span>").parent().append("<a></a><a></a>");
        },
        _draw: function() {
            this._enhance();
            this._addClass(this.uiSpinner, "ui-spinner", "ui-widget ui-widget-content");
            this._addClass("ui-spinner-input");
            this.element.attr("role", "spinbutton");
            this.buttons = this.uiSpinner.children("a").attr("tabIndex", -1).attr("aria-hidden", true).button({
                classes: {
                    "ui-button": ""
                }
            });
            this._removeClass(this.buttons, "ui-corner-all");
            this._addClass(this.buttons.first(), "ui-spinner-button ui-spinner-up");
            this._addClass(this.buttons.last(), "ui-spinner-button ui-spinner-down");
            this.buttons.first().button({
                icon: this.options.icons.up,
                showLabel: false
            });
            this.buttons.last().button({
                icon: this.options.icons.down,
                showLabel: false
            });
            if (this.buttons.height() > Math.ceil(this.uiSpinner.height() * .5) && this.uiSpinner.height() > 0) {
                this.uiSpinner.height(this.uiSpinner.height());
            }
        },
        _keydown: function(event) {
            var options = this.options, keyCode = $.ui.keyCode;
            switch (event.keyCode) {
              case keyCode.UP:
                this._repeat(null, 1, event);
                return true;

              case keyCode.DOWN:
                this._repeat(null, -1, event);
                return true;

              case keyCode.PAGE_UP:
                this._repeat(null, options.page, event);
                return true;

              case keyCode.PAGE_DOWN:
                this._repeat(null, -options.page, event);
                return true;
            }
            return false;
        },
        _start: function(event) {
            if (!this.spinning && this._trigger("start", event) === false) {
                return false;
            }
            if (!this.counter) {
                this.counter = 1;
            }
            this.spinning = true;
            return true;
        },
        _repeat: function(i, steps, event) {
            i = i || 500;
            clearTimeout(this.timer);
            this.timer = this._delay(function() {
                this._repeat(40, steps, event);
            }, i);
            this._spin(steps * this.options.step, event);
        },
        _spin: function(step, event) {
            var value = this.value() || 0;
            if (!this.counter) {
                this.counter = 1;
            }
            value = this._adjustValue(value + step * this._increment(this.counter));
            if (!this.spinning || this._trigger("spin", event, {
                value: value
            }) !== false) {
                this._value(value);
                this.counter++;
            }
        },
        _increment: function(i) {
            var incremental = this.options.incremental;
            if (incremental) {
                return typeof incremental === "function" ? incremental(i) : Math.floor(i * i * i / 5e4 - i * i / 500 + 17 * i / 200 + 1);
            }
            return 1;
        },
        _precision: function() {
            var precision = this._precisionOf(this.options.step);
            if (this.options.min !== null) {
                precision = Math.max(precision, this._precisionOf(this.options.min));
            }
            return precision;
        },
        _precisionOf: function(num) {
            var str = num.toString(), decimal = str.indexOf(".");
            return decimal === -1 ? 0 : str.length - decimal - 1;
        },
        _adjustValue: function(value) {
            var base, aboveMin, options = this.options;
            base = options.min !== null ? options.min : 0;
            aboveMin = value - base;
            aboveMin = Math.round(aboveMin / options.step) * options.step;
            value = base + aboveMin;
            value = parseFloat(value.toFixed(this._precision()));
            if (options.max !== null && value > options.max) {
                return options.max;
            }
            if (options.min !== null && value < options.min) {
                return options.min;
            }
            return value;
        },
        _stop: function(event) {
            if (!this.spinning) {
                return;
            }
            clearTimeout(this.timer);
            clearTimeout(this.mousewheelTimer);
            this.counter = 0;
            this.spinning = false;
            this._trigger("stop", event);
        },
        _setOption: function(key, value) {
            var prevValue, first, last;
            if (key === "culture" || key === "numberFormat") {
                prevValue = this._parse(this.element.val());
                this.options[key] = value;
                this.element.val(this._format(prevValue));
                return;
            }
            if (key === "max" || key === "min" || key === "step") {
                if (typeof value === "string") {
                    value = this._parse(value);
                }
            }
            if (key === "icons") {
                first = this.buttons.first().find(".ui-icon");
                this._removeClass(first, null, this.options.icons.up);
                this._addClass(first, null, value.up);
                last = this.buttons.last().find(".ui-icon");
                this._removeClass(last, null, this.options.icons.down);
                this._addClass(last, null, value.down);
            }
            this._super(key, value);
        },
        _setOptionDisabled: function(value) {
            this._super(value);
            this._toggleClass(this.uiSpinner, null, "ui-state-disabled", !!value);
            this.element.prop("disabled", !!value);
            this.buttons.button(value ? "disable" : "enable");
        },
        _setOptions: spinnerModifier(function(options) {
            this._super(options);
        }),
        _parse: function(val) {
            if (typeof val === "string" && val !== "") {
                val = window.Globalize && this.options.numberFormat ? Globalize.parseFloat(val, 10, this.options.culture) : +val;
            }
            return val === "" || isNaN(val) ? null : val;
        },
        _format: function(value) {
            if (value === "") {
                return "";
            }
            return window.Globalize && this.options.numberFormat ? Globalize.format(value, this.options.numberFormat, this.options.culture) : value;
        },
        _refresh: function() {
            this.element.attr({
                "aria-valuemin": this.options.min,
                "aria-valuemax": this.options.max,
                "aria-valuenow": this._parse(this.element.val())
            });
        },
        isValid: function() {
            var value = this.value();
            if (value === null) {
                return false;
            }
            return value === this._adjustValue(value);
        },
        _value: function(value, allowAny) {
            var parsed;
            if (value !== "") {
                parsed = this._parse(value);
                if (parsed !== null) {
                    if (!allowAny) {
                        parsed = this._adjustValue(parsed);
                    }
                    value = this._format(parsed);
                }
            }
            this.element.val(value);
            this._refresh();
        },
        _destroy: function() {
            this.element.prop("disabled", false).removeAttr("autocomplete role aria-valuemin aria-valuemax aria-valuenow");
            this.uiSpinner.replaceWith(this.element);
        },
        stepUp: spinnerModifier(function(steps) {
            this._stepUp(steps);
        }),
        _stepUp: function(steps) {
            if (this._start()) {
                this._spin((steps || 1) * this.options.step);
                this._stop();
            }
        },
        stepDown: spinnerModifier(function(steps) {
            this._stepDown(steps);
        }),
        _stepDown: function(steps) {
            if (this._start()) {
                this._spin((steps || 1) * -this.options.step);
                this._stop();
            }
        },
        pageUp: spinnerModifier(function(pages) {
            this._stepUp((pages || 1) * this.options.page);
        }),
        pageDown: spinnerModifier(function(pages) {
            this._stepDown((pages || 1) * this.options.page);
        }),
        value: function(newVal) {
            if (!arguments.length) {
                return this._parse(this.element.val());
            }
            spinnerModifier(this._value).call(this, newVal);
        },
        widget: function() {
            return this.uiSpinner;
        }
    });
    if ($.uiBackCompat !== false) {
        $.widget("ui.spinner", $.ui.spinner, {
            _enhance: function() {
                this.uiSpinner = this.element.attr("autocomplete", "off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml());
            },
            _uiSpinnerHtml: function() {
                return "<span>";
            },
            _buttonHtml: function() {
                return "<a></a><a></a>";
            }
        });
    }
    var widgetsSpinner = $.ui.spinner;
    $.widget("ui.tabs", {
        version: "1.13.1",
        delay: 300,
        options: {
            active: null,
            classes: {
                "ui-tabs": "ui-corner-all",
                "ui-tabs-nav": "ui-corner-all",
                "ui-tabs-panel": "ui-corner-bottom",
                "ui-tabs-tab": "ui-corner-top"
            },
            collapsible: false,
            event: "click",
            heightStyle: "content",
            hide: null,
            show: null,
            activate: null,
            beforeActivate: null,
            beforeLoad: null,
            load: null
        },
        _isLocal: function() {
            var rhash = /#.*$/;
            return function(anchor) {
                var anchorUrl, locationUrl;
                anchorUrl = anchor.href.replace(rhash, "");
                locationUrl = location.href.replace(rhash, "");
                try {
                    anchorUrl = decodeURIComponent(anchorUrl);
                } catch (error) {}
                try {
                    locationUrl = decodeURIComponent(locationUrl);
                } catch (error) {}
                return anchor.hash.length > 1 && anchorUrl === locationUrl;
            };
        }(),
        _create: function() {
            var that = this, options = this.options;
            this.running = false;
            this._addClass("ui-tabs", "ui-widget ui-widget-content");
            this._toggleClass("ui-tabs-collapsible", null, options.collapsible);
            this._processTabs();
            options.active = this._initialActive();
            if (Array.isArray(options.disabled)) {
                options.disabled = $.uniqueSort(options.disabled.concat($.map(this.tabs.filter(".ui-state-disabled"), function(li) {
                    return that.tabs.index(li);
                }))).sort();
            }
            if (this.options.active !== false && this.anchors.length) {
                this.active = this._findActive(options.active);
            } else {
                this.active = $();
            }
            this._refresh();
            if (this.active.length) {
                this.load(options.active);
            }
        },
        _initialActive: function() {
            var active = this.options.active, collapsible = this.options.collapsible, locationHash = location.hash.substring(1);
            if (active === null) {
                if (locationHash) {
                    this.tabs.each(function(i, tab) {
                        if ($(tab).attr("aria-controls") === locationHash) {
                            active = i;
                            return false;
                        }
                    });
                }
                if (active === null) {
                    active = this.tabs.index(this.tabs.filter(".ui-tabs-active"));
                }
                if (active === null || active === -1) {
                    active = this.tabs.length ? 0 : false;
                }
            }
            if (active !== false) {
                active = this.tabs.index(this.tabs.eq(active));
                if (active === -1) {
                    active = collapsible ? false : 0;
                }
            }
            if (!collapsible && active === false && this.anchors.length) {
                active = 0;
            }
            return active;
        },
        _getCreateEventData: function() {
            return {
                tab: this.active,
                panel: !this.active.length ? $() : this._getPanelForTab(this.active)
            };
        },
        _tabKeydown: function(event) {
            var focusedTab = $($.ui.safeActiveElement(this.document[0])).closest("li"), selectedIndex = this.tabs.index(focusedTab), goingForward = true;
            if (this._handlePageNav(event)) {
                return;
            }
            switch (event.keyCode) {
              case $.ui.keyCode.RIGHT:
              case $.ui.keyCode.DOWN:
                selectedIndex++;
                break;

              case $.ui.keyCode.UP:
              case $.ui.keyCode.LEFT:
                goingForward = false;
                selectedIndex--;
                break;

              case $.ui.keyCode.END:
                selectedIndex = this.anchors.length - 1;
                break;

              case $.ui.keyCode.HOME:
                selectedIndex = 0;
                break;

              case $.ui.keyCode.SPACE:
                event.preventDefault();
                clearTimeout(this.activating);
                this._activate(selectedIndex);
                return;

              case $.ui.keyCode.ENTER:
                event.preventDefault();
                clearTimeout(this.activating);
                this._activate(selectedIndex === this.options.active ? false : selectedIndex);
                return;

              default:
                return;
            }
            event.preventDefault();
            clearTimeout(this.activating);
            selectedIndex = this._focusNextTab(selectedIndex, goingForward);
            if (!event.ctrlKey && !event.metaKey) {
                focusedTab.attr("aria-selected", "false");
                this.tabs.eq(selectedIndex).attr("aria-selected", "true");
                this.activating = this._delay(function() {
                    this.option("active", selectedIndex);
                }, this.delay);
            }
        },
        _panelKeydown: function(event) {
            if (this._handlePageNav(event)) {
                return;
            }
            if (event.ctrlKey && event.keyCode === $.ui.keyCode.UP) {
                event.preventDefault();
                this.active.trigger("focus");
            }
        },
        _handlePageNav: function(event) {
            if (event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP) {
                this._activate(this._focusNextTab(this.options.active - 1, false));
                return true;
            }
            if (event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN) {
                this._activate(this._focusNextTab(this.options.active + 1, true));
                return true;
            }
        },
        _findNextTab: function(index, goingForward) {
            var lastTabIndex = this.tabs.length - 1;
            function constrain() {
                if (index > lastTabIndex) {
                    index = 0;
                }
                if (index < 0) {
                    index = lastTabIndex;
                }
                return index;
            }
            while ($.inArray(constrain(), this.options.disabled) !== -1) {
                index = goingForward ? index + 1 : index - 1;
            }
            return index;
        },
        _focusNextTab: function(index, goingForward) {
            index = this._findNextTab(index, goingForward);
            this.tabs.eq(index).trigger("focus");
            return index;
        },
        _setOption: function(key, value) {
            if (key === "active") {
                this._activate(value);
                return;
            }
            this._super(key, value);
            if (key === "collapsible") {
                this._toggleClass("ui-tabs-collapsible", null, value);
                if (!value && this.options.active === false) {
                    this._activate(0);
                }
            }
            if (key === "event") {
                this._setupEvents(value);
            }
            if (key === "heightStyle") {
                this._setupHeightStyle(value);
            }
        },
        _sanitizeSelector: function(hash) {
            return hash ? hash.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&") : "";
        },
        refresh: function() {
            var options = this.options, lis = this.tablist.children(":has(a[href])");
            options.disabled = $.map(lis.filter(".ui-state-disabled"), function(tab) {
                return lis.index(tab);
            });
            this._processTabs();
            if (options.active === false || !this.anchors.length) {
                options.active = false;
                this.active = $();
            } else if (this.active.length && !$.contains(this.tablist[0], this.active[0])) {
                if (this.tabs.length === options.disabled.length) {
                    options.active = false;
                    this.active = $();
                } else {
                    this._activate(this._findNextTab(Math.max(0, options.active - 1), false));
                }
            } else {
                options.active = this.tabs.index(this.active);
            }
            this._refresh();
        },
        _refresh: function() {
            this._setOptionDisabled(this.options.disabled);
            this._setupEvents(this.options.event);
            this._setupHeightStyle(this.options.heightStyle);
            this.tabs.not(this.active).attr({
                "aria-selected": "false",
                "aria-expanded": "false",
                tabIndex: -1
            });
            this.panels.not(this._getPanelForTab(this.active)).hide().attr({
                "aria-hidden": "true"
            });
            if (!this.active.length) {
                this.tabs.eq(0).attr("tabIndex", 0);
            } else {
                this.active.attr({
                    "aria-selected": "true",
                    "aria-expanded": "true",
                    tabIndex: 0
                });
                this._addClass(this.active, "ui-tabs-active", "ui-state-active");
                this._getPanelForTab(this.active).show().attr({
                    "aria-hidden": "false"
                });
            }
        },
        _processTabs: function() {
            var that = this, prevTabs = this.tabs, prevAnchors = this.anchors, prevPanels = this.panels;
            this.tablist = this._getList().attr("role", "tablist");
            this._addClass(this.tablist, "ui-tabs-nav", "ui-helper-reset ui-helper-clearfix ui-widget-header");
            this.tablist.on("mousedown" + this.eventNamespace, "> li", function(event) {
                if ($(this).is(".ui-state-disabled")) {
                    event.preventDefault();
                }
            }).on("focus" + this.eventNamespace, ".ui-tabs-anchor", function() {
                if ($(this).closest("li").is(".ui-state-disabled")) {
                    this.blur();
                }
            });
            this.tabs = this.tablist.find("> li:has(a[href])").attr({
                role: "tab",
                tabIndex: -1
            });
            this._addClass(this.tabs, "ui-tabs-tab", "ui-state-default");
            this.anchors = this.tabs.map(function() {
                return $("a", this)[0];
            }).attr({
                tabIndex: -1
            });
            this._addClass(this.anchors, "ui-tabs-anchor");
            this.panels = $();
            this.anchors.each(function(i, anchor) {
                var selector, panel, panelId, anchorId = $(anchor).uniqueId().attr("id"), tab = $(anchor).closest("li"), originalAriaControls = tab.attr("aria-controls");
                if (that._isLocal(anchor)) {
                    selector = anchor.hash;
                    panelId = selector.substring(1);
                    panel = that.element.find(that._sanitizeSelector(selector));
                } else {
                    panelId = tab.attr("aria-controls") || $({}).uniqueId()[0].id;
                    selector = "#" + panelId;
                    panel = that.element.find(selector);
                    if (!panel.length) {
                        panel = that._createPanel(panelId);
                        panel.insertAfter(that.panels[i - 1] || that.tablist);
                    }
                    panel.attr("aria-live", "polite");
                }
                if (panel.length) {
                    that.panels = that.panels.add(panel);
                }
                if (originalAriaControls) {
                    tab.data("ui-tabs-aria-controls", originalAriaControls);
                }
                tab.attr({
                    "aria-controls": panelId,
                    "aria-labelledby": anchorId
                });
                panel.attr("aria-labelledby", anchorId);
            });
            this.panels.attr("role", "tabpanel");
            this._addClass(this.panels, "ui-tabs-panel", "ui-widget-content");
            if (prevTabs) {
                this._off(prevTabs.not(this.tabs));
                this._off(prevAnchors.not(this.anchors));
                this._off(prevPanels.not(this.panels));
            }
        },
        _getList: function() {
            return this.tablist || this.element.find("ol, ul").eq(0);
        },
        _createPanel: function(id) {
            return $("<div>").attr("id", id).data("ui-tabs-destroy", true);
        },
        _setOptionDisabled: function(disabled) {
            var currentItem, li, i;
            if (Array.isArray(disabled)) {
                if (!disabled.length) {
                    disabled = false;
                } else if (disabled.length === this.anchors.length) {
                    disabled = true;
                }
            }
            for (i = 0; li = this.tabs[i]; i++) {
                currentItem = $(li);
                if (disabled === true || $.inArray(i, disabled) !== -1) {
                    currentItem.attr("aria-disabled", "true");
                    this._addClass(currentItem, null, "ui-state-disabled");
                } else {
                    currentItem.removeAttr("aria-disabled");
                    this._removeClass(currentItem, null, "ui-state-disabled");
                }
            }
            this.options.disabled = disabled;
            this._toggleClass(this.widget(), this.widgetFullName + "-disabled", null, disabled === true);
        },
        _setupEvents: function(event) {
            var events = {};
            if (event) {
                $.each(event.split(" "), function(index, eventName) {
                    events[eventName] = "_eventHandler";
                });
            }
            this._off(this.anchors.add(this.tabs).add(this.panels));
            this._on(true, this.anchors, {
                click: function(event) {
                    event.preventDefault();
                }
            });
            this._on(this.anchors, events);
            this._on(this.tabs, {
                keydown: "_tabKeydown"
            });
            this._on(this.panels, {
                keydown: "_panelKeydown"
            });
            this._focusable(this.tabs);
            this._hoverable(this.tabs);
        },
        _setupHeightStyle: function(heightStyle) {
            var maxHeight, parent = this.element.parent();
            if (heightStyle === "fill") {
                maxHeight = parent.height();
                maxHeight -= this.element.outerHeight() - this.element.height();
                this.element.siblings(":visible").each(function() {
                    var elem = $(this), position = elem.css("position");
                    if (position === "absolute" || position === "fixed") {
                        return;
                    }
                    maxHeight -= elem.outerHeight(true);
                });
                this.element.children().not(this.panels).each(function() {
                    maxHeight -= $(this).outerHeight(true);
                });
                this.panels.each(function() {
                    $(this).height(Math.max(0, maxHeight - $(this).innerHeight() + $(this).height()));
                }).css("overflow", "auto");
            } else if (heightStyle === "auto") {
                maxHeight = 0;
                this.panels.each(function() {
                    maxHeight = Math.max(maxHeight, $(this).height("").height());
                }).height(maxHeight);
            }
        },
        _eventHandler: function(event) {
            var options = this.options, active = this.active, anchor = $(event.currentTarget), tab = anchor.closest("li"), clickedIsActive = tab[0] === active[0], collapsing = clickedIsActive && options.collapsible, toShow = collapsing ? $() : this._getPanelForTab(tab), toHide = !active.length ? $() : this._getPanelForTab(active), eventData = {
                oldTab: active,
                oldPanel: toHide,
                newTab: collapsing ? $() : tab,
                newPanel: toShow
            };
            event.preventDefault();
            if (tab.hasClass("ui-state-disabled") || tab.hasClass("ui-tabs-loading") || this.running || clickedIsActive && !options.collapsible || this._trigger("beforeActivate", event, eventData) === false) {
                return;
            }
            options.active = collapsing ? false : this.tabs.index(tab);
            this.active = clickedIsActive ? $() : tab;
            if (this.xhr) {
                this.xhr.abort();
            }
            if (!toHide.length && !toShow.length) {
                $.error("jQuery UI Tabs: Mismatching fragment identifier.");
            }
            if (toShow.length) {
                this.load(this.tabs.index(tab), event);
            }
            this._toggle(event, eventData);
        },
        _toggle: function(event, eventData) {
            var that = this, toShow = eventData.newPanel, toHide = eventData.oldPanel;
            this.running = true;
            function complete() {
                that.running = false;
                that._trigger("activate", event, eventData);
            }
            function show() {
                that._addClass(eventData.newTab.closest("li"), "ui-tabs-active", "ui-state-active");
                if (toShow.length && that.options.show) {
                    that._show(toShow, that.options.show, complete);
                } else {
                    toShow.show();
                    complete();
                }
            }
            if (toHide.length && this.options.hide) {
                this._hide(toHide, this.options.hide, function() {
                    that._removeClass(eventData.oldTab.closest("li"), "ui-tabs-active", "ui-state-active");
                    show();
                });
            } else {
                this._removeClass(eventData.oldTab.closest("li"), "ui-tabs-active", "ui-state-active");
                toHide.hide();
                show();
            }
            toHide.attr("aria-hidden", "true");
            eventData.oldTab.attr({
                "aria-selected": "false",
                "aria-expanded": "false"
            });
            if (toShow.length && toHide.length) {
                eventData.oldTab.attr("tabIndex", -1);
            } else if (toShow.length) {
                this.tabs.filter(function() {
                    return $(this).attr("tabIndex") === 0;
                }).attr("tabIndex", -1);
            }
            toShow.attr("aria-hidden", "false");
            eventData.newTab.attr({
                "aria-selected": "true",
                "aria-expanded": "true",
                tabIndex: 0
            });
        },
        _activate: function(index) {
            var anchor, active = this._findActive(index);
            if (active[0] === this.active[0]) {
                return;
            }
            if (!active.length) {
                active = this.active;
            }
            anchor = active.find(".ui-tabs-anchor")[0];
            this._eventHandler({
                target: anchor,
                currentTarget: anchor,
                preventDefault: $.noop
            });
        },
        _findActive: function(index) {
            return index === false ? $() : this.tabs.eq(index);
        },
        _getIndex: function(index) {
            if (typeof index === "string") {
                index = this.anchors.index(this.anchors.filter("[href$='" + $.escapeSelector(index) + "']"));
            }
            return index;
        },
        _destroy: function() {
            if (this.xhr) {
                this.xhr.abort();
            }
            this.tablist.removeAttr("role").off(this.eventNamespace);
            this.anchors.removeAttr("role tabIndex").removeUniqueId();
            this.tabs.add(this.panels).each(function() {
                if ($.data(this, "ui-tabs-destroy")) {
                    $(this).remove();
                } else {
                    $(this).removeAttr("role tabIndex " + "aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded");
                }
            });
            this.tabs.each(function() {
                var li = $(this), prev = li.data("ui-tabs-aria-controls");
                if (prev) {
                    li.attr("aria-controls", prev).removeData("ui-tabs-aria-controls");
                } else {
                    li.removeAttr("aria-controls");
                }
            });
            this.panels.show();
            if (this.options.heightStyle !== "content") {
                this.panels.css("height", "");
            }
        },
        enable: function(index) {
            var disabled = this.options.disabled;
            if (disabled === false) {
                return;
            }
            if (index === undefined) {
                disabled = false;
            } else {
                index = this._getIndex(index);
                if (Array.isArray(disabled)) {
                    disabled = $.map(disabled, function(num) {
                        return num !== index ? num : null;
                    });
                } else {
                    disabled = $.map(this.tabs, function(li, num) {
                        return num !== index ? num : null;
                    });
                }
            }
            this._setOptionDisabled(disabled);
        },
        disable: function(index) {
            var disabled = this.options.disabled;
            if (disabled === true) {
                return;
            }
            if (index === undefined) {
                disabled = true;
            } else {
                index = this._getIndex(index);
                if ($.inArray(index, disabled) !== -1) {
                    return;
                }
                if (Array.isArray(disabled)) {
                    disabled = $.merge([ index ], disabled).sort();
                } else {
                    disabled = [ index ];
                }
            }
            this._setOptionDisabled(disabled);
        },
        load: function(index, event) {
            index = this._getIndex(index);
            var that = this, tab = this.tabs.eq(index), anchor = tab.find(".ui-tabs-anchor"), panel = this._getPanelForTab(tab), eventData = {
                tab: tab,
                panel: panel
            }, complete = function(jqXHR, status) {
                if (status === "abort") {
                    that.panels.stop(false, true);
                }
                that._removeClass(tab, "ui-tabs-loading");
                panel.removeAttr("aria-busy");
                if (jqXHR === that.xhr) {
                    delete that.xhr;
                }
            };
            if (this._isLocal(anchor[0])) {
                return;
            }
            this.xhr = $.ajax(this._ajaxSettings(anchor, event, eventData));
            if (this.xhr && this.xhr.statusText !== "canceled") {
                this._addClass(tab, "ui-tabs-loading");
                panel.attr("aria-busy", "true");
                this.xhr.done(function(response, status, jqXHR) {
                    setTimeout(function() {
                        panel.html(response);
                        that._trigger("load", event, eventData);
                        complete(jqXHR, status);
                    }, 1);
                }).fail(function(jqXHR, status) {
                    setTimeout(function() {
                        complete(jqXHR, status);
                    }, 1);
                });
            }
        },
        _ajaxSettings: function(anchor, event, eventData) {
            var that = this;
            return {
                url: anchor.attr("href").replace(/#.*$/, ""),
                beforeSend: function(jqXHR, settings) {
                    return that._trigger("beforeLoad", event, $.extend({
                        jqXHR: jqXHR,
                        ajaxSettings: settings
                    }, eventData));
                }
            };
        },
        _getPanelForTab: function(tab) {
            var id = $(tab).attr("aria-controls");
            return this.element.find(this._sanitizeSelector("#" + id));
        }
    });
    if ($.uiBackCompat !== false) {
        $.widget("ui.tabs", $.ui.tabs, {
            _processTabs: function() {
                this._superApply(arguments);
                this._addClass(this.tabs, "ui-tab");
            }
        });
    }
    var widgetsTabs = $.ui.tabs;
    $.widget("ui.tooltip", {
        version: "1.13.1",
        options: {
            classes: {
                "ui-tooltip": "ui-corner-all ui-widget-shadow"
            },
            content: function() {
                var title = $(this).attr("title");
                return $("<a>").text(title).html();
            },
            hide: true,
            items: "[title]:not([disabled])",
            position: {
                my: "left top+15",
                at: "left bottom",
                collision: "flipfit flip"
            },
            show: true,
            track: false,
            close: null,
            open: null
        },
        _addDescribedBy: function(elem, id) {
            var describedby = (elem.attr("aria-describedby") || "").split(/\s+/);
            describedby.push(id);
            elem.data("ui-tooltip-id", id).attr("aria-describedby", String.prototype.trim.call(describedby.join(" ")));
        },
        _removeDescribedBy: function(elem) {
            var id = elem.data("ui-tooltip-id"), describedby = (elem.attr("aria-describedby") || "").split(/\s+/), index = $.inArray(id, describedby);
            if (index !== -1) {
                describedby.splice(index, 1);
            }
            elem.removeData("ui-tooltip-id");
            describedby = String.prototype.trim.call(describedby.join(" "));
            if (describedby) {
                elem.attr("aria-describedby", describedby);
            } else {
                elem.removeAttr("aria-describedby");
            }
        },
        _create: function() {
            this._on({
                mouseover: "open",
                focusin: "open"
            });
            this.tooltips = {};
            this.parents = {};
            this.liveRegion = $("<div>").attr({
                role: "log",
                "aria-live": "assertive",
                "aria-relevant": "additions"
            }).appendTo(this.document[0].body);
            this._addClass(this.liveRegion, null, "ui-helper-hidden-accessible");
            this.disabledTitles = $([]);
        },
        _setOption: function(key, value) {
            var that = this;
            this._super(key, value);
            if (key === "content") {
                $.each(this.tooltips, function(id, tooltipData) {
                    that._updateContent(tooltipData.element);
                });
            }
        },
        _setOptionDisabled: function(value) {
            this[value ? "_disable" : "_enable"]();
        },
        _disable: function() {
            var that = this;
            $.each(this.tooltips, function(id, tooltipData) {
                var event = $.Event("blur");
                event.target = event.currentTarget = tooltipData.element[0];
                that.close(event, true);
            });
            this.disabledTitles = this.disabledTitles.add(this.element.find(this.options.items).addBack().filter(function() {
                var element = $(this);
                if (element.is("[title]")) {
                    return element.data("ui-tooltip-title", element.attr("title")).removeAttr("title");
                }
            }));
        },
        _enable: function() {
            this.disabledTitles.each(function() {
                var element = $(this);
                if (element.data("ui-tooltip-title")) {
                    element.attr("title", element.data("ui-tooltip-title"));
                }
            });
            this.disabledTitles = $([]);
        },
        open: function(event) {
            var that = this, target = $(event ? event.target : this.element).closest(this.options.items);
            if (!target.length || target.data("ui-tooltip-id")) {
                return;
            }
            if (target.attr("title")) {
                target.data("ui-tooltip-title", target.attr("title"));
            }
            target.data("ui-tooltip-open", true);
            if (event && event.type === "mouseover") {
                target.parents().each(function() {
                    var parent = $(this), blurEvent;
                    if (parent.data("ui-tooltip-open")) {
                        blurEvent = $.Event("blur");
                        blurEvent.target = blurEvent.currentTarget = this;
                        that.close(blurEvent, true);
                    }
                    if (parent.attr("title")) {
                        parent.uniqueId();
                        that.parents[this.id] = {
                            element: this,
                            title: parent.attr("title")
                        };
                        parent.attr("title", "");
                    }
                });
            }
            this._registerCloseHandlers(event, target);
            this._updateContent(target, event);
        },
        _updateContent: function(target, event) {
            var content, contentOption = this.options.content, that = this, eventType = event ? event.type : null;
            if (typeof contentOption === "string" || contentOption.nodeType || contentOption.jquery) {
                return this._open(event, target, contentOption);
            }
            content = contentOption.call(target[0], function(response) {
                that._delay(function() {
                    if (!target.data("ui-tooltip-open")) {
                        return;
                    }
                    if (event) {
                        event.type = eventType;
                    }
                    this._open(event, target, response);
                });
            });
            if (content) {
                this._open(event, target, content);
            }
        },
        _open: function(event, target, content) {
            var tooltipData, tooltip, delayedShow, a11yContent, positionOption = $.extend({}, this.options.position);
            if (!content) {
                return;
            }
            tooltipData = this._find(target);
            if (tooltipData) {
                tooltipData.tooltip.find(".ui-tooltip-content").html(content);
                return;
            }
            if (target.is("[title]")) {
                if (event && event.type === "mouseover") {
                    target.attr("title", "");
                } else {
                    target.removeAttr("title");
                }
            }
            tooltipData = this._tooltip(target);
            tooltip = tooltipData.tooltip;
            this._addDescribedBy(target, tooltip.attr("id"));
            tooltip.find(".ui-tooltip-content").html(content);
            this.liveRegion.children().hide();
            a11yContent = $("<div>").html(tooltip.find(".ui-tooltip-content").html());
            a11yContent.removeAttr("name").find("[name]").removeAttr("name");
            a11yContent.removeAttr("id").find("[id]").removeAttr("id");
            a11yContent.appendTo(this.liveRegion);
            function position(event) {
                positionOption.of = event;
                if (tooltip.is(":hidden")) {
                    return;
                }
                tooltip.position(positionOption);
            }
            if (this.options.track && event && /^mouse/.test(event.type)) {
                this._on(this.document, {
                    mousemove: position
                });
                position(event);
            } else {
                tooltip.position($.extend({
                    of: target
                }, this.options.position));
            }
            tooltip.hide();
            this._show(tooltip, this.options.show);
            if (this.options.track && this.options.show && this.options.show.delay) {
                delayedShow = this.delayedShow = setInterval(function() {
                    if (tooltip.is(":visible")) {
                        position(positionOption.of);
                        clearInterval(delayedShow);
                    }
                }, 13);
            }
            this._trigger("open", event, {
                tooltip: tooltip
            });
        },
        _registerCloseHandlers: function(event, target) {
            var events = {
                keyup: function(event) {
                    if (event.keyCode === $.ui.keyCode.ESCAPE) {
                        var fakeEvent = $.Event(event);
                        fakeEvent.currentTarget = target[0];
                        this.close(fakeEvent, true);
                    }
                }
            };
            if (target[0] !== this.element[0]) {
                events.remove = function() {
                    var targetElement = this._find(target);
                    if (targetElement) {
                        this._removeTooltip(targetElement.tooltip);
                    }
                };
            }
            if (!event || event.type === "mouseover") {
                events.mouseleave = "close";
            }
            if (!event || event.type === "focusin") {
                events.focusout = "close";
            }
            this._on(true, target, events);
        },
        close: function(event) {
            var tooltip, that = this, target = $(event ? event.currentTarget : this.element), tooltipData = this._find(target);
            if (!tooltipData) {
                target.removeData("ui-tooltip-open");
                return;
            }
            tooltip = tooltipData.tooltip;
            if (tooltipData.closing) {
                return;
            }
            clearInterval(this.delayedShow);
            if (target.data("ui-tooltip-title") && !target.attr("title")) {
                target.attr("title", target.data("ui-tooltip-title"));
            }
            this._removeDescribedBy(target);
            tooltipData.hiding = true;
            tooltip.stop(true);
            this._hide(tooltip, this.options.hide, function() {
                that._removeTooltip($(this));
            });
            target.removeData("ui-tooltip-open");
            this._off(target, "mouseleave focusout keyup");
            if (target[0] !== this.element[0]) {
                this._off(target, "remove");
            }
            this._off(this.document, "mousemove");
            if (event && event.type === "mouseleave") {
                $.each(this.parents, function(id, parent) {
                    $(parent.element).attr("title", parent.title);
                    delete that.parents[id];
                });
            }
            tooltipData.closing = true;
            this._trigger("close", event, {
                tooltip: tooltip
            });
            if (!tooltipData.hiding) {
                tooltipData.closing = false;
            }
        },
        _tooltip: function(element) {
            var tooltip = $("<div>").attr("role", "tooltip"), content = $("<div>").appendTo(tooltip), id = tooltip.uniqueId().attr("id");
            this._addClass(content, "ui-tooltip-content");
            this._addClass(tooltip, "ui-tooltip", "ui-widget ui-widget-content");
            tooltip.appendTo(this._appendTo(element));
            return this.tooltips[id] = {
                element: element,
                tooltip: tooltip
            };
        },
        _find: function(target) {
            var id = target.data("ui-tooltip-id");
            return id ? this.tooltips[id] : null;
        },
        _removeTooltip: function(tooltip) {
            clearInterval(this.delayedShow);
            tooltip.remove();
            delete this.tooltips[tooltip.attr("id")];
        },
        _appendTo: function(target) {
            var element = target.closest(".ui-front, dialog");
            if (!element.length) {
                element = this.document[0].body;
            }
            return element;
        },
        _destroy: function() {
            var that = this;
            $.each(this.tooltips, function(id, tooltipData) {
                var event = $.Event("blur"), element = tooltipData.element;
                event.target = event.currentTarget = element[0];
                that.close(event, true);
                $("#" + id).remove();
                if (element.data("ui-tooltip-title")) {
                    if (!element.attr("title")) {
                        element.attr("title", element.data("ui-tooltip-title"));
                    }
                    element.removeData("ui-tooltip-title");
                }
            });
            this.liveRegion.remove();
        }
    });
    if ($.uiBackCompat !== false) {
        $.widget("ui.tooltip", $.ui.tooltip, {
            options: {
                tooltipClass: null
            },
            _tooltip: function() {
                var tooltipData = this._superApply(arguments);
                if (this.options.tooltipClass) {
                    tooltipData.tooltip.addClass(this.options.tooltipClass);
                }
                return tooltipData;
            }
        });
    }
    var widgetsTooltip = $.ui.tooltip;
});

(function() {
    var undefined;
    var VERSION = "4.17.21";
    var LARGE_ARRAY_SIZE = 200;
    var CORE_ERROR_TEXT = "Unsupported core-js use. Try https://npms.io/search?q=ponyfill.", FUNC_ERROR_TEXT = "Expected a function", INVALID_TEMPL_VAR_ERROR_TEXT = "Invalid `variable` option passed into `_.template`";
    var HASH_UNDEFINED = "__lodash_hash_undefined__";
    var MAX_MEMOIZE_SIZE = 500;
    var PLACEHOLDER = "__lodash_placeholder__";
    var CLONE_DEEP_FLAG = 1, CLONE_FLAT_FLAG = 2, CLONE_SYMBOLS_FLAG = 4;
    var COMPARE_PARTIAL_FLAG = 1, COMPARE_UNORDERED_FLAG = 2;
    var WRAP_BIND_FLAG = 1, WRAP_BIND_KEY_FLAG = 2, WRAP_CURRY_BOUND_FLAG = 4, WRAP_CURRY_FLAG = 8, WRAP_CURRY_RIGHT_FLAG = 16, WRAP_PARTIAL_FLAG = 32, WRAP_PARTIAL_RIGHT_FLAG = 64, WRAP_ARY_FLAG = 128, WRAP_REARG_FLAG = 256, WRAP_FLIP_FLAG = 512;
    var DEFAULT_TRUNC_LENGTH = 30, DEFAULT_TRUNC_OMISSION = "...";
    var HOT_COUNT = 800, HOT_SPAN = 16;
    var LAZY_FILTER_FLAG = 1, LAZY_MAP_FLAG = 2, LAZY_WHILE_FLAG = 3;
    var INFINITY = 1 / 0, MAX_SAFE_INTEGER = 9007199254740991, MAX_INTEGER = 17976931348623157e292, NAN = 0 / 0;
    var MAX_ARRAY_LENGTH = 4294967295, MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1, HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;
    var wrapFlags = [ [ "ary", WRAP_ARY_FLAG ], [ "bind", WRAP_BIND_FLAG ], [ "bindKey", WRAP_BIND_KEY_FLAG ], [ "curry", WRAP_CURRY_FLAG ], [ "curryRight", WRAP_CURRY_RIGHT_FLAG ], [ "flip", WRAP_FLIP_FLAG ], [ "partial", WRAP_PARTIAL_FLAG ], [ "partialRight", WRAP_PARTIAL_RIGHT_FLAG ], [ "rearg", WRAP_REARG_FLAG ] ];
    var argsTag = "[object Arguments]", arrayTag = "[object Array]", asyncTag = "[object AsyncFunction]", boolTag = "[object Boolean]", dateTag = "[object Date]", domExcTag = "[object DOMException]", errorTag = "[object Error]", funcTag = "[object Function]", genTag = "[object GeneratorFunction]", mapTag = "[object Map]", numberTag = "[object Number]", nullTag = "[object Null]", objectTag = "[object Object]", promiseTag = "[object Promise]", proxyTag = "[object Proxy]", regexpTag = "[object RegExp]", setTag = "[object Set]", stringTag = "[object String]", symbolTag = "[object Symbol]", undefinedTag = "[object Undefined]", weakMapTag = "[object WeakMap]", weakSetTag = "[object WeakSet]";
    var arrayBufferTag = "[object ArrayBuffer]", dataViewTag = "[object DataView]", float32Tag = "[object Float32Array]", float64Tag = "[object Float64Array]", int8Tag = "[object Int8Array]", int16Tag = "[object Int16Array]", int32Tag = "[object Int32Array]", uint8Tag = "[object Uint8Array]", uint8ClampedTag = "[object Uint8ClampedArray]", uint16Tag = "[object Uint16Array]", uint32Tag = "[object Uint32Array]";
    var reEmptyStringLeading = /\b__p \+= '';/g, reEmptyStringMiddle = /\b(__p \+=) '' \+/g, reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
    var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g, reUnescapedHtml = /[&<>"']/g, reHasEscapedHtml = RegExp(reEscapedHtml.source), reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
    var reEscape = /<%-([\s\S]+?)%>/g, reEvaluate = /<%([\s\S]+?)%>/g, reInterpolate = /<%=([\s\S]+?)%>/g;
    var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/, reIsPlainProp = /^\w*$/, rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
    var reRegExpChar = /[\\^$.*+?()[\]{}|]/g, reHasRegExpChar = RegExp(reRegExpChar.source);
    var reTrimStart = /^\s+/;
    var reWhitespace = /\s/;
    var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/, reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/, reSplitDetails = /,? & /;
    var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
    var reForbiddenIdentifierChars = /[()=,{}\[\]\/\s]/;
    var reEscapeChar = /\\(\\)?/g;
    var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
    var reFlags = /\w*$/;
    var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
    var reIsBinary = /^0b[01]+$/i;
    var reIsHostCtor = /^\[object .+?Constructor\]$/;
    var reIsOctal = /^0o[0-7]+$/i;
    var reIsUint = /^(?:0|[1-9]\d*)$/;
    var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g;
    var reNoMatch = /($^)/;
    var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
    var rsAstralRange = "\\ud800-\\udfff", rsComboMarksRange = "\\u0300-\\u036f", reComboHalfMarksRange = "\\ufe20-\\ufe2f", rsComboSymbolsRange = "\\u20d0-\\u20ff", rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange, rsDingbatRange = "\\u2700-\\u27bf", rsLowerRange = "a-z\\xdf-\\xf6\\xf8-\\xff", rsMathOpRange = "\\xac\\xb1\\xd7\\xf7", rsNonCharRange = "\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf", rsPunctuationRange = "\\u2000-\\u206f", rsSpaceRange = " \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000", rsUpperRange = "A-Z\\xc0-\\xd6\\xd8-\\xde", rsVarRange = "\\ufe0e\\ufe0f", rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;
    var rsApos = "['’]", rsAstral = "[" + rsAstralRange + "]", rsBreak = "[" + rsBreakRange + "]", rsCombo = "[" + rsComboRange + "]", rsDigits = "\\d+", rsDingbat = "[" + rsDingbatRange + "]", rsLower = "[" + rsLowerRange + "]", rsMisc = "[^" + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + "]", rsFitz = "\\ud83c[\\udffb-\\udfff]", rsModifier = "(?:" + rsCombo + "|" + rsFitz + ")", rsNonAstral = "[^" + rsAstralRange + "]", rsRegional = "(?:\\ud83c[\\udde6-\\uddff]){2}", rsSurrPair = "[\\ud800-\\udbff][\\udc00-\\udfff]", rsUpper = "[" + rsUpperRange + "]", rsZWJ = "\\u200d";
    var rsMiscLower = "(?:" + rsLower + "|" + rsMisc + ")", rsMiscUpper = "(?:" + rsUpper + "|" + rsMisc + ")", rsOptContrLower = "(?:" + rsApos + "(?:d|ll|m|re|s|t|ve))?", rsOptContrUpper = "(?:" + rsApos + "(?:D|LL|M|RE|S|T|VE))?", reOptMod = rsModifier + "?", rsOptVar = "[" + rsVarRange + "]?", rsOptJoin = "(?:" + rsZWJ + "(?:" + [ rsNonAstral, rsRegional, rsSurrPair ].join("|") + ")" + rsOptVar + reOptMod + ")*", rsOrdLower = "\\d*(?:1st|2nd|3rd|(?![123])\\dth)(?=\\b|[A-Z_])", rsOrdUpper = "\\d*(?:1ST|2ND|3RD|(?![123])\\dTH)(?=\\b|[a-z_])", rsSeq = rsOptVar + reOptMod + rsOptJoin, rsEmoji = "(?:" + [ rsDingbat, rsRegional, rsSurrPair ].join("|") + ")" + rsSeq, rsSymbol = "(?:" + [ rsNonAstral + rsCombo + "?", rsCombo, rsRegional, rsSurrPair, rsAstral ].join("|") + ")";
    var reApos = RegExp(rsApos, "g");
    var reComboMark = RegExp(rsCombo, "g");
    var reUnicode = RegExp(rsFitz + "(?=" + rsFitz + ")|" + rsSymbol + rsSeq, "g");
    var reUnicodeWord = RegExp([ rsUpper + "?" + rsLower + "+" + rsOptContrLower + "(?=" + [ rsBreak, rsUpper, "$" ].join("|") + ")", rsMiscUpper + "+" + rsOptContrUpper + "(?=" + [ rsBreak, rsUpper + rsMiscLower, "$" ].join("|") + ")", rsUpper + "?" + rsMiscLower + "+" + rsOptContrLower, rsUpper + "+" + rsOptContrUpper, rsOrdUpper, rsOrdLower, rsDigits, rsEmoji ].join("|"), "g");
    var reHasUnicode = RegExp("[" + rsZWJ + rsAstralRange + rsComboRange + rsVarRange + "]");
    var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;
    var contextProps = [ "Array", "Buffer", "DataView", "Date", "Error", "Float32Array", "Float64Array", "Function", "Int8Array", "Int16Array", "Int32Array", "Map", "Math", "Object", "Promise", "RegExp", "Set", "String", "Symbol", "TypeError", "Uint8Array", "Uint8ClampedArray", "Uint16Array", "Uint32Array", "WeakMap", "_", "clearTimeout", "isFinite", "parseInt", "setTimeout" ];
    var templateCounter = -1;
    var typedArrayTags = {};
    typedArrayTags[float32Tag] = typedArrayTags[float64Tag] = typedArrayTags[int8Tag] = typedArrayTags[int16Tag] = typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] = typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] = typedArrayTags[uint32Tag] = true;
    typedArrayTags[argsTag] = typedArrayTags[arrayTag] = typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] = typedArrayTags[dataViewTag] = typedArrayTags[dateTag] = typedArrayTags[errorTag] = typedArrayTags[funcTag] = typedArrayTags[mapTag] = typedArrayTags[numberTag] = typedArrayTags[objectTag] = typedArrayTags[regexpTag] = typedArrayTags[setTag] = typedArrayTags[stringTag] = typedArrayTags[weakMapTag] = false;
    var cloneableTags = {};
    cloneableTags[argsTag] = cloneableTags[arrayTag] = cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] = cloneableTags[boolTag] = cloneableTags[dateTag] = cloneableTags[float32Tag] = cloneableTags[float64Tag] = cloneableTags[int8Tag] = cloneableTags[int16Tag] = cloneableTags[int32Tag] = cloneableTags[mapTag] = cloneableTags[numberTag] = cloneableTags[objectTag] = cloneableTags[regexpTag] = cloneableTags[setTag] = cloneableTags[stringTag] = cloneableTags[symbolTag] = cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] = cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
    cloneableTags[errorTag] = cloneableTags[funcTag] = cloneableTags[weakMapTag] = false;
    var deburredLetters = {
        "À": "A",
        "Á": "A",
        "Â": "A",
        "Ã": "A",
        "Ä": "A",
        "Å": "A",
        "à": "a",
        "á": "a",
        "â": "a",
        "ã": "a",
        "ä": "a",
        "å": "a",
        "Ç": "C",
        "ç": "c",
        "Ð": "D",
        "ð": "d",
        "È": "E",
        "É": "E",
        "Ê": "E",
        "Ë": "E",
        "è": "e",
        "é": "e",
        "ê": "e",
        "ë": "e",
        "Ì": "I",
        "Í": "I",
        "Î": "I",
        "Ï": "I",
        "ì": "i",
        "í": "i",
        "î": "i",
        "ï": "i",
        "Ñ": "N",
        "ñ": "n",
        "Ò": "O",
        "Ó": "O",
        "Ô": "O",
        "Õ": "O",
        "Ö": "O",
        "Ø": "O",
        "ò": "o",
        "ó": "o",
        "ô": "o",
        "õ": "o",
        "ö": "o",
        "ø": "o",
        "Ù": "U",
        "Ú": "U",
        "Û": "U",
        "Ü": "U",
        "ù": "u",
        "ú": "u",
        "û": "u",
        "ü": "u",
        "Ý": "Y",
        "ý": "y",
        "ÿ": "y",
        "Æ": "Ae",
        "æ": "ae",
        "Þ": "Th",
        "þ": "th",
        "ß": "ss",
        "Ā": "A",
        "Ă": "A",
        "Ą": "A",
        "ā": "a",
        "ă": "a",
        "ą": "a",
        "Ć": "C",
        "Ĉ": "C",
        "Ċ": "C",
        "Č": "C",
        "ć": "c",
        "ĉ": "c",
        "ċ": "c",
        "č": "c",
        "Ď": "D",
        "Đ": "D",
        "ď": "d",
        "đ": "d",
        "Ē": "E",
        "Ĕ": "E",
        "Ė": "E",
        "Ę": "E",
        "Ě": "E",
        "ē": "e",
        "ĕ": "e",
        "ė": "e",
        "ę": "e",
        "ě": "e",
        "Ĝ": "G",
        "Ğ": "G",
        "Ġ": "G",
        "Ģ": "G",
        "ĝ": "g",
        "ğ": "g",
        "ġ": "g",
        "ģ": "g",
        "Ĥ": "H",
        "Ħ": "H",
        "ĥ": "h",
        "ħ": "h",
        "Ĩ": "I",
        "Ī": "I",
        "Ĭ": "I",
        "Į": "I",
        "İ": "I",
        "ĩ": "i",
        "ī": "i",
        "ĭ": "i",
        "į": "i",
        "ı": "i",
        "Ĵ": "J",
        "ĵ": "j",
        "Ķ": "K",
        "ķ": "k",
        "ĸ": "k",
        "Ĺ": "L",
        "Ļ": "L",
        "Ľ": "L",
        "Ŀ": "L",
        "Ł": "L",
        "ĺ": "l",
        "ļ": "l",
        "ľ": "l",
        "ŀ": "l",
        "ł": "l",
        "Ń": "N",
        "Ņ": "N",
        "Ň": "N",
        "Ŋ": "N",
        "ń": "n",
        "ņ": "n",
        "ň": "n",
        "ŋ": "n",
        "Ō": "O",
        "Ŏ": "O",
        "Ő": "O",
        "ō": "o",
        "ŏ": "o",
        "ő": "o",
        "Ŕ": "R",
        "Ŗ": "R",
        "Ř": "R",
        "ŕ": "r",
        "ŗ": "r",
        "ř": "r",
        "Ś": "S",
        "Ŝ": "S",
        "Ş": "S",
        "Š": "S",
        "ś": "s",
        "ŝ": "s",
        "ş": "s",
        "š": "s",
        "Ţ": "T",
        "Ť": "T",
        "Ŧ": "T",
        "ţ": "t",
        "ť": "t",
        "ŧ": "t",
        "Ũ": "U",
        "Ū": "U",
        "Ŭ": "U",
        "Ů": "U",
        "Ű": "U",
        "Ų": "U",
        "ũ": "u",
        "ū": "u",
        "ŭ": "u",
        "ů": "u",
        "ű": "u",
        "ų": "u",
        "Ŵ": "W",
        "ŵ": "w",
        "Ŷ": "Y",
        "ŷ": "y",
        "Ÿ": "Y",
        "Ź": "Z",
        "Ż": "Z",
        "Ž": "Z",
        "ź": "z",
        "ż": "z",
        "ž": "z",
        "Ĳ": "IJ",
        "ĳ": "ij",
        "Œ": "Oe",
        "œ": "oe",
        "ŉ": "'n",
        "ſ": "s"
    };
    var htmlEscapes = {
        "&": "&amp;",
        "<": "&lt;",
        ">": "&gt;",
        '"': "&quot;",
        "'": "&#39;"
    };
    var htmlUnescapes = {
        "&amp;": "&",
        "&lt;": "<",
        "&gt;": ">",
        "&quot;": '"',
        "&#39;": "'"
    };
    var stringEscapes = {
        "\\": "\\",
        "'": "'",
        "\n": "n",
        "\r": "r",
        "\u2028": "u2028",
        "\u2029": "u2029"
    };
    var freeParseFloat = parseFloat, freeParseInt = parseInt;
    var freeGlobal = typeof global == "object" && global && global.Object === Object && global;
    var freeSelf = typeof self == "object" && self && self.Object === Object && self;
    var root = freeGlobal || freeSelf || Function("return this")();
    var freeExports = typeof exports == "object" && exports && !exports.nodeType && exports;
    var freeModule = freeExports && typeof module == "object" && module && !module.nodeType && module;
    var moduleExports = freeModule && freeModule.exports === freeExports;
    var freeProcess = moduleExports && freeGlobal.process;
    var nodeUtil = function() {
        try {
            var types = freeModule && freeModule.require && freeModule.require("util").types;
            if (types) {
                return types;
            }
            return freeProcess && freeProcess.binding && freeProcess.binding("util");
        } catch (e) {}
    }();
    var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer, nodeIsDate = nodeUtil && nodeUtil.isDate, nodeIsMap = nodeUtil && nodeUtil.isMap, nodeIsRegExp = nodeUtil && nodeUtil.isRegExp, nodeIsSet = nodeUtil && nodeUtil.isSet, nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
    function apply(func, thisArg, args) {
        switch (args.length) {
          case 0:
            return func.call(thisArg);

          case 1:
            return func.call(thisArg, args[0]);

          case 2:
            return func.call(thisArg, args[0], args[1]);

          case 3:
            return func.call(thisArg, args[0], args[1], args[2]);
        }
        return func.apply(thisArg, args);
    }
    function arrayAggregator(array, setter, iteratee, accumulator) {
        var index = -1, length = array == null ? 0 : array.length;
        while (++index < length) {
            var value = array[index];
            setter(accumulator, value, iteratee(value), array);
        }
        return accumulator;
    }
    function arrayEach(array, iteratee) {
        var index = -1, length = array == null ? 0 : array.length;
        while (++index < length) {
            if (iteratee(array[index], index, array) === false) {
                break;
            }
        }
        return array;
    }
    function arrayEachRight(array, iteratee) {
        var length = array == null ? 0 : array.length;
        while (length--) {
            if (iteratee(array[length], length, array) === false) {
                break;
            }
        }
        return array;
    }
    function arrayEvery(array, predicate) {
        var index = -1, length = array == null ? 0 : array.length;
        while (++index < length) {
            if (!predicate(array[index], index, array)) {
                return false;
            }
        }
        return true;
    }
    function arrayFilter(array, predicate) {
        var index = -1, length = array == null ? 0 : array.length, resIndex = 0, result = [];
        while (++index < length) {
            var value = array[index];
            if (predicate(value, index, array)) {
                result[resIndex++] = value;
            }
        }
        return result;
    }
    function arrayIncludes(array, value) {
        var length = array == null ? 0 : array.length;
        return !!length && baseIndexOf(array, value, 0) > -1;
    }
    function arrayIncludesWith(array, value, comparator) {
        var index = -1, length = array == null ? 0 : array.length;
        while (++index < length) {
            if (comparator(value, array[index])) {
                return true;
            }
        }
        return false;
    }
    function arrayMap(array, iteratee) {
        var index = -1, length = array == null ? 0 : array.length, result = Array(length);
        while (++index < length) {
            result[index] = iteratee(array[index], index, array);
        }
        return result;
    }
    function arrayPush(array, values) {
        var index = -1, length = values.length, offset = array.length;
        while (++index < length) {
            array[offset + index] = values[index];
        }
        return array;
    }
    function arrayReduce(array, iteratee, accumulator, initAccum) {
        var index = -1, length = array == null ? 0 : array.length;
        if (initAccum && length) {
            accumulator = array[++index];
        }
        while (++index < length) {
            accumulator = iteratee(accumulator, array[index], index, array);
        }
        return accumulator;
    }
    function arrayReduceRight(array, iteratee, accumulator, initAccum) {
        var length = array == null ? 0 : array.length;
        if (initAccum && length) {
            accumulator = array[--length];
        }
        while (length--) {
            accumulator = iteratee(accumulator, array[length], length, array);
        }
        return accumulator;
    }
    function arraySome(array, predicate) {
        var index = -1, length = array == null ? 0 : array.length;
        while (++index < length) {
            if (predicate(array[index], index, array)) {
                return true;
            }
        }
        return false;
    }
    var asciiSize = baseProperty("length");
    function asciiToArray(string) {
        return string.split("");
    }
    function asciiWords(string) {
        return string.match(reAsciiWord) || [];
    }
    function baseFindKey(collection, predicate, eachFunc) {
        var result;
        eachFunc(collection, function(value, key, collection) {
            if (predicate(value, key, collection)) {
                result = key;
                return false;
            }
        });
        return result;
    }
    function baseFindIndex(array, predicate, fromIndex, fromRight) {
        var length = array.length, index = fromIndex + (fromRight ? 1 : -1);
        while (fromRight ? index-- : ++index < length) {
            if (predicate(array[index], index, array)) {
                return index;
            }
        }
        return -1;
    }
    function baseIndexOf(array, value, fromIndex) {
        return value === value ? strictIndexOf(array, value, fromIndex) : baseFindIndex(array, baseIsNaN, fromIndex);
    }
    function baseIndexOfWith(array, value, fromIndex, comparator) {
        var index = fromIndex - 1, length = array.length;
        while (++index < length) {
            if (comparator(array[index], value)) {
                return index;
            }
        }
        return -1;
    }
    function baseIsNaN(value) {
        return value !== value;
    }
    function baseMean(array, iteratee) {
        var length = array == null ? 0 : array.length;
        return length ? baseSum(array, iteratee) / length : NAN;
    }
    function baseProperty(key) {
        return function(object) {
            return object == null ? undefined : object[key];
        };
    }
    function basePropertyOf(object) {
        return function(key) {
            return object == null ? undefined : object[key];
        };
    }
    function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) {
        eachFunc(collection, function(value, index, collection) {
            accumulator = initAccum ? (initAccum = false, value) : iteratee(accumulator, value, index, collection);
        });
        return accumulator;
    }
    function baseSortBy(array, comparer) {
        var length = array.length;
        array.sort(comparer);
        while (length--) {
            array[length] = array[length].value;
        }
        return array;
    }
    function baseSum(array, iteratee) {
        var result, index = -1, length = array.length;
        while (++index < length) {
            var current = iteratee(array[index]);
            if (current !== undefined) {
                result = result === undefined ? current : result + current;
            }
        }
        return result;
    }
    function baseTimes(n, iteratee) {
        var index = -1, result = Array(n);
        while (++index < n) {
            result[index] = iteratee(index);
        }
        return result;
    }
    function baseToPairs(object, props) {
        return arrayMap(props, function(key) {
            return [ key, object[key] ];
        });
    }
    function baseTrim(string) {
        return string ? string.slice(0, trimmedEndIndex(string) + 1).replace(reTrimStart, "") : string;
    }
    function baseUnary(func) {
        return function(value) {
            return func(value);
        };
    }
    function baseValues(object, props) {
        return arrayMap(props, function(key) {
            return object[key];
        });
    }
    function cacheHas(cache, key) {
        return cache.has(key);
    }
    function charsStartIndex(strSymbols, chrSymbols) {
        var index = -1, length = strSymbols.length;
        while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
        return index;
    }
    function charsEndIndex(strSymbols, chrSymbols) {
        var index = strSymbols.length;
        while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
        return index;
    }
    function countHolders(array, placeholder) {
        var length = array.length, result = 0;
        while (length--) {
            if (array[length] === placeholder) {
                ++result;
            }
        }
        return result;
    }
    var deburrLetter = basePropertyOf(deburredLetters);
    var escapeHtmlChar = basePropertyOf(htmlEscapes);
    function escapeStringChar(chr) {
        return "\\" + stringEscapes[chr];
    }
    function getValue(object, key) {
        return object == null ? undefined : object[key];
    }
    function hasUnicode(string) {
        return reHasUnicode.test(string);
    }
    function hasUnicodeWord(string) {
        return reHasUnicodeWord.test(string);
    }
    function iteratorToArray(iterator) {
        var data, result = [];
        while (!(data = iterator.next()).done) {
            result.push(data.value);
        }
        return result;
    }
    function mapToArray(map) {
        var index = -1, result = Array(map.size);
        map.forEach(function(value, key) {
            result[++index] = [ key, value ];
        });
        return result;
    }
    function overArg(func, transform) {
        return function(arg) {
            return func(transform(arg));
        };
    }
    function replaceHolders(array, placeholder) {
        var index = -1, length = array.length, resIndex = 0, result = [];
        while (++index < length) {
            var value = array[index];
            if (value === placeholder || value === PLACEHOLDER) {
                array[index] = PLACEHOLDER;
                result[resIndex++] = index;
            }
        }
        return result;
    }
    function setToArray(set) {
        var index = -1, result = Array(set.size);
        set.forEach(function(value) {
            result[++index] = value;
        });
        return result;
    }
    function setToPairs(set) {
        var index = -1, result = Array(set.size);
        set.forEach(function(value) {
            result[++index] = [ value, value ];
        });
        return result;
    }
    function strictIndexOf(array, value, fromIndex) {
        var index = fromIndex - 1, length = array.length;
        while (++index < length) {
            if (array[index] === value) {
                return index;
            }
        }
        return -1;
    }
    function strictLastIndexOf(array, value, fromIndex) {
        var index = fromIndex + 1;
        while (index--) {
            if (array[index] === value) {
                return index;
            }
        }
        return index;
    }
    function stringSize(string) {
        return hasUnicode(string) ? unicodeSize(string) : asciiSize(string);
    }
    function stringToArray(string) {
        return hasUnicode(string) ? unicodeToArray(string) : asciiToArray(string);
    }
    function trimmedEndIndex(string) {
        var index = string.length;
        while (index-- && reWhitespace.test(string.charAt(index))) {}
        return index;
    }
    var unescapeHtmlChar = basePropertyOf(htmlUnescapes);
    function unicodeSize(string) {
        var result = reUnicode.lastIndex = 0;
        while (reUnicode.test(string)) {
            ++result;
        }
        return result;
    }
    function unicodeToArray(string) {
        return string.match(reUnicode) || [];
    }
    function unicodeWords(string) {
        return string.match(reUnicodeWord) || [];
    }
    var runInContext = function runInContext(context) {
        context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps));
        var Array = context.Array, Date = context.Date, Error = context.Error, Function = context.Function, Math = context.Math, Object = context.Object, RegExp = context.RegExp, String = context.String, TypeError = context.TypeError;
        var arrayProto = Array.prototype, funcProto = Function.prototype, objectProto = Object.prototype;
        var coreJsData = context["__core-js_shared__"];
        var funcToString = funcProto.toString;
        var hasOwnProperty = objectProto.hasOwnProperty;
        var idCounter = 0;
        var maskSrcKey = function() {
            var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || "");
            return uid ? "Symbol(src)_1." + uid : "";
        }();
        var nativeObjectToString = objectProto.toString;
        var objectCtorString = funcToString.call(Object);
        var oldDash = root._;
        var reIsNative = RegExp("^" + funcToString.call(hasOwnProperty).replace(reRegExpChar, "\\$&").replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, "$1.*?") + "$");
        var Buffer = moduleExports ? context.Buffer : undefined, Symbol = context.Symbol, Uint8Array = context.Uint8Array, allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined, getPrototype = overArg(Object.getPrototypeOf, Object), objectCreate = Object.create, propertyIsEnumerable = objectProto.propertyIsEnumerable, splice = arrayProto.splice, spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined, symIterator = Symbol ? Symbol.iterator : undefined, symToStringTag = Symbol ? Symbol.toStringTag : undefined;
        var defineProperty = function() {
            try {
                var func = getNative(Object, "defineProperty");
                func({}, "", {});
                return func;
            } catch (e) {}
        }();
        var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout, ctxNow = Date && Date.now !== root.Date.now && Date.now, ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout;
        var nativeCeil = Math.ceil, nativeFloor = Math.floor, nativeGetSymbols = Object.getOwnPropertySymbols, nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined, nativeIsFinite = context.isFinite, nativeJoin = arrayProto.join, nativeKeys = overArg(Object.keys, Object), nativeMax = Math.max, nativeMin = Math.min, nativeNow = Date.now, nativeParseInt = context.parseInt, nativeRandom = Math.random, nativeReverse = arrayProto.reverse;
        var DataView = getNative(context, "DataView"), Map = getNative(context, "Map"), Promise = getNative(context, "Promise"), Set = getNative(context, "Set"), WeakMap = getNative(context, "WeakMap"), nativeCreate = getNative(Object, "create");
        var metaMap = WeakMap && new WeakMap();
        var realNames = {};
        var dataViewCtorString = toSource(DataView), mapCtorString = toSource(Map), promiseCtorString = toSource(Promise), setCtorString = toSource(Set), weakMapCtorString = toSource(WeakMap);
        var symbolProto = Symbol ? Symbol.prototype : undefined, symbolValueOf = symbolProto ? symbolProto.valueOf : undefined, symbolToString = symbolProto ? symbolProto.toString : undefined;
        function lodash(value) {
            if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
                if (value instanceof LodashWrapper) {
                    return value;
                }
                if (hasOwnProperty.call(value, "__wrapped__")) {
                    return wrapperClone(value);
                }
            }
            return new LodashWrapper(value);
        }
        var baseCreate = function() {
            function object() {}
            return function(proto) {
                if (!isObject(proto)) {
                    return {};
                }
                if (objectCreate) {
                    return objectCreate(proto);
                }
                object.prototype = proto;
                var result = new object();
                object.prototype = undefined;
                return result;
            };
        }();
        function baseLodash() {}
        function LodashWrapper(value, chainAll) {
            this.__wrapped__ = value;
            this.__actions__ = [];
            this.__chain__ = !!chainAll;
            this.__index__ = 0;
            this.__values__ = undefined;
        }
        lodash.templateSettings = {
            escape: reEscape,
            evaluate: reEvaluate,
            interpolate: reInterpolate,
            variable: "",
            imports: {
                _: lodash
            }
        };
        lodash.prototype = baseLodash.prototype;
        lodash.prototype.constructor = lodash;
        LodashWrapper.prototype = baseCreate(baseLodash.prototype);
        LodashWrapper.prototype.constructor = LodashWrapper;
        function LazyWrapper(value) {
            this.__wrapped__ = value;
            this.__actions__ = [];
            this.__dir__ = 1;
            this.__filtered__ = false;
            this.__iteratees__ = [];
            this.__takeCount__ = MAX_ARRAY_LENGTH;
            this.__views__ = [];
        }
        function lazyClone() {
            var result = new LazyWrapper(this.__wrapped__);
            result.__actions__ = copyArray(this.__actions__);
            result.__dir__ = this.__dir__;
            result.__filtered__ = this.__filtered__;
            result.__iteratees__ = copyArray(this.__iteratees__);
            result.__takeCount__ = this.__takeCount__;
            result.__views__ = copyArray(this.__views__);
            return result;
        }
        function lazyReverse() {
            if (this.__filtered__) {
                var result = new LazyWrapper(this);
                result.__dir__ = -1;
                result.__filtered__ = true;
            } else {
                result = this.clone();
                result.__dir__ *= -1;
            }
            return result;
        }
        function lazyValue() {
            var array = this.__wrapped__.value(), dir = this.__dir__, isArr = isArray(array), isRight = dir < 0, arrLength = isArr ? array.length : 0, view = getView(0, arrLength, this.__views__), start = view.start, end = view.end, length = end - start, index = isRight ? end : start - 1, iteratees = this.__iteratees__, iterLength = iteratees.length, resIndex = 0, takeCount = nativeMin(length, this.__takeCount__);
            if (!isArr || !isRight && arrLength == length && takeCount == length) {
                return baseWrapperValue(array, this.__actions__);
            }
            var result = [];
            outer: while (length-- && resIndex < takeCount) {
                index += dir;
                var iterIndex = -1, value = array[index];
                while (++iterIndex < iterLength) {
                    var data = iteratees[iterIndex], iteratee = data.iteratee, type = data.type, computed = iteratee(value);
                    if (type == LAZY_MAP_FLAG) {
                        value = computed;
                    } else if (!computed) {
                        if (type == LAZY_FILTER_FLAG) {
                            continue outer;
                        } else {
                            break outer;
                        }
                    }
                }
                result[resIndex++] = value;
            }
            return result;
        }
        LazyWrapper.prototype = baseCreate(baseLodash.prototype);
        LazyWrapper.prototype.constructor = LazyWrapper;
        function Hash(entries) {
            var index = -1, length = entries == null ? 0 : entries.length;
            this.clear();
            while (++index < length) {
                var entry = entries[index];
                this.set(entry[0], entry[1]);
            }
        }
        function hashClear() {
            this.__data__ = nativeCreate ? nativeCreate(null) : {};
            this.size = 0;
        }
        function hashDelete(key) {
            var result = this.has(key) && delete this.__data__[key];
            this.size -= result ? 1 : 0;
            return result;
        }
        function hashGet(key) {
            var data = this.__data__;
            if (nativeCreate) {
                var result = data[key];
                return result === HASH_UNDEFINED ? undefined : result;
            }
            return hasOwnProperty.call(data, key) ? data[key] : undefined;
        }
        function hashHas(key) {
            var data = this.__data__;
            return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key);
        }
        function hashSet(key, value) {
            var data = this.__data__;
            this.size += this.has(key) ? 0 : 1;
            data[key] = nativeCreate && value === undefined ? HASH_UNDEFINED : value;
            return this;
        }
        Hash.prototype.clear = hashClear;
        Hash.prototype["delete"] = hashDelete;
        Hash.prototype.get = hashGet;
        Hash.prototype.has = hashHas;
        Hash.prototype.set = hashSet;
        function ListCache(entries) {
            var index = -1, length = entries == null ? 0 : entries.length;
            this.clear();
            while (++index < length) {
                var entry = entries[index];
                this.set(entry[0], entry[1]);
            }
        }
        function listCacheClear() {
            this.__data__ = [];
            this.size = 0;
        }
        function listCacheDelete(key) {
            var data = this.__data__, index = assocIndexOf(data, key);
            if (index < 0) {
                return false;
            }
            var lastIndex = data.length - 1;
            if (index == lastIndex) {
                data.pop();
            } else {
                splice.call(data, index, 1);
            }
            --this.size;
            return true;
        }
        function listCacheGet(key) {
            var data = this.__data__, index = assocIndexOf(data, key);
            return index < 0 ? undefined : data[index][1];
        }
        function listCacheHas(key) {
            return assocIndexOf(this.__data__, key) > -1;
        }
        function listCacheSet(key, value) {
            var data = this.__data__, index = assocIndexOf(data, key);
            if (index < 0) {
                ++this.size;
                data.push([ key, value ]);
            } else {
                data[index][1] = value;
            }
            return this;
        }
        ListCache.prototype.clear = listCacheClear;
        ListCache.prototype["delete"] = listCacheDelete;
        ListCache.prototype.get = listCacheGet;
        ListCache.prototype.has = listCacheHas;
        ListCache.prototype.set = listCacheSet;
        function MapCache(entries) {
            var index = -1, length = entries == null ? 0 : entries.length;
            this.clear();
            while (++index < length) {
                var entry = entries[index];
                this.set(entry[0], entry[1]);
            }
        }
        function mapCacheClear() {
            this.size = 0;
            this.__data__ = {
                hash: new Hash(),
                map: new (Map || ListCache)(),
                string: new Hash()
            };
        }
        function mapCacheDelete(key) {
            var result = getMapData(this, key)["delete"](key);
            this.size -= result ? 1 : 0;
            return result;
        }
        function mapCacheGet(key) {
            return getMapData(this, key).get(key);
        }
        function mapCacheHas(key) {
            return getMapData(this, key).has(key);
        }
        function mapCacheSet(key, value) {
            var data = getMapData(this, key), size = data.size;
            data.set(key, value);
            this.size += data.size == size ? 0 : 1;
            return this;
        }
        MapCache.prototype.clear = mapCacheClear;
        MapCache.prototype["delete"] = mapCacheDelete;
        MapCache.prototype.get = mapCacheGet;
        MapCache.prototype.has = mapCacheHas;
        MapCache.prototype.set = mapCacheSet;
        function SetCache(values) {
            var index = -1, length = values == null ? 0 : values.length;
            this.__data__ = new MapCache();
            while (++index < length) {
                this.add(values[index]);
            }
        }
        function setCacheAdd(value) {
            this.__data__.set(value, HASH_UNDEFINED);
            return this;
        }
        function setCacheHas(value) {
            return this.__data__.has(value);
        }
        SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
        SetCache.prototype.has = setCacheHas;
        function Stack(entries) {
            var data = this.__data__ = new ListCache(entries);
            this.size = data.size;
        }
        function stackClear() {
            this.__data__ = new ListCache();
            this.size = 0;
        }
        function stackDelete(key) {
            var data = this.__data__, result = data["delete"](key);
            this.size = data.size;
            return result;
        }
        function stackGet(key) {
            return this.__data__.get(key);
        }
        function stackHas(key) {
            return this.__data__.has(key);
        }
        function stackSet(key, value) {
            var data = this.__data__;
            if (data instanceof ListCache) {
                var pairs = data.__data__;
                if (!Map || pairs.length < LARGE_ARRAY_SIZE - 1) {
                    pairs.push([ key, value ]);
                    this.size = ++data.size;
                    return this;
                }
                data = this.__data__ = new MapCache(pairs);
            }
            data.set(key, value);
            this.size = data.size;
            return this;
        }
        Stack.prototype.clear = stackClear;
        Stack.prototype["delete"] = stackDelete;
        Stack.prototype.get = stackGet;
        Stack.prototype.has = stackHas;
        Stack.prototype.set = stackSet;
        function arrayLikeKeys(value, inherited) {
            var isArr = isArray(value), isArg = !isArr && isArguments(value), isBuff = !isArr && !isArg && isBuffer(value), isType = !isArr && !isArg && !isBuff && isTypedArray(value), skipIndexes = isArr || isArg || isBuff || isType, result = skipIndexes ? baseTimes(value.length, String) : [], length = result.length;
            for (var key in value) {
                if ((inherited || hasOwnProperty.call(value, key)) && !(skipIndexes && (key == "length" || isBuff && (key == "offset" || key == "parent") || isType && (key == "buffer" || key == "byteLength" || key == "byteOffset") || isIndex(key, length)))) {
                    result.push(key);
                }
            }
            return result;
        }
        function arraySample(array) {
            var length = array.length;
            return length ? array[baseRandom(0, length - 1)] : undefined;
        }
        function arraySampleSize(array, n) {
            return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length));
        }
        function arrayShuffle(array) {
            return shuffleSelf(copyArray(array));
        }
        function assignMergeValue(object, key, value) {
            if (value !== undefined && !eq(object[key], value) || value === undefined && !(key in object)) {
                baseAssignValue(object, key, value);
            }
        }
        function assignValue(object, key, value) {
            var objValue = object[key];
            if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) || value === undefined && !(key in object)) {
                baseAssignValue(object, key, value);
            }
        }
        function assocIndexOf(array, key) {
            var length = array.length;
            while (length--) {
                if (eq(array[length][0], key)) {
                    return length;
                }
            }
            return -1;
        }
        function baseAggregator(collection, setter, iteratee, accumulator) {
            baseEach(collection, function(value, key, collection) {
                setter(accumulator, value, iteratee(value), collection);
            });
            return accumulator;
        }
        function baseAssign(object, source) {
            return object && copyObject(source, keys(source), object);
        }
        function baseAssignIn(object, source) {
            return object && copyObject(source, keysIn(source), object);
        }
        function baseAssignValue(object, key, value) {
            if (key == "__proto__" && defineProperty) {
                defineProperty(object, key, {
                    configurable: true,
                    enumerable: true,
                    value: value,
                    writable: true
                });
            } else {
                object[key] = value;
            }
        }
        function baseAt(object, paths) {
            var index = -1, length = paths.length, result = Array(length), skip = object == null;
            while (++index < length) {
                result[index] = skip ? undefined : get(object, paths[index]);
            }
            return result;
        }
        function baseClamp(number, lower, upper) {
            if (number === number) {
                if (upper !== undefined) {
                    number = number <= upper ? number : upper;
                }
                if (lower !== undefined) {
                    number = number >= lower ? number : lower;
                }
            }
            return number;
        }
        function baseClone(value, bitmask, customizer, key, object, stack) {
            var result, isDeep = bitmask & CLONE_DEEP_FLAG, isFlat = bitmask & CLONE_FLAT_FLAG, isFull = bitmask & CLONE_SYMBOLS_FLAG;
            if (customizer) {
                result = object ? customizer(value, key, object, stack) : customizer(value);
            }
            if (result !== undefined) {
                return result;
            }
            if (!isObject(value)) {
                return value;
            }
            var isArr = isArray(value);
            if (isArr) {
                result = initCloneArray(value);
                if (!isDeep) {
                    return copyArray(value, result);
                }
            } else {
                var tag = getTag(value), isFunc = tag == funcTag || tag == genTag;
                if (isBuffer(value)) {
                    return cloneBuffer(value, isDeep);
                }
                if (tag == objectTag || tag == argsTag || isFunc && !object) {
                    result = isFlat || isFunc ? {} : initCloneObject(value);
                    if (!isDeep) {
                        return isFlat ? copySymbolsIn(value, baseAssignIn(result, value)) : copySymbols(value, baseAssign(result, value));
                    }
                } else {
                    if (!cloneableTags[tag]) {
                        return object ? value : {};
                    }
                    result = initCloneByTag(value, tag, isDeep);
                }
            }
            stack || (stack = new Stack());
            var stacked = stack.get(value);
            if (stacked) {
                return stacked;
            }
            stack.set(value, result);
            if (isSet(value)) {
                value.forEach(function(subValue) {
                    result.add(baseClone(subValue, bitmask, customizer, subValue, value, stack));
                });
            } else if (isMap(value)) {
                value.forEach(function(subValue, key) {
                    result.set(key, baseClone(subValue, bitmask, customizer, key, value, stack));
                });
            }
            var keysFunc = isFull ? isFlat ? getAllKeysIn : getAllKeys : isFlat ? keysIn : keys;
            var props = isArr ? undefined : keysFunc(value);
            arrayEach(props || value, function(subValue, key) {
                if (props) {
                    key = subValue;
                    subValue = value[key];
                }
                assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));
            });
            return result;
        }
        function baseConforms(source) {
            var props = keys(source);
            return function(object) {
                return baseConformsTo(object, source, props);
            };
        }
        function baseConformsTo(object, source, props) {
            var length = props.length;
            if (object == null) {
                return !length;
            }
            object = Object(object);
            while (length--) {
                var key = props[length], predicate = source[key], value = object[key];
                if (value === undefined && !(key in object) || !predicate(value)) {
                    return false;
                }
            }
            return true;
        }
        function baseDelay(func, wait, args) {
            if (typeof func != "function") {
                throw new TypeError(FUNC_ERROR_TEXT);
            }
            return setTimeout(function() {
                func.apply(undefined, args);
            }, wait);
        }
        function baseDifference(array, values, iteratee, comparator) {
            var index = -1, includes = arrayIncludes, isCommon = true, length = array.length, result = [], valuesLength = values.length;
            if (!length) {
                return result;
            }
            if (iteratee) {
                values = arrayMap(values, baseUnary(iteratee));
            }
            if (comparator) {
                includes = arrayIncludesWith;
                isCommon = false;
            } else if (values.length >= LARGE_ARRAY_SIZE) {
                includes = cacheHas;
                isCommon = false;
                values = new SetCache(values);
            }
            outer: while (++index < length) {
                var value = array[index], computed = iteratee == null ? value : iteratee(value);
                value = comparator || value !== 0 ? value : 0;
                if (isCommon && computed === computed) {
                    var valuesIndex = valuesLength;
                    while (valuesIndex--) {
                        if (values[valuesIndex] === computed) {
                            continue outer;
                        }
                    }
                    result.push(value);
                } else if (!includes(values, computed, comparator)) {
                    result.push(value);
                }
            }
            return result;
        }
        var baseEach = createBaseEach(baseForOwn);
        var baseEachRight = createBaseEach(baseForOwnRight, true);
        function baseEvery(collection, predicate) {
            var result = true;
            baseEach(collection, function(value, index, collection) {
                result = !!predicate(value, index, collection);
                return result;
            });
            return result;
        }
        function baseExtremum(array, iteratee, comparator) {
            var index = -1, length = array.length;
            while (++index < length) {
                var value = array[index], current = iteratee(value);
                if (current != null && (computed === undefined ? current === current && !isSymbol(current) : comparator(current, computed))) {
                    var computed = current, result = value;
                }
            }
            return result;
        }
        function baseFill(array, value, start, end) {
            var length = array.length;
            start = toInteger(start);
            if (start < 0) {
                start = -start > length ? 0 : length + start;
            }
            end = end === undefined || end > length ? length : toInteger(end);
            if (end < 0) {
                end += length;
            }
            end = start > end ? 0 : toLength(end);
            while (start < end) {
                array[start++] = value;
            }
            return array;
        }
        function baseFilter(collection, predicate) {
            var result = [];
            baseEach(collection, function(value, index, collection) {
                if (predicate(value, index, collection)) {
                    result.push(value);
                }
            });
            return result;
        }
        function baseFlatten(array, depth, predicate, isStrict, result) {
            var index = -1, length = array.length;
            predicate || (predicate = isFlattenable);
            result || (result = []);
            while (++index < length) {
                var value = array[index];
                if (depth > 0 && predicate(value)) {
                    if (depth > 1) {
                        baseFlatten(value, depth - 1, predicate, isStrict, result);
                    } else {
                        arrayPush(result, value);
                    }
                } else if (!isStrict) {
                    result[result.length] = value;
                }
            }
            return result;
        }
        var baseFor = createBaseFor();
        var baseForRight = createBaseFor(true);
        function baseForOwn(object, iteratee) {
            return object && baseFor(object, iteratee, keys);
        }
        function baseForOwnRight(object, iteratee) {
            return object && baseForRight(object, iteratee, keys);
        }
        function baseFunctions(object, props) {
            return arrayFilter(props, function(key) {
                return isFunction(object[key]);
            });
        }
        function baseGet(object, path) {
            path = castPath(path, object);
            var index = 0, length = path.length;
            while (object != null && index < length) {
                object = object[toKey(path[index++])];
            }
            return index && index == length ? object : undefined;
        }
        function baseGetAllKeys(object, keysFunc, symbolsFunc) {
            var result = keysFunc(object);
            return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
        }
        function baseGetTag(value) {
            if (value == null) {
                return value === undefined ? undefinedTag : nullTag;
            }
            return symToStringTag && symToStringTag in Object(value) ? getRawTag(value) : objectToString(value);
        }
        function baseGt(value, other) {
            return value > other;
        }
        function baseHas(object, key) {
            return object != null && hasOwnProperty.call(object, key);
        }
        function baseHasIn(object, key) {
            return object != null && key in Object(object);
        }
        function baseInRange(number, start, end) {
            return number >= nativeMin(start, end) && number < nativeMax(start, end);
        }
        function baseIntersection(arrays, iteratee, comparator) {
            var includes = comparator ? arrayIncludesWith : arrayIncludes, length = arrays[0].length, othLength = arrays.length, othIndex = othLength, caches = Array(othLength), maxLength = Infinity, result = [];
            while (othIndex--) {
                var array = arrays[othIndex];
                if (othIndex && iteratee) {
                    array = arrayMap(array, baseUnary(iteratee));
                }
                maxLength = nativeMin(array.length, maxLength);
                caches[othIndex] = !comparator && (iteratee || length >= 120 && array.length >= 120) ? new SetCache(othIndex && array) : undefined;
            }
            array = arrays[0];
            var index = -1, seen = caches[0];
            outer: while (++index < length && result.length < maxLength) {
                var value = array[index], computed = iteratee ? iteratee(value) : value;
                value = comparator || value !== 0 ? value : 0;
                if (!(seen ? cacheHas(seen, computed) : includes(result, computed, comparator))) {
                    othIndex = othLength;
                    while (--othIndex) {
                        var cache = caches[othIndex];
                        if (!(cache ? cacheHas(cache, computed) : includes(arrays[othIndex], computed, comparator))) {
                            continue outer;
                        }
                    }
                    if (seen) {
                        seen.push(computed);
                    }
                    result.push(value);
                }
            }
            return result;
        }
        function baseInverter(object, setter, iteratee, accumulator) {
            baseForOwn(object, function(value, key, object) {
                setter(accumulator, iteratee(value), key, object);
            });
            return accumulator;
        }
        function baseInvoke(object, path, args) {
            path = castPath(path, object);
            object = parent(object, path);
            var func = object == null ? object : object[toKey(last(path))];
            return func == null ? undefined : apply(func, object, args);
        }
        function baseIsArguments(value) {
            return isObjectLike(value) && baseGetTag(value) == argsTag;
        }
        function baseIsArrayBuffer(value) {
            return isObjectLike(value) && baseGetTag(value) == arrayBufferTag;
        }
        function baseIsDate(value) {
            return isObjectLike(value) && baseGetTag(value) == dateTag;
        }
        function baseIsEqual(value, other, bitmask, customizer, stack) {
            if (value === other) {
                return true;
            }
            if (value == null || other == null || !isObjectLike(value) && !isObjectLike(other)) {
                return value !== value && other !== other;
            }
            return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
        }
        function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
            var objIsArr = isArray(object), othIsArr = isArray(other), objTag = objIsArr ? arrayTag : getTag(object), othTag = othIsArr ? arrayTag : getTag(other);
            objTag = objTag == argsTag ? objectTag : objTag;
            othTag = othTag == argsTag ? objectTag : othTag;
            var objIsObj = objTag == objectTag, othIsObj = othTag == objectTag, isSameTag = objTag == othTag;
            if (isSameTag && isBuffer(object)) {
                if (!isBuffer(other)) {
                    return false;
                }
                objIsArr = true;
                objIsObj = false;
            }
            if (isSameTag && !objIsObj) {
                stack || (stack = new Stack());
                return objIsArr || isTypedArray(object) ? equalArrays(object, other, bitmask, customizer, equalFunc, stack) : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
            }
            if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
                var objIsWrapped = objIsObj && hasOwnProperty.call(object, "__wrapped__"), othIsWrapped = othIsObj && hasOwnProperty.call(other, "__wrapped__");
                if (objIsWrapped || othIsWrapped) {
                    var objUnwrapped = objIsWrapped ? object.value() : object, othUnwrapped = othIsWrapped ? other.value() : other;
                    stack || (stack = new Stack());
                    return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
                }
            }
            if (!isSameTag) {
                return false;
            }
            stack || (stack = new Stack());
            return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
        }
        function baseIsMap(value) {
            return isObjectLike(value) && getTag(value) == mapTag;
        }
        function baseIsMatch(object, source, matchData, customizer) {
            var index = matchData.length, length = index, noCustomizer = !customizer;
            if (object == null) {
                return !length;
            }
            object = Object(object);
            while (index--) {
                var data = matchData[index];
                if (noCustomizer && data[2] ? data[1] !== object[data[0]] : !(data[0] in object)) {
                    return false;
                }
            }
            while (++index < length) {
                data = matchData[index];
                var key = data[0], objValue = object[key], srcValue = data[1];
                if (noCustomizer && data[2]) {
                    if (objValue === undefined && !(key in object)) {
                        return false;
                    }
                } else {
                    var stack = new Stack();
                    if (customizer) {
                        var result = customizer(objValue, srcValue, key, object, source, stack);
                    }
                    if (!(result === undefined ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack) : result)) {
                        return false;
                    }
                }
            }
            return true;
        }
        function baseIsNative(value) {
            if (!isObject(value) || isMasked(value)) {
                return false;
            }
            var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
            return pattern.test(toSource(value));
        }
        function baseIsRegExp(value) {
            return isObjectLike(value) && baseGetTag(value) == regexpTag;
        }
        function baseIsSet(value) {
            return isObjectLike(value) && getTag(value) == setTag;
        }
        function baseIsTypedArray(value) {
            return isObjectLike(value) && isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
        }
        function baseIteratee(value) {
            if (typeof value == "function") {
                return value;
            }
            if (value == null) {
                return identity;
            }
            if (typeof value == "object") {
                return isArray(value) ? baseMatchesProperty(value[0], value[1]) : baseMatches(value);
            }
            return property(value);
        }
        function baseKeys(object) {
            if (!isPrototype(object)) {
                return nativeKeys(object);
            }
            var result = [];
            for (var key in Object(object)) {
                if (hasOwnProperty.call(object, key) && key != "constructor") {
                    result.push(key);
                }
            }
            return result;
        }
        function baseKeysIn(object) {
            if (!isObject(object)) {
                return nativeKeysIn(object);
            }
            var isProto = isPrototype(object), result = [];
            for (var key in object) {
                if (!(key == "constructor" && (isProto || !hasOwnProperty.call(object, key)))) {
                    result.push(key);
                }
            }
            return result;
        }
        function baseLt(value, other) {
            return value < other;
        }
        function baseMap(collection, iteratee) {
            var index = -1, result = isArrayLike(collection) ? Array(collection.length) : [];
            baseEach(collection, function(value, key, collection) {
                result[++index] = iteratee(value, key, collection);
            });
            return result;
        }
        function baseMatches(source) {
            var matchData = getMatchData(source);
            if (matchData.length == 1 && matchData[0][2]) {
                return matchesStrictComparable(matchData[0][0], matchData[0][1]);
            }
            return function(object) {
                return object === source || baseIsMatch(object, source, matchData);
            };
        }
        function baseMatchesProperty(path, srcValue) {
            if (isKey(path) && isStrictComparable(srcValue)) {
                return matchesStrictComparable(toKey(path), srcValue);
            }
            return function(object) {
                var objValue = get(object, path);
                return objValue === undefined && objValue === srcValue ? hasIn(object, path) : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
            };
        }
        function baseMerge(object, source, srcIndex, customizer, stack) {
            if (object === source) {
                return;
            }
            baseFor(source, function(srcValue, key) {
                stack || (stack = new Stack());
                if (isObject(srcValue)) {
                    baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
                } else {
                    var newValue = customizer ? customizer(safeGet(object, key), srcValue, key + "", object, source, stack) : undefined;
                    if (newValue === undefined) {
                        newValue = srcValue;
                    }
                    assignMergeValue(object, key, newValue);
                }
            }, keysIn);
        }
        function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
            var objValue = safeGet(object, key), srcValue = safeGet(source, key), stacked = stack.get(srcValue);
            if (stacked) {
                assignMergeValue(object, key, stacked);
                return;
            }
            var newValue = customizer ? customizer(objValue, srcValue, key + "", object, source, stack) : undefined;
            var isCommon = newValue === undefined;
            if (isCommon) {
                var isArr = isArray(srcValue), isBuff = !isArr && isBuffer(srcValue), isTyped = !isArr && !isBuff && isTypedArray(srcValue);
                newValue = srcValue;
                if (isArr || isBuff || isTyped) {
                    if (isArray(objValue)) {
                        newValue = objValue;
                    } else if (isArrayLikeObject(objValue)) {
                        newValue = copyArray(objValue);
                    } else if (isBuff) {
                        isCommon = false;
                        newValue = cloneBuffer(srcValue, true);
                    } else if (isTyped) {
                        isCommon = false;
                        newValue = cloneTypedArray(srcValue, true);
                    } else {
                        newValue = [];
                    }
                } else if (isPlainObject(srcValue) || isArguments(srcValue)) {
                    newValue = objValue;
                    if (isArguments(objValue)) {
                        newValue = toPlainObject(objValue);
                    } else if (!isObject(objValue) || isFunction(objValue)) {
                        newValue = initCloneObject(srcValue);
                    }
                } else {
                    isCommon = false;
                }
            }
            if (isCommon) {
                stack.set(srcValue, newValue);
                mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
                stack["delete"](srcValue);
            }
            assignMergeValue(object, key, newValue);
        }
        function baseNth(array, n) {
            var length = array.length;
            if (!length) {
                return;
            }
            n += n < 0 ? length : 0;
            return isIndex(n, length) ? array[n] : undefined;
        }
        function baseOrderBy(collection, iteratees, orders) {
            if (iteratees.length) {
                iteratees = arrayMap(iteratees, function(iteratee) {
                    if (isArray(iteratee)) {
                        return function(value) {
                            return baseGet(value, iteratee.length === 1 ? iteratee[0] : iteratee);
                        };
                    }
                    return iteratee;
                });
            } else {
                iteratees = [ identity ];
            }
            var index = -1;
            iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
            var result = baseMap(collection, function(value, key, collection) {
                var criteria = arrayMap(iteratees, function(iteratee) {
                    return iteratee(value);
                });
                return {
                    criteria: criteria,
                    index: ++index,
                    value: value
                };
            });
            return baseSortBy(result, function(object, other) {
                return compareMultiple(object, other, orders);
            });
        }
        function basePick(object, paths) {
            return basePickBy(object, paths, function(value, path) {
                return hasIn(object, path);
            });
        }
        function basePickBy(object, paths, predicate) {
            var index = -1, length = paths.length, result = {};
            while (++index < length) {
                var path = paths[index], value = baseGet(object, path);
                if (predicate(value, path)) {
                    baseSet(result, castPath(path, object), value);
                }
            }
            return result;
        }
        function basePropertyDeep(path) {
            return function(object) {
                return baseGet(object, path);
            };
        }
        function basePullAll(array, values, iteratee, comparator) {
            var indexOf = comparator ? baseIndexOfWith : baseIndexOf, index = -1, length = values.length, seen = array;
            if (array === values) {
                values = copyArray(values);
            }
            if (iteratee) {
                seen = arrayMap(array, baseUnary(iteratee));
            }
            while (++index < length) {
                var fromIndex = 0, value = values[index], computed = iteratee ? iteratee(value) : value;
                while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) {
                    if (seen !== array) {
                        splice.call(seen, fromIndex, 1);
                    }
                    splice.call(array, fromIndex, 1);
                }
            }
            return array;
        }
        function basePullAt(array, indexes) {
            var length = array ? indexes.length : 0, lastIndex = length - 1;
            while (length--) {
                var index = indexes[length];
                if (length == lastIndex || index !== previous) {
                    var previous = index;
                    if (isIndex(index)) {
                        splice.call(array, index, 1);
                    } else {
                        baseUnset(array, index);
                    }
                }
            }
            return array;
        }
        function baseRandom(lower, upper) {
            return lower + nativeFloor(nativeRandom() * (upper - lower + 1));
        }
        function baseRange(start, end, step, fromRight) {
            var index = -1, length = nativeMax(nativeCeil((end - start) / (step || 1)), 0), result = Array(length);
            while (length--) {
                result[fromRight ? length : ++index] = start;
                start += step;
            }
            return result;
        }
        function baseRepeat(string, n) {
            var result = "";
            if (!string || n < 1 || n > MAX_SAFE_INTEGER) {
                return result;
            }
            do {
                if (n % 2) {
                    result += string;
                }
                n = nativeFloor(n / 2);
                if (n) {
                    string += string;
                }
            } while (n);
            return result;
        }
        function baseRest(func, start) {
            return setToString(overRest(func, start, identity), func + "");
        }
        function baseSample(collection) {
            return arraySample(values(collection));
        }
        function baseSampleSize(collection, n) {
            var array = values(collection);
            return shuffleSelf(array, baseClamp(n, 0, array.length));
        }
        function baseSet(object, path, value, customizer) {
            if (!isObject(object)) {
                return object;
            }
            path = castPath(path, object);
            var index = -1, length = path.length, lastIndex = length - 1, nested = object;
            while (nested != null && ++index < length) {
                var key = toKey(path[index]), newValue = value;
                if (key === "__proto__" || key === "constructor" || key === "prototype") {
                    return object;
                }
                if (index != lastIndex) {
                    var objValue = nested[key];
                    newValue = customizer ? customizer(objValue, key, nested) : undefined;
                    if (newValue === undefined) {
                        newValue = isObject(objValue) ? objValue : isIndex(path[index + 1]) ? [] : {};
                    }
                }
                assignValue(nested, key, newValue);
                nested = nested[key];
            }
            return object;
        }
        var baseSetData = !metaMap ? identity : function(func, data) {
            metaMap.set(func, data);
            return func;
        };
        var baseSetToString = !defineProperty ? identity : function(func, string) {
            return defineProperty(func, "toString", {
                configurable: true,
                enumerable: false,
                value: constant(string),
                writable: true
            });
        };
        function baseShuffle(collection) {
            return shuffleSelf(values(collection));
        }
        function baseSlice(array, start, end) {
            var index = -1, length = array.length;
            if (start < 0) {
                start = -start > length ? 0 : length + start;
            }
            end = end > length ? length : end;
            if (end < 0) {
                end += length;
            }
            length = start > end ? 0 : end - start >>> 0;
            start >>>= 0;
            var result = Array(length);
            while (++index < length) {
                result[index] = array[index + start];
            }
            return result;
        }
        function baseSome(collection, predicate) {
            var result;
            baseEach(collection, function(value, index, collection) {
                result = predicate(value, index, collection);
                return !result;
            });
            return !!result;
        }
        function baseSortedIndex(array, value, retHighest) {
            var low = 0, high = array == null ? low : array.length;
            if (typeof value == "number" && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
                while (low < high) {
                    var mid = low + high >>> 1, computed = array[mid];
                    if (computed !== null && !isSymbol(computed) && (retHighest ? computed <= value : computed < value)) {
                        low = mid + 1;
                    } else {
                        high = mid;
                    }
                }
                return high;
            }
            return baseSortedIndexBy(array, value, identity, retHighest);
        }
        function baseSortedIndexBy(array, value, iteratee, retHighest) {
            var low = 0, high = array == null ? 0 : array.length;
            if (high === 0) {
                return 0;
            }
            value = iteratee(value);
            var valIsNaN = value !== value, valIsNull = value === null, valIsSymbol = isSymbol(value), valIsUndefined = value === undefined;
            while (low < high) {
                var mid = nativeFloor((low + high) / 2), computed = iteratee(array[mid]), othIsDefined = computed !== undefined, othIsNull = computed === null, othIsReflexive = computed === computed, othIsSymbol = isSymbol(computed);
                if (valIsNaN) {
                    var setLow = retHighest || othIsReflexive;
                } else if (valIsUndefined) {
                    setLow = othIsReflexive && (retHighest || othIsDefined);
                } else if (valIsNull) {
                    setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull);
                } else if (valIsSymbol) {
                    setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol);
                } else if (othIsNull || othIsSymbol) {
                    setLow = false;
                } else {
                    setLow = retHighest ? computed <= value : computed < value;
                }
                if (setLow) {
                    low = mid + 1;
                } else {
                    high = mid;
                }
            }
            return nativeMin(high, MAX_ARRAY_INDEX);
        }
        function baseSortedUniq(array, iteratee) {
            var index = -1, length = array.length, resIndex = 0, result = [];
            while (++index < length) {
                var value = array[index], computed = iteratee ? iteratee(value) : value;
                if (!index || !eq(computed, seen)) {
                    var seen = computed;
                    result[resIndex++] = value === 0 ? 0 : value;
                }
            }
            return result;
        }
        function baseToNumber(value) {
            if (typeof value == "number") {
                return value;
            }
            if (isSymbol(value)) {
                return NAN;
            }
            return +value;
        }
        function baseToString(value) {
            if (typeof value == "string") {
                return value;
            }
            if (isArray(value)) {
                return arrayMap(value, baseToString) + "";
            }
            if (isSymbol(value)) {
                return symbolToString ? symbolToString.call(value) : "";
            }
            var result = value + "";
            return result == "0" && 1 / value == -INFINITY ? "-0" : result;
        }
        function baseUniq(array, iteratee, comparator) {
            var index = -1, includes = arrayIncludes, length = array.length, isCommon = true, result = [], seen = result;
            if (comparator) {
                isCommon = false;
                includes = arrayIncludesWith;
            } else if (length >= LARGE_ARRAY_SIZE) {
                var set = iteratee ? null : createSet(array);
                if (set) {
                    return setToArray(set);
                }
                isCommon = false;
                includes = cacheHas;
                seen = new SetCache();
            } else {
                seen = iteratee ? [] : result;
            }
            outer: while (++index < length) {
                var value = array[index], computed = iteratee ? iteratee(value) : value;
                value = comparator || value !== 0 ? value : 0;
                if (isCommon && computed === computed) {
                    var seenIndex = seen.length;
                    while (seenIndex--) {
                        if (seen[seenIndex] === computed) {
                            continue outer;
                        }
                    }
                    if (iteratee) {
                        seen.push(computed);
                    }
                    result.push(value);
                } else if (!includes(seen, computed, comparator)) {
                    if (seen !== result) {
                        seen.push(computed);
                    }
                    result.push(value);
                }
            }
            return result;
        }
        function baseUnset(object, path) {
            path = castPath(path, object);
            object = parent(object, path);
            return object == null || delete object[toKey(last(path))];
        }
        function baseUpdate(object, path, updater, customizer) {
            return baseSet(object, path, updater(baseGet(object, path)), customizer);
        }
        function baseWhile(array, predicate, isDrop, fromRight) {
            var length = array.length, index = fromRight ? length : -1;
            while ((fromRight ? index-- : ++index < length) && predicate(array[index], index, array)) {}
            return isDrop ? baseSlice(array, fromRight ? 0 : index, fromRight ? index + 1 : length) : baseSlice(array, fromRight ? index + 1 : 0, fromRight ? length : index);
        }
        function baseWrapperValue(value, actions) {
            var result = value;
            if (result instanceof LazyWrapper) {
                result = result.value();
            }
            return arrayReduce(actions, function(result, action) {
                return action.func.apply(action.thisArg, arrayPush([ result ], action.args));
            }, result);
        }
        function baseXor(arrays, iteratee, comparator) {
            var length = arrays.length;
            if (length < 2) {
                return length ? baseUniq(arrays[0]) : [];
            }
            var index = -1, result = Array(length);
            while (++index < length) {
                var array = arrays[index], othIndex = -1;
                while (++othIndex < length) {
                    if (othIndex != index) {
                        result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator);
                    }
                }
            }
            return baseUniq(baseFlatten(result, 1), iteratee, comparator);
        }
        function baseZipObject(props, values, assignFunc) {
            var index = -1, length = props.length, valsLength = values.length, result = {};
            while (++index < length) {
                var value = index < valsLength ? values[index] : undefined;
                assignFunc(result, props[index], value);
            }
            return result;
        }
        function castArrayLikeObject(value) {
            return isArrayLikeObject(value) ? value : [];
        }
        function castFunction(value) {
            return typeof value == "function" ? value : identity;
        }
        function castPath(value, object) {
            if (isArray(value)) {
                return value;
            }
            return isKey(value, object) ? [ value ] : stringToPath(toString(value));
        }
        var castRest = baseRest;
        function castSlice(array, start, end) {
            var length = array.length;
            end = end === undefined ? length : end;
            return !start && end >= length ? array : baseSlice(array, start, end);
        }
        var clearTimeout = ctxClearTimeout || function(id) {
            return root.clearTimeout(id);
        };
        function cloneBuffer(buffer, isDeep) {
            if (isDeep) {
                return buffer.slice();
            }
            var length = buffer.length, result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);
            buffer.copy(result);
            return result;
        }
        function cloneArrayBuffer(arrayBuffer) {
            var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
            new Uint8Array(result).set(new Uint8Array(arrayBuffer));
            return result;
        }
        function cloneDataView(dataView, isDeep) {
            var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
            return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
        }
        function cloneRegExp(regexp) {
            var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));
            result.lastIndex = regexp.lastIndex;
            return result;
        }
        function cloneSymbol(symbol) {
            return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};
        }
        function cloneTypedArray(typedArray, isDeep) {
            var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
            return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
        }
        function compareAscending(value, other) {
            if (value !== other) {
                var valIsDefined = value !== undefined, valIsNull = value === null, valIsReflexive = value === value, valIsSymbol = isSymbol(value);
                var othIsDefined = other !== undefined, othIsNull = other === null, othIsReflexive = other === other, othIsSymbol = isSymbol(other);
                if (!othIsNull && !othIsSymbol && !valIsSymbol && value > other || valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol || valIsNull && othIsDefined && othIsReflexive || !valIsDefined && othIsReflexive || !valIsReflexive) {
                    return 1;
                }
                if (!valIsNull && !valIsSymbol && !othIsSymbol && value < other || othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol || othIsNull && valIsDefined && valIsReflexive || !othIsDefined && valIsReflexive || !othIsReflexive) {
                    return -1;
                }
            }
            return 0;
        }
        function compareMultiple(object, other, orders) {
            var index = -1, objCriteria = object.criteria, othCriteria = other.criteria, length = objCriteria.length, ordersLength = orders.length;
            while (++index < length) {
                var result = compareAscending(objCriteria[index], othCriteria[index]);
                if (result) {
                    if (index >= ordersLength) {
                        return result;
                    }
                    var order = orders[index];
                    return result * (order == "desc" ? -1 : 1);
                }
            }
            return object.index - other.index;
        }
        function composeArgs(args, partials, holders, isCurried) {
            var argsIndex = -1, argsLength = args.length, holdersLength = holders.length, leftIndex = -1, leftLength = partials.length, rangeLength = nativeMax(argsLength - holdersLength, 0), result = Array(leftLength + rangeLength), isUncurried = !isCurried;
            while (++leftIndex < leftLength) {
                result[leftIndex] = partials[leftIndex];
            }
            while (++argsIndex < holdersLength) {
                if (isUncurried || argsIndex < argsLength) {
                    result[holders[argsIndex]] = args[argsIndex];
                }
            }
            while (rangeLength--) {
                result[leftIndex++] = args[argsIndex++];
            }
            return result;
        }
        function composeArgsRight(args, partials, holders, isCurried) {
            var argsIndex = -1, argsLength = args.length, holdersIndex = -1, holdersLength = holders.length, rightIndex = -1, rightLength = partials.length, rangeLength = nativeMax(argsLength - holdersLength, 0), result = Array(rangeLength + rightLength), isUncurried = !isCurried;
            while (++argsIndex < rangeLength) {
                result[argsIndex] = args[argsIndex];
            }
            var offset = argsIndex;
            while (++rightIndex < rightLength) {
                result[offset + rightIndex] = partials[rightIndex];
            }
            while (++holdersIndex < holdersLength) {
                if (isUncurried || argsIndex < argsLength) {
                    result[offset + holders[holdersIndex]] = args[argsIndex++];
                }
            }
            return result;
        }
        function copyArray(source, array) {
            var index = -1, length = source.length;
            array || (array = Array(length));
            while (++index < length) {
                array[index] = source[index];
            }
            return array;
        }
        function copyObject(source, props, object, customizer) {
            var isNew = !object;
            object || (object = {});
            var index = -1, length = props.length;
            while (++index < length) {
                var key = props[index];
                var newValue = customizer ? customizer(object[key], source[key], key, object, source) : undefined;
                if (newValue === undefined) {
                    newValue = source[key];
                }
                if (isNew) {
                    baseAssignValue(object, key, newValue);
                } else {
                    assignValue(object, key, newValue);
                }
            }
            return object;
        }
        function copySymbols(source, object) {
            return copyObject(source, getSymbols(source), object);
        }
        function copySymbolsIn(source, object) {
            return copyObject(source, getSymbolsIn(source), object);
        }
        function createAggregator(setter, initializer) {
            return function(collection, iteratee) {
                var func = isArray(collection) ? arrayAggregator : baseAggregator, accumulator = initializer ? initializer() : {};
                return func(collection, setter, getIteratee(iteratee, 2), accumulator);
            };
        }
        function createAssigner(assigner) {
            return baseRest(function(object, sources) {
                var index = -1, length = sources.length, customizer = length > 1 ? sources[length - 1] : undefined, guard = length > 2 ? sources[2] : undefined;
                customizer = assigner.length > 3 && typeof customizer == "function" ? (length--, 
                customizer) : undefined;
                if (guard && isIterateeCall(sources[0], sources[1], guard)) {
                    customizer = length < 3 ? undefined : customizer;
                    length = 1;
                }
                object = Object(object);
                while (++index < length) {
                    var source = sources[index];
                    if (source) {
                        assigner(object, source, index, customizer);
                    }
                }
                return object;
            });
        }
        function createBaseEach(eachFunc, fromRight) {
            return function(collection, iteratee) {
                if (collection == null) {
                    return collection;
                }
                if (!isArrayLike(collection)) {
                    return eachFunc(collection, iteratee);
                }
                var length = collection.length, index = fromRight ? length : -1, iterable = Object(collection);
                while (fromRight ? index-- : ++index < length) {
                    if (iteratee(iterable[index], index, iterable) === false) {
                        break;
                    }
                }
                return collection;
            };
        }
        function createBaseFor(fromRight) {
            return function(object, iteratee, keysFunc) {
                var index = -1, iterable = Object(object), props = keysFunc(object), length = props.length;
                while (length--) {
                    var key = props[fromRight ? length : ++index];
                    if (iteratee(iterable[key], key, iterable) === false) {
                        break;
                    }
                }
                return object;
            };
        }
        function createBind(func, bitmask, thisArg) {
            var isBind = bitmask & WRAP_BIND_FLAG, Ctor = createCtor(func);
            function wrapper() {
                var fn = this && this !== root && this instanceof wrapper ? Ctor : func;
                return fn.apply(isBind ? thisArg : this, arguments);
            }
            return wrapper;
        }
        function createCaseFirst(methodName) {
            return function(string) {
                string = toString(string);
                var strSymbols = hasUnicode(string) ? stringToArray(string) : undefined;
                var chr = strSymbols ? strSymbols[0] : string.charAt(0);
                var trailing = strSymbols ? castSlice(strSymbols, 1).join("") : string.slice(1);
                return chr[methodName]() + trailing;
            };
        }
        function createCompounder(callback) {
            return function(string) {
                return arrayReduce(words(deburr(string).replace(reApos, "")), callback, "");
            };
        }
        function createCtor(Ctor) {
            return function() {
                var args = arguments;
                switch (args.length) {
                  case 0:
                    return new Ctor();

                  case 1:
                    return new Ctor(args[0]);

                  case 2:
                    return new Ctor(args[0], args[1]);

                  case 3:
                    return new Ctor(args[0], args[1], args[2]);

                  case 4:
                    return new Ctor(args[0], args[1], args[2], args[3]);

                  case 5:
                    return new Ctor(args[0], args[1], args[2], args[3], args[4]);

                  case 6:
                    return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);

                  case 7:
                    return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
                }
                var thisBinding = baseCreate(Ctor.prototype), result = Ctor.apply(thisBinding, args);
                return isObject(result) ? result : thisBinding;
            };
        }
        function createCurry(func, bitmask, arity) {
            var Ctor = createCtor(func);
            function wrapper() {
                var length = arguments.length, args = Array(length), index = length, placeholder = getHolder(wrapper);
                while (index--) {
                    args[index] = arguments[index];
                }
                var holders = length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder ? [] : replaceHolders(args, placeholder);
                length -= holders.length;
                if (length < arity) {
                    return createRecurry(func, bitmask, createHybrid, wrapper.placeholder, undefined, args, holders, undefined, undefined, arity - length);
                }
                var fn = this && this !== root && this instanceof wrapper ? Ctor : func;
                return apply(fn, this, args);
            }
            return wrapper;
        }
        function createFind(findIndexFunc) {
            return function(collection, predicate, fromIndex) {
                var iterable = Object(collection);
                if (!isArrayLike(collection)) {
                    var iteratee = getIteratee(predicate, 3);
                    collection = keys(collection);
                    predicate = function(key) {
                        return iteratee(iterable[key], key, iterable);
                    };
                }
                var index = findIndexFunc(collection, predicate, fromIndex);
                return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined;
            };
        }
        function createFlow(fromRight) {
            return flatRest(function(funcs) {
                var length = funcs.length, index = length, prereq = LodashWrapper.prototype.thru;
                if (fromRight) {
                    funcs.reverse();
                }
                while (index--) {
                    var func = funcs[index];
                    if (typeof func != "function") {
                        throw new TypeError(FUNC_ERROR_TEXT);
                    }
                    if (prereq && !wrapper && getFuncName(func) == "wrapper") {
                        var wrapper = new LodashWrapper([], true);
                    }
                }
                index = wrapper ? index : length;
                while (++index < length) {
                    func = funcs[index];
                    var funcName = getFuncName(func), data = funcName == "wrapper" ? getData(func) : undefined;
                    if (data && isLaziable(data[0]) && data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) && !data[4].length && data[9] == 1) {
                        wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
                    } else {
                        wrapper = func.length == 1 && isLaziable(func) ? wrapper[funcName]() : wrapper.thru(func);
                    }
                }
                return function() {
                    var args = arguments, value = args[0];
                    if (wrapper && args.length == 1 && isArray(value)) {
                        return wrapper.plant(value).value();
                    }
                    var index = 0, result = length ? funcs[index].apply(this, args) : value;
                    while (++index < length) {
                        result = funcs[index].call(this, result);
                    }
                    return result;
                };
            });
        }
        function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
            var isAry = bitmask & WRAP_ARY_FLAG, isBind = bitmask & WRAP_BIND_FLAG, isBindKey = bitmask & WRAP_BIND_KEY_FLAG, isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG), isFlip = bitmask & WRAP_FLIP_FLAG, Ctor = isBindKey ? undefined : createCtor(func);
            function wrapper() {
                var length = arguments.length, args = Array(length), index = length;
                while (index--) {
                    args[index] = arguments[index];
                }
                if (isCurried) {
                    var placeholder = getHolder(wrapper), holdersCount = countHolders(args, placeholder);
                }
                if (partials) {
                    args = composeArgs(args, partials, holders, isCurried);
                }
                if (partialsRight) {
                    args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
                }
                length -= holdersCount;
                if (isCurried && length < arity) {
                    var newHolders = replaceHolders(args, placeholder);
                    return createRecurry(func, bitmask, createHybrid, wrapper.placeholder, thisArg, args, newHolders, argPos, ary, arity - length);
                }
                var thisBinding = isBind ? thisArg : this, fn = isBindKey ? thisBinding[func] : func;
                length = args.length;
                if (argPos) {
                    args = reorder(args, argPos);
                } else if (isFlip && length > 1) {
                    args.reverse();
                }
                if (isAry && ary < length) {
                    args.length = ary;
                }
                if (this && this !== root && this instanceof wrapper) {
                    fn = Ctor || createCtor(fn);
                }
                return fn.apply(thisBinding, args);
            }
            return wrapper;
        }
        function createInverter(setter, toIteratee) {
            return function(object, iteratee) {
                return baseInverter(object, setter, toIteratee(iteratee), {});
            };
        }
        function createMathOperation(operator, defaultValue) {
            return function(value, other) {
                var result;
                if (value === undefined && other === undefined) {
                    return defaultValue;
                }
                if (value !== undefined) {
                    result = value;
                }
                if (other !== undefined) {
                    if (result === undefined) {
                        return other;
                    }
                    if (typeof value == "string" || typeof other == "string") {
                        value = baseToString(value);
                        other = baseToString(other);
                    } else {
                        value = baseToNumber(value);
                        other = baseToNumber(other);
                    }
                    result = operator(value, other);
                }
                return result;
            };
        }
        function createOver(arrayFunc) {
            return flatRest(function(iteratees) {
                iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
                return baseRest(function(args) {
                    var thisArg = this;
                    return arrayFunc(iteratees, function(iteratee) {
                        return apply(iteratee, thisArg, args);
                    });
                });
            });
        }
        function createPadding(length, chars) {
            chars = chars === undefined ? " " : baseToString(chars);
            var charsLength = chars.length;
            if (charsLength < 2) {
                return charsLength ? baseRepeat(chars, length) : chars;
            }
            var result = baseRepeat(chars, nativeCeil(length / stringSize(chars)));
            return hasUnicode(chars) ? castSlice(stringToArray(result), 0, length).join("") : result.slice(0, length);
        }
        function createPartial(func, bitmask, thisArg, partials) {
            var isBind = bitmask & WRAP_BIND_FLAG, Ctor = createCtor(func);
            function wrapper() {
                var argsIndex = -1, argsLength = arguments.length, leftIndex = -1, leftLength = partials.length, args = Array(leftLength + argsLength), fn = this && this !== root && this instanceof wrapper ? Ctor : func;
                while (++leftIndex < leftLength) {
                    args[leftIndex] = partials[leftIndex];
                }
                while (argsLength--) {
                    args[leftIndex++] = arguments[++argsIndex];
                }
                return apply(fn, isBind ? thisArg : this, args);
            }
            return wrapper;
        }
        function createRange(fromRight) {
            return function(start, end, step) {
                if (step && typeof step != "number" && isIterateeCall(start, end, step)) {
                    end = step = undefined;
                }
                start = toFinite(start);
                if (end === undefined) {
                    end = start;
                    start = 0;
                } else {
                    end = toFinite(end);
                }
                step = step === undefined ? start < end ? 1 : -1 : toFinite(step);
                return baseRange(start, end, step, fromRight);
            };
        }
        function createRelationalOperation(operator) {
            return function(value, other) {
                if (!(typeof value == "string" && typeof other == "string")) {
                    value = toNumber(value);
                    other = toNumber(other);
                }
                return operator(value, other);
            };
        }
        function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {
            var isCurry = bitmask & WRAP_CURRY_FLAG, newHolders = isCurry ? holders : undefined, newHoldersRight = isCurry ? undefined : holders, newPartials = isCurry ? partials : undefined, newPartialsRight = isCurry ? undefined : partials;
            bitmask |= isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG;
            bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG);
            if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) {
                bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG);
            }
            var newData = [ func, bitmask, thisArg, newPartials, newHolders, newPartialsRight, newHoldersRight, argPos, ary, arity ];
            var result = wrapFunc.apply(undefined, newData);
            if (isLaziable(func)) {
                setData(result, newData);
            }
            result.placeholder = placeholder;
            return setWrapToString(result, func, bitmask);
        }
        function createRound(methodName) {
            var func = Math[methodName];
            return function(number, precision) {
                number = toNumber(number);
                precision = precision == null ? 0 : nativeMin(toInteger(precision), 292);
                if (precision && nativeIsFinite(number)) {
                    var pair = (toString(number) + "e").split("e"), value = func(pair[0] + "e" + (+pair[1] + precision));
                    pair = (toString(value) + "e").split("e");
                    return +(pair[0] + "e" + (+pair[1] - precision));
                }
                return func(number);
            };
        }
        var createSet = !(Set && 1 / setToArray(new Set([ , -0 ]))[1] == INFINITY) ? noop : function(values) {
            return new Set(values);
        };
        function createToPairs(keysFunc) {
            return function(object) {
                var tag = getTag(object);
                if (tag == mapTag) {
                    return mapToArray(object);
                }
                if (tag == setTag) {
                    return setToPairs(object);
                }
                return baseToPairs(object, keysFunc(object));
            };
        }
        function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
            var isBindKey = bitmask & WRAP_BIND_KEY_FLAG;
            if (!isBindKey && typeof func != "function") {
                throw new TypeError(FUNC_ERROR_TEXT);
            }
            var length = partials ? partials.length : 0;
            if (!length) {
                bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG);
                partials = holders = undefined;
            }
            ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0);
            arity = arity === undefined ? arity : toInteger(arity);
            length -= holders ? holders.length : 0;
            if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) {
                var partialsRight = partials, holdersRight = holders;
                partials = holders = undefined;
            }
            var data = isBindKey ? undefined : getData(func);
            var newData = [ func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity ];
            if (data) {
                mergeData(newData, data);
            }
            func = newData[0];
            bitmask = newData[1];
            thisArg = newData[2];
            partials = newData[3];
            holders = newData[4];
            arity = newData[9] = newData[9] === undefined ? isBindKey ? 0 : func.length : nativeMax(newData[9] - length, 0);
            if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) {
                bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG);
            }
            if (!bitmask || bitmask == WRAP_BIND_FLAG) {
                var result = createBind(func, bitmask, thisArg);
            } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) {
                result = createCurry(func, bitmask, arity);
            } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) {
                result = createPartial(func, bitmask, thisArg, partials);
            } else {
                result = createHybrid.apply(undefined, newData);
            }
            var setter = data ? baseSetData : setData;
            return setWrapToString(setter(result, newData), func, bitmask);
        }
        function customDefaultsAssignIn(objValue, srcValue, key, object) {
            if (objValue === undefined || eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key)) {
                return srcValue;
            }
            return objValue;
        }
        function customDefaultsMerge(objValue, srcValue, key, object, source, stack) {
            if (isObject(objValue) && isObject(srcValue)) {
                stack.set(srcValue, objValue);
                baseMerge(objValue, srcValue, undefined, customDefaultsMerge, stack);
                stack["delete"](srcValue);
            }
            return objValue;
        }
        function customOmitClone(value) {
            return isPlainObject(value) ? undefined : value;
        }
        function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
            var isPartial = bitmask & COMPARE_PARTIAL_FLAG, arrLength = array.length, othLength = other.length;
            if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
                return false;
            }
            var arrStacked = stack.get(array);
            var othStacked = stack.get(other);
            if (arrStacked && othStacked) {
                return arrStacked == other && othStacked == array;
            }
            var index = -1, result = true, seen = bitmask & COMPARE_UNORDERED_FLAG ? new SetCache() : undefined;
            stack.set(array, other);
            stack.set(other, array);
            while (++index < arrLength) {
                var arrValue = array[index], othValue = other[index];
                if (customizer) {
                    var compared = isPartial ? customizer(othValue, arrValue, index, other, array, stack) : customizer(arrValue, othValue, index, array, other, stack);
                }
                if (compared !== undefined) {
                    if (compared) {
                        continue;
                    }
                    result = false;
                    break;
                }
                if (seen) {
                    if (!arraySome(other, function(othValue, othIndex) {
                        if (!cacheHas(seen, othIndex) && (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
                            return seen.push(othIndex);
                        }
                    })) {
                        result = false;
                        break;
                    }
                } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
                    result = false;
                    break;
                }
            }
            stack["delete"](array);
            stack["delete"](other);
            return result;
        }
        function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
            switch (tag) {
              case dataViewTag:
                if (object.byteLength != other.byteLength || object.byteOffset != other.byteOffset) {
                    return false;
                }
                object = object.buffer;
                other = other.buffer;

              case arrayBufferTag:
                if (object.byteLength != other.byteLength || !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
                    return false;
                }
                return true;

              case boolTag:
              case dateTag:
              case numberTag:
                return eq(+object, +other);

              case errorTag:
                return object.name == other.name && object.message == other.message;

              case regexpTag:
              case stringTag:
                return object == other + "";

              case mapTag:
                var convert = mapToArray;

              case setTag:
                var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
                convert || (convert = setToArray);
                if (object.size != other.size && !isPartial) {
                    return false;
                }
                var stacked = stack.get(object);
                if (stacked) {
                    return stacked == other;
                }
                bitmask |= COMPARE_UNORDERED_FLAG;
                stack.set(object, other);
                var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
                stack["delete"](object);
                return result;

              case symbolTag:
                if (symbolValueOf) {
                    return symbolValueOf.call(object) == symbolValueOf.call(other);
                }
            }
            return false;
        }
        function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
            var isPartial = bitmask & COMPARE_PARTIAL_FLAG, objProps = getAllKeys(object), objLength = objProps.length, othProps = getAllKeys(other), othLength = othProps.length;
            if (objLength != othLength && !isPartial) {
                return false;
            }
            var index = objLength;
            while (index--) {
                var key = objProps[index];
                if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
                    return false;
                }
            }
            var objStacked = stack.get(object);
            var othStacked = stack.get(other);
            if (objStacked && othStacked) {
                return objStacked == other && othStacked == object;
            }
            var result = true;
            stack.set(object, other);
            stack.set(other, object);
            var skipCtor = isPartial;
            while (++index < objLength) {
                key = objProps[index];
                var objValue = object[key], othValue = other[key];
                if (customizer) {
                    var compared = isPartial ? customizer(othValue, objValue, key, other, object, stack) : customizer(objValue, othValue, key, object, other, stack);
                }
                if (!(compared === undefined ? objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack) : compared)) {
                    result = false;
                    break;
                }
                skipCtor || (skipCtor = key == "constructor");
            }
            if (result && !skipCtor) {
                var objCtor = object.constructor, othCtor = other.constructor;
                if (objCtor != othCtor && ("constructor" in object && "constructor" in other) && !(typeof objCtor == "function" && objCtor instanceof objCtor && typeof othCtor == "function" && othCtor instanceof othCtor)) {
                    result = false;
                }
            }
            stack["delete"](object);
            stack["delete"](other);
            return result;
        }
        function flatRest(func) {
            return setToString(overRest(func, undefined, flatten), func + "");
        }
        function getAllKeys(object) {
            return baseGetAllKeys(object, keys, getSymbols);
        }
        function getAllKeysIn(object) {
            return baseGetAllKeys(object, keysIn, getSymbolsIn);
        }
        var getData = !metaMap ? noop : function(func) {
            return metaMap.get(func);
        };
        function getFuncName(func) {
            var result = func.name + "", array = realNames[result], length = hasOwnProperty.call(realNames, result) ? array.length : 0;
            while (length--) {
                var data = array[length], otherFunc = data.func;
                if (otherFunc == null || otherFunc == func) {
                    return data.name;
                }
            }
            return result;
        }
        function getHolder(func) {
            var object = hasOwnProperty.call(lodash, "placeholder") ? lodash : func;
            return object.placeholder;
        }
        function getIteratee() {
            var result = lodash.iteratee || iteratee;
            result = result === iteratee ? baseIteratee : result;
            return arguments.length ? result(arguments[0], arguments[1]) : result;
        }
        function getMapData(map, key) {
            var data = map.__data__;
            return isKeyable(key) ? data[typeof key == "string" ? "string" : "hash"] : data.map;
        }
        function getMatchData(object) {
            var result = keys(object), length = result.length;
            while (length--) {
                var key = result[length], value = object[key];
                result[length] = [ key, value, isStrictComparable(value) ];
            }
            return result;
        }
        function getNative(object, key) {
            var value = getValue(object, key);
            return baseIsNative(value) ? value : undefined;
        }
        function getRawTag(value) {
            var isOwn = hasOwnProperty.call(value, symToStringTag), tag = value[symToStringTag];
            try {
                value[symToStringTag] = undefined;
                var unmasked = true;
            } catch (e) {}
            var result = nativeObjectToString.call(value);
            if (unmasked) {
                if (isOwn) {
                    value[symToStringTag] = tag;
                } else {
                    delete value[symToStringTag];
                }
            }
            return result;
        }
        var getSymbols = !nativeGetSymbols ? stubArray : function(object) {
            if (object == null) {
                return [];
            }
            object = Object(object);
            return arrayFilter(nativeGetSymbols(object), function(symbol) {
                return propertyIsEnumerable.call(object, symbol);
            });
        };
        var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) {
            var result = [];
            while (object) {
                arrayPush(result, getSymbols(object));
                object = getPrototype(object);
            }
            return result;
        };
        var getTag = baseGetTag;
        if (DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag || Map && getTag(new Map()) != mapTag || Promise && getTag(Promise.resolve()) != promiseTag || Set && getTag(new Set()) != setTag || WeakMap && getTag(new WeakMap()) != weakMapTag) {
            getTag = function(value) {
                var result = baseGetTag(value), Ctor = result == objectTag ? value.constructor : undefined, ctorString = Ctor ? toSource(Ctor) : "";
                if (ctorString) {
                    switch (ctorString) {
                      case dataViewCtorString:
                        return dataViewTag;

                      case mapCtorString:
                        return mapTag;

                      case promiseCtorString:
                        return promiseTag;

                      case setCtorString:
                        return setTag;

                      case weakMapCtorString:
                        return weakMapTag;
                    }
                }
                return result;
            };
        }
        function getView(start, end, transforms) {
            var index = -1, length = transforms.length;
            while (++index < length) {
                var data = transforms[index], size = data.size;
                switch (data.type) {
                  case "drop":
                    start += size;
                    break;

                  case "dropRight":
                    end -= size;
                    break;

                  case "take":
                    end = nativeMin(end, start + size);
                    break;

                  case "takeRight":
                    start = nativeMax(start, end - size);
                    break;
                }
            }
            return {
                start: start,
                end: end
            };
        }
        function getWrapDetails(source) {
            var match = source.match(reWrapDetails);
            return match ? match[1].split(reSplitDetails) : [];
        }
        function hasPath(object, path, hasFunc) {
            path = castPath(path, object);
            var index = -1, length = path.length, result = false;
            while (++index < length) {
                var key = toKey(path[index]);
                if (!(result = object != null && hasFunc(object, key))) {
                    break;
                }
                object = object[key];
            }
            if (result || ++index != length) {
                return result;
            }
            length = object == null ? 0 : object.length;
            return !!length && isLength(length) && isIndex(key, length) && (isArray(object) || isArguments(object));
        }
        function initCloneArray(array) {
            var length = array.length, result = new array.constructor(length);
            if (length && typeof array[0] == "string" && hasOwnProperty.call(array, "index")) {
                result.index = array.index;
                result.input = array.input;
            }
            return result;
        }
        function initCloneObject(object) {
            return typeof object.constructor == "function" && !isPrototype(object) ? baseCreate(getPrototype(object)) : {};
        }
        function initCloneByTag(object, tag, isDeep) {
            var Ctor = object.constructor;
            switch (tag) {
              case arrayBufferTag:
                return cloneArrayBuffer(object);

              case boolTag:
              case dateTag:
                return new Ctor(+object);

              case dataViewTag:
                return cloneDataView(object, isDeep);

              case float32Tag:
              case float64Tag:
              case int8Tag:
              case int16Tag:
              case int32Tag:
              case uint8Tag:
              case uint8ClampedTag:
              case uint16Tag:
              case uint32Tag:
                return cloneTypedArray(object, isDeep);

              case mapTag:
                return new Ctor();

              case numberTag:
              case stringTag:
                return new Ctor(object);

              case regexpTag:
                return cloneRegExp(object);

              case setTag:
                return new Ctor();

              case symbolTag:
                return cloneSymbol(object);
            }
        }
        function insertWrapDetails(source, details) {
            var length = details.length;
            if (!length) {
                return source;
            }
            var lastIndex = length - 1;
            details[lastIndex] = (length > 1 ? "& " : "") + details[lastIndex];
            details = details.join(length > 2 ? ", " : " ");
            return source.replace(reWrapComment, "{\n/* [wrapped with " + details + "] */\n");
        }
        function isFlattenable(value) {
            return isArray(value) || isArguments(value) || !!(spreadableSymbol && value && value[spreadableSymbol]);
        }
        function isIndex(value, length) {
            var type = typeof value;
            length = length == null ? MAX_SAFE_INTEGER : length;
            return !!length && (type == "number" || type != "symbol" && reIsUint.test(value)) && (value > -1 && value % 1 == 0 && value < length);
        }
        function isIterateeCall(value, index, object) {
            if (!isObject(object)) {
                return false;
            }
            var type = typeof index;
            if (type == "number" ? isArrayLike(object) && isIndex(index, object.length) : type == "string" && index in object) {
                return eq(object[index], value);
            }
            return false;
        }
        function isKey(value, object) {
            if (isArray(value)) {
                return false;
            }
            var type = typeof value;
            if (type == "number" || type == "symbol" || type == "boolean" || value == null || isSymbol(value)) {
                return true;
            }
            return reIsPlainProp.test(value) || !reIsDeepProp.test(value) || object != null && value in Object(object);
        }
        function isKeyable(value) {
            var type = typeof value;
            return type == "string" || type == "number" || type == "symbol" || type == "boolean" ? value !== "__proto__" : value === null;
        }
        function isLaziable(func) {
            var funcName = getFuncName(func), other = lodash[funcName];
            if (typeof other != "function" || !(funcName in LazyWrapper.prototype)) {
                return false;
            }
            if (func === other) {
                return true;
            }
            var data = getData(other);
            return !!data && func === data[0];
        }
        function isMasked(func) {
            return !!maskSrcKey && maskSrcKey in func;
        }
        var isMaskable = coreJsData ? isFunction : stubFalse;
        function isPrototype(value) {
            var Ctor = value && value.constructor, proto = typeof Ctor == "function" && Ctor.prototype || objectProto;
            return value === proto;
        }
        function isStrictComparable(value) {
            return value === value && !isObject(value);
        }
        function matchesStrictComparable(key, srcValue) {
            return function(object) {
                if (object == null) {
                    return false;
                }
                return object[key] === srcValue && (srcValue !== undefined || key in Object(object));
            };
        }
        function memoizeCapped(func) {
            var result = memoize(func, function(key) {
                if (cache.size === MAX_MEMOIZE_SIZE) {
                    cache.clear();
                }
                return key;
            });
            var cache = result.cache;
            return result;
        }
        function mergeData(data, source) {
            var bitmask = data[1], srcBitmask = source[1], newBitmask = bitmask | srcBitmask, isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG);
            var isCombo = srcBitmask == WRAP_ARY_FLAG && bitmask == WRAP_CURRY_FLAG || srcBitmask == WRAP_ARY_FLAG && bitmask == WRAP_REARG_FLAG && data[7].length <= source[8] || srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG) && source[7].length <= source[8] && bitmask == WRAP_CURRY_FLAG;
            if (!(isCommon || isCombo)) {
                return data;
            }
            if (srcBitmask & WRAP_BIND_FLAG) {
                data[2] = source[2];
                newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG;
            }
            var value = source[3];
            if (value) {
                var partials = data[3];
                data[3] = partials ? composeArgs(partials, value, source[4]) : value;
                data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4];
            }
            value = source[5];
            if (value) {
                partials = data[5];
                data[5] = partials ? composeArgsRight(partials, value, source[6]) : value;
                data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6];
            }
            value = source[7];
            if (value) {
                data[7] = value;
            }
            if (srcBitmask & WRAP_ARY_FLAG) {
                data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
            }
            if (data[9] == null) {
                data[9] = source[9];
            }
            data[0] = source[0];
            data[1] = newBitmask;
            return data;
        }
        function nativeKeysIn(object) {
            var result = [];
            if (object != null) {
                for (var key in Object(object)) {
                    result.push(key);
                }
            }
            return result;
        }
        function objectToString(value) {
            return nativeObjectToString.call(value);
        }
        function overRest(func, start, transform) {
            start = nativeMax(start === undefined ? func.length - 1 : start, 0);
            return function() {
                var args = arguments, index = -1, length = nativeMax(args.length - start, 0), array = Array(length);
                while (++index < length) {
                    array[index] = args[start + index];
                }
                index = -1;
                var otherArgs = Array(start + 1);
                while (++index < start) {
                    otherArgs[index] = args[index];
                }
                otherArgs[start] = transform(array);
                return apply(func, this, otherArgs);
            };
        }
        function parent(object, path) {
            return path.length < 2 ? object : baseGet(object, baseSlice(path, 0, -1));
        }
        function reorder(array, indexes) {
            var arrLength = array.length, length = nativeMin(indexes.length, arrLength), oldArray = copyArray(array);
            while (length--) {
                var index = indexes[length];
                array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;
            }
            return array;
        }
        function safeGet(object, key) {
            if (key === "constructor" && typeof object[key] === "function") {
                return;
            }
            if (key == "__proto__") {
                return;
            }
            return object[key];
        }
        var setData = shortOut(baseSetData);
        var setTimeout = ctxSetTimeout || function(func, wait) {
            return root.setTimeout(func, wait);
        };
        var setToString = shortOut(baseSetToString);
        function setWrapToString(wrapper, reference, bitmask) {
            var source = reference + "";
            return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask)));
        }
        function shortOut(func) {
            var count = 0, lastCalled = 0;
            return function() {
                var stamp = nativeNow(), remaining = HOT_SPAN - (stamp - lastCalled);
                lastCalled = stamp;
                if (remaining > 0) {
                    if (++count >= HOT_COUNT) {
                        return arguments[0];
                    }
                } else {
                    count = 0;
                }
                return func.apply(undefined, arguments);
            };
        }
        function shuffleSelf(array, size) {
            var index = -1, length = array.length, lastIndex = length - 1;
            size = size === undefined ? length : size;
            while (++index < size) {
                var rand = baseRandom(index, lastIndex), value = array[rand];
                array[rand] = array[index];
                array[index] = value;
            }
            array.length = size;
            return array;
        }
        var stringToPath = memoizeCapped(function(string) {
            var result = [];
            if (string.charCodeAt(0) === 46) {
                result.push("");
            }
            string.replace(rePropName, function(match, number, quote, subString) {
                result.push(quote ? subString.replace(reEscapeChar, "$1") : number || match);
            });
            return result;
        });
        function toKey(value) {
            if (typeof value == "string" || isSymbol(value)) {
                return value;
            }
            var result = value + "";
            return result == "0" && 1 / value == -INFINITY ? "-0" : result;
        }
        function toSource(func) {
            if (func != null) {
                try {
                    return funcToString.call(func);
                } catch (e) {}
                try {
                    return func + "";
                } catch (e) {}
            }
            return "";
        }
        function updateWrapDetails(details, bitmask) {
            arrayEach(wrapFlags, function(pair) {
                var value = "_." + pair[0];
                if (bitmask & pair[1] && !arrayIncludes(details, value)) {
                    details.push(value);
                }
            });
            return details.sort();
        }
        function wrapperClone(wrapper) {
            if (wrapper instanceof LazyWrapper) {
                return wrapper.clone();
            }
            var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);
            result.__actions__ = copyArray(wrapper.__actions__);
            result.__index__ = wrapper.__index__;
            result.__values__ = wrapper.__values__;
            return result;
        }
        function chunk(array, size, guard) {
            if (guard ? isIterateeCall(array, size, guard) : size === undefined) {
                size = 1;
            } else {
                size = nativeMax(toInteger(size), 0);
            }
            var length = array == null ? 0 : array.length;
            if (!length || size < 1) {
                return [];
            }
            var index = 0, resIndex = 0, result = Array(nativeCeil(length / size));
            while (index < length) {
                result[resIndex++] = baseSlice(array, index, index += size);
            }
            return result;
        }
        function compact(array) {
            var index = -1, length = array == null ? 0 : array.length, resIndex = 0, result = [];
            while (++index < length) {
                var value = array[index];
                if (value) {
                    result[resIndex++] = value;
                }
            }
            return result;
        }
        function concat() {
            var length = arguments.length;
            if (!length) {
                return [];
            }
            var args = Array(length - 1), array = arguments[0], index = length;
            while (index--) {
                args[index - 1] = arguments[index];
            }
            return arrayPush(isArray(array) ? copyArray(array) : [ array ], baseFlatten(args, 1));
        }
        var difference = baseRest(function(array, values) {
            return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true)) : [];
        });
        var differenceBy = baseRest(function(array, values) {
            var iteratee = last(values);
            if (isArrayLikeObject(iteratee)) {
                iteratee = undefined;
            }
            return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2)) : [];
        });
        var differenceWith = baseRest(function(array, values) {
            var comparator = last(values);
            if (isArrayLikeObject(comparator)) {
                comparator = undefined;
            }
            return isArrayLikeObject(array) ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator) : [];
        });
        function drop(array, n, guard) {
            var length = array == null ? 0 : array.length;
            if (!length) {
                return [];
            }
            n = guard || n === undefined ? 1 : toInteger(n);
            return baseSlice(array, n < 0 ? 0 : n, length);
        }
        function dropRight(array, n, guard) {
            var length = array == null ? 0 : array.length;
            if (!length) {
                return [];
            }
            n = guard || n === undefined ? 1 : toInteger(n);
            n = length - n;
            return baseSlice(array, 0, n < 0 ? 0 : n);
        }
        function dropRightWhile(array, predicate) {
            return array && array.length ? baseWhile(array, getIteratee(predicate, 3), true, true) : [];
        }
        function dropWhile(array, predicate) {
            return array && array.length ? baseWhile(array, getIteratee(predicate, 3), true) : [];
        }
        function fill(array, value, start, end) {
            var length = array == null ? 0 : array.length;
            if (!length) {
                return [];
            }
            if (start && typeof start != "number" && isIterateeCall(array, value, start)) {
                start = 0;
                end = length;
            }
            return baseFill(array, value, start, end);
        }
        function findIndex(array, predicate, fromIndex) {
            var length = array == null ? 0 : array.length;
            if (!length) {
                return -1;
            }
            var index = fromIndex == null ? 0 : toInteger(fromIndex);
            if (index < 0) {
                index = nativeMax(length + index, 0);
            }
            return baseFindIndex(array, getIteratee(predicate, 3), index);
        }
        function findLastIndex(array, predicate, fromIndex) {
            var length = array == null ? 0 : array.length;
            if (!length) {
                return -1;
            }
            var index = length - 1;
            if (fromIndex !== undefined) {
                index = toInteger(fromIndex);
                index = fromIndex < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
            }
            return baseFindIndex(array, getIteratee(predicate, 3), index, true);
        }
        function flatten(array) {
            var length = array == null ? 0 : array.length;
            return length ? baseFlatten(array, 1) : [];
        }
        function flattenDeep(array) {
            var length = array == null ? 0 : array.length;
            return length ? baseFlatten(array, INFINITY) : [];
        }
        function flattenDepth(array, depth) {
            var length = array == null ? 0 : array.length;
            if (!length) {
                return [];
            }
            depth = depth === undefined ? 1 : toInteger(depth);
            return baseFlatten(array, depth);
        }
        function fromPairs(pairs) {
            var index = -1, length = pairs == null ? 0 : pairs.length, result = {};
            while (++index < length) {
                var pair = pairs[index];
                result[pair[0]] = pair[1];
            }
            return result;
        }
        function head(array) {
            return array && array.length ? array[0] : undefined;
        }
        function indexOf(array, value, fromIndex) {
            var length = array == null ? 0 : array.length;
            if (!length) {
                return -1;
            }
            var index = fromIndex == null ? 0 : toInteger(fromIndex);
            if (index < 0) {
                index = nativeMax(length + index, 0);
            }
            return baseIndexOf(array, value, index);
        }
        function initial(array) {
            var length = array == null ? 0 : array.length;
            return length ? baseSlice(array, 0, -1) : [];
        }
        var intersection = baseRest(function(arrays) {
            var mapped = arrayMap(arrays, castArrayLikeObject);
            return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped) : [];
        });
        var intersectionBy = baseRest(function(arrays) {
            var iteratee = last(arrays), mapped = arrayMap(arrays, castArrayLikeObject);
            if (iteratee === last(mapped)) {
                iteratee = undefined;
            } else {
                mapped.pop();
            }
            return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped, getIteratee(iteratee, 2)) : [];
        });
        var intersectionWith = baseRest(function(arrays) {
            var comparator = last(arrays), mapped = arrayMap(arrays, castArrayLikeObject);
            comparator = typeof comparator == "function" ? comparator : undefined;
            if (comparator) {
                mapped.pop();
            }
            return mapped.length && mapped[0] === arrays[0] ? baseIntersection(mapped, undefined, comparator) : [];
        });
        function join(array, separator) {
            return array == null ? "" : nativeJoin.call(array, separator);
        }
        function last(array) {
            var length = array == null ? 0 : array.length;
            return length ? array[length - 1] : undefined;
        }
        function lastIndexOf(array, value, fromIndex) {
            var length = array == null ? 0 : array.length;
            if (!length) {
                return -1;
            }
            var index = length;
            if (fromIndex !== undefined) {
                index = toInteger(fromIndex);
                index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
            }
            return value === value ? strictLastIndexOf(array, value, index) : baseFindIndex(array, baseIsNaN, index, true);
        }
        function nth(array, n) {
            return array && array.length ? baseNth(array, toInteger(n)) : undefined;
        }
        var pull = baseRest(pullAll);
        function pullAll(array, values) {
            return array && array.length && values && values.length ? basePullAll(array, values) : array;
        }
        function pullAllBy(array, values, iteratee) {
            return array && array.length && values && values.length ? basePullAll(array, values, getIteratee(iteratee, 2)) : array;
        }
        function pullAllWith(array, values, comparator) {
            return array && array.length && values && values.length ? basePullAll(array, values, undefined, comparator) : array;
        }
        var pullAt = flatRest(function(array, indexes) {
            var length = array == null ? 0 : array.length, result = baseAt(array, indexes);
            basePullAt(array, arrayMap(indexes, function(index) {
                return isIndex(index, length) ? +index : index;
            }).sort(compareAscending));
            return result;
        });
        function remove(array, predicate) {
            var result = [];
            if (!(array && array.length)) {
                return result;
            }
            var index = -1, indexes = [], length = array.length;
            predicate = getIteratee(predicate, 3);
            while (++index < length) {
                var value = array[index];
                if (predicate(value, index, array)) {
                    result.push(value);
                    indexes.push(index);
                }
            }
            basePullAt(array, indexes);
            return result;
        }
        function reverse(array) {
            return array == null ? array : nativeReverse.call(array);
        }
        function slice(array, start, end) {
            var length = array == null ? 0 : array.length;
            if (!length) {
                return [];
            }
            if (end && typeof end != "number" && isIterateeCall(array, start, end)) {
                start = 0;
                end = length;
            } else {
                start = start == null ? 0 : toInteger(start);
                end = end === undefined ? length : toInteger(end);
            }
            return baseSlice(array, start, end);
        }
        function sortedIndex(array, value) {
            return baseSortedIndex(array, value);
        }
        function sortedIndexBy(array, value, iteratee) {
            return baseSortedIndexBy(array, value, getIteratee(iteratee, 2));
        }
        function sortedIndexOf(array, value) {
            var length = array == null ? 0 : array.length;
            if (length) {
                var index = baseSortedIndex(array, value);
                if (index < length && eq(array[index], value)) {
                    return index;
                }
            }
            return -1;
        }
        function sortedLastIndex(array, value) {
            return baseSortedIndex(array, value, true);
        }
        function sortedLastIndexBy(array, value, iteratee) {
            return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true);
        }
        function sortedLastIndexOf(array, value) {
            var length = array == null ? 0 : array.length;
            if (length) {
                var index = baseSortedIndex(array, value, true) - 1;
                if (eq(array[index], value)) {
                    return index;
                }
            }
            return -1;
        }
        function sortedUniq(array) {
            return array && array.length ? baseSortedUniq(array) : [];
        }
        function sortedUniqBy(array, iteratee) {
            return array && array.length ? baseSortedUniq(array, getIteratee(iteratee, 2)) : [];
        }
        function tail(array) {
            var length = array == null ? 0 : array.length;
            return length ? baseSlice(array, 1, length) : [];
        }
        function take(array, n, guard) {
            if (!(array && array.length)) {
                return [];
            }
            n = guard || n === undefined ? 1 : toInteger(n);
            return baseSlice(array, 0, n < 0 ? 0 : n);
        }
        function takeRight(array, n, guard) {
            var length = array == null ? 0 : array.length;
            if (!length) {
                return [];
            }
            n = guard || n === undefined ? 1 : toInteger(n);
            n = length - n;
            return baseSlice(array, n < 0 ? 0 : n, length);
        }
        function takeRightWhile(array, predicate) {
            return array && array.length ? baseWhile(array, getIteratee(predicate, 3), false, true) : [];
        }
        function takeWhile(array, predicate) {
            return array && array.length ? baseWhile(array, getIteratee(predicate, 3)) : [];
        }
        var union = baseRest(function(arrays) {
            return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));
        });
        var unionBy = baseRest(function(arrays) {
            var iteratee = last(arrays);
            if (isArrayLikeObject(iteratee)) {
                iteratee = undefined;
            }
            return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2));
        });
        var unionWith = baseRest(function(arrays) {
            var comparator = last(arrays);
            comparator = typeof comparator == "function" ? comparator : undefined;
            return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator);
        });
        function uniq(array) {
            return array && array.length ? baseUniq(array) : [];
        }
        function uniqBy(array, iteratee) {
            return array && array.length ? baseUniq(array, getIteratee(iteratee, 2)) : [];
        }
        function uniqWith(array, comparator) {
            comparator = typeof comparator == "function" ? comparator : undefined;
            return array && array.length ? baseUniq(array, undefined, comparator) : [];
        }
        function unzip(array) {
            if (!(array && array.length)) {
                return [];
            }
            var length = 0;
            array = arrayFilter(array, function(group) {
                if (isArrayLikeObject(group)) {
                    length = nativeMax(group.length, length);
                    return true;
                }
            });
            return baseTimes(length, function(index) {
                return arrayMap(array, baseProperty(index));
            });
        }
        function unzipWith(array, iteratee) {
            if (!(array && array.length)) {
                return [];
            }
            var result = unzip(array);
            if (iteratee == null) {
                return result;
            }
            return arrayMap(result, function(group) {
                return apply(iteratee, undefined, group);
            });
        }
        var without = baseRest(function(array, values) {
            return isArrayLikeObject(array) ? baseDifference(array, values) : [];
        });
        var xor = baseRest(function(arrays) {
            return baseXor(arrayFilter(arrays, isArrayLikeObject));
        });
        var xorBy = baseRest(function(arrays) {
            var iteratee = last(arrays);
            if (isArrayLikeObject(iteratee)) {
                iteratee = undefined;
            }
            return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2));
        });
        var xorWith = baseRest(function(arrays) {
            var comparator = last(arrays);
            comparator = typeof comparator == "function" ? comparator : undefined;
            return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator);
        });
        var zip = baseRest(unzip);
        function zipObject(props, values) {
            return baseZipObject(props || [], values || [], assignValue);
        }
        function zipObjectDeep(props, values) {
            return baseZipObject(props || [], values || [], baseSet);
        }
        var zipWith = baseRest(function(arrays) {
            var length = arrays.length, iteratee = length > 1 ? arrays[length - 1] : undefined;
            iteratee = typeof iteratee == "function" ? (arrays.pop(), iteratee) : undefined;
            return unzipWith(arrays, iteratee);
        });
        function chain(value) {
            var result = lodash(value);
            result.__chain__ = true;
            return result;
        }
        function tap(value, interceptor) {
            interceptor(value);
            return value;
        }
        function thru(value, interceptor) {
            return interceptor(value);
        }
        var wrapperAt = flatRest(function(paths) {
            var length = paths.length, start = length ? paths[0] : 0, value = this.__wrapped__, interceptor = function(object) {
                return baseAt(object, paths);
            };
            if (length > 1 || this.__actions__.length || !(value instanceof LazyWrapper) || !isIndex(start)) {
                return this.thru(interceptor);
            }
            value = value.slice(start, +start + (length ? 1 : 0));
            value.__actions__.push({
                func: thru,
                args: [ interceptor ],
                thisArg: undefined
            });
            return new LodashWrapper(value, this.__chain__).thru(function(array) {
                if (length && !array.length) {
                    array.push(undefined);
                }
                return array;
            });
        });
        function wrapperChain() {
            return chain(this);
        }
        function wrapperCommit() {
            return new LodashWrapper(this.value(), this.__chain__);
        }
        function wrapperNext() {
            if (this.__values__ === undefined) {
                this.__values__ = toArray(this.value());
            }
            var done = this.__index__ >= this.__values__.length, value = done ? undefined : this.__values__[this.__index__++];
            return {
                done: done,
                value: value
            };
        }
        function wrapperToIterator() {
            return this;
        }
        function wrapperPlant(value) {
            var result, parent = this;
            while (parent instanceof baseLodash) {
                var clone = wrapperClone(parent);
                clone.__index__ = 0;
                clone.__values__ = undefined;
                if (result) {
                    previous.__wrapped__ = clone;
                } else {
                    result = clone;
                }
                var previous = clone;
                parent = parent.__wrapped__;
            }
            previous.__wrapped__ = value;
            return result;
        }
        function wrapperReverse() {
            var value = this.__wrapped__;
            if (value instanceof LazyWrapper) {
                var wrapped = value;
                if (this.__actions__.length) {
                    wrapped = new LazyWrapper(this);
                }
                wrapped = wrapped.reverse();
                wrapped.__actions__.push({
                    func: thru,
                    args: [ reverse ],
                    thisArg: undefined
                });
                return new LodashWrapper(wrapped, this.__chain__);
            }
            return this.thru(reverse);
        }
        function wrapperValue() {
            return baseWrapperValue(this.__wrapped__, this.__actions__);
        }
        var countBy = createAggregator(function(result, value, key) {
            if (hasOwnProperty.call(result, key)) {
                ++result[key];
            } else {
                baseAssignValue(result, key, 1);
            }
        });
        function every(collection, predicate, guard) {
            var func = isArray(collection) ? arrayEvery : baseEvery;
            if (guard && isIterateeCall(collection, predicate, guard)) {
                predicate = undefined;
            }
            return func(collection, getIteratee(predicate, 3));
        }
        function filter(collection, predicate) {
            var func = isArray(collection) ? arrayFilter : baseFilter;
            return func(collection, getIteratee(predicate, 3));
        }
        var find = createFind(findIndex);
        var findLast = createFind(findLastIndex);
        function flatMap(collection, iteratee) {
            return baseFlatten(map(collection, iteratee), 1);
        }
        function flatMapDeep(collection, iteratee) {
            return baseFlatten(map(collection, iteratee), INFINITY);
        }
        function flatMapDepth(collection, iteratee, depth) {
            depth = depth === undefined ? 1 : toInteger(depth);
            return baseFlatten(map(collection, iteratee), depth);
        }
        function forEach(collection, iteratee) {
            var func = isArray(collection) ? arrayEach : baseEach;
            return func(collection, getIteratee(iteratee, 3));
        }
        function forEachRight(collection, iteratee) {
            var func = isArray(collection) ? arrayEachRight : baseEachRight;
            return func(collection, getIteratee(iteratee, 3));
        }
        var groupBy = createAggregator(function(result, value, key) {
            if (hasOwnProperty.call(result, key)) {
                result[key].push(value);
            } else {
                baseAssignValue(result, key, [ value ]);
            }
        });
        function includes(collection, value, fromIndex, guard) {
            collection = isArrayLike(collection) ? collection : values(collection);
            fromIndex = fromIndex && !guard ? toInteger(fromIndex) : 0;
            var length = collection.length;
            if (fromIndex < 0) {
                fromIndex = nativeMax(length + fromIndex, 0);
            }
            return isString(collection) ? fromIndex <= length && collection.indexOf(value, fromIndex) > -1 : !!length && baseIndexOf(collection, value, fromIndex) > -1;
        }
        var invokeMap = baseRest(function(collection, path, args) {
            var index = -1, isFunc = typeof path == "function", result = isArrayLike(collection) ? Array(collection.length) : [];
            baseEach(collection, function(value) {
                result[++index] = isFunc ? apply(path, value, args) : baseInvoke(value, path, args);
            });
            return result;
        });
        var keyBy = createAggregator(function(result, value, key) {
            baseAssignValue(result, key, value);
        });
        function map(collection, iteratee) {
            var func = isArray(collection) ? arrayMap : baseMap;
            return func(collection, getIteratee(iteratee, 3));
        }
        function orderBy(collection, iteratees, orders, guard) {
            if (collection == null) {
                return [];
            }
            if (!isArray(iteratees)) {
                iteratees = iteratees == null ? [] : [ iteratees ];
            }
            orders = guard ? undefined : orders;
            if (!isArray(orders)) {
                orders = orders == null ? [] : [ orders ];
            }
            return baseOrderBy(collection, iteratees, orders);
        }
        var partition = createAggregator(function(result, value, key) {
            result[key ? 0 : 1].push(value);
        }, function() {
            return [ [], [] ];
        });
        function reduce(collection, iteratee, accumulator) {
            var func = isArray(collection) ? arrayReduce : baseReduce, initAccum = arguments.length < 3;
            return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach);
        }
        function reduceRight(collection, iteratee, accumulator) {
            var func = isArray(collection) ? arrayReduceRight : baseReduce, initAccum = arguments.length < 3;
            return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight);
        }
        function reject(collection, predicate) {
            var func = isArray(collection) ? arrayFilter : baseFilter;
            return func(collection, negate(getIteratee(predicate, 3)));
        }
        function sample(collection) {
            var func = isArray(collection) ? arraySample : baseSample;
            return func(collection);
        }
        function sampleSize(collection, n, guard) {
            if (guard ? isIterateeCall(collection, n, guard) : n === undefined) {
                n = 1;
            } else {
                n = toInteger(n);
            }
            var func = isArray(collection) ? arraySampleSize : baseSampleSize;
            return func(collection, n);
        }
        function shuffle(collection) {
            var func = isArray(collection) ? arrayShuffle : baseShuffle;
            return func(collection);
        }
        function size(collection) {
            if (collection == null) {
                return 0;
            }
            if (isArrayLike(collection)) {
                return isString(collection) ? stringSize(collection) : collection.length;
            }
            var tag = getTag(collection);
            if (tag == mapTag || tag == setTag) {
                return collection.size;
            }
            return baseKeys(collection).length;
        }
        function some(collection, predicate, guard) {
            var func = isArray(collection) ? arraySome : baseSome;
            if (guard && isIterateeCall(collection, predicate, guard)) {
                predicate = undefined;
            }
            return func(collection, getIteratee(predicate, 3));
        }
        var sortBy = baseRest(function(collection, iteratees) {
            if (collection == null) {
                return [];
            }
            var length = iteratees.length;
            if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {
                iteratees = [];
            } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {
                iteratees = [ iteratees[0] ];
            }
            return baseOrderBy(collection, baseFlatten(iteratees, 1), []);
        });
        var now = ctxNow || function() {
            return root.Date.now();
        };
        function after(n, func) {
            if (typeof func != "function") {
                throw new TypeError(FUNC_ERROR_TEXT);
            }
            n = toInteger(n);
            return function() {
                if (--n < 1) {
                    return func.apply(this, arguments);
                }
            };
        }
        function ary(func, n, guard) {
            n = guard ? undefined : n;
            n = func && n == null ? func.length : n;
            return createWrap(func, WRAP_ARY_FLAG, undefined, undefined, undefined, undefined, n);
        }
        function before(n, func) {
            var result;
            if (typeof func != "function") {
                throw new TypeError(FUNC_ERROR_TEXT);
            }
            n = toInteger(n);
            return function() {
                if (--n > 0) {
                    result = func.apply(this, arguments);
                }
                if (n <= 1) {
                    func = undefined;
                }
                return result;
            };
        }
        var bind = baseRest(function(func, thisArg, partials) {
            var bitmask = WRAP_BIND_FLAG;
            if (partials.length) {
                var holders = replaceHolders(partials, getHolder(bind));
                bitmask |= WRAP_PARTIAL_FLAG;
            }
            return createWrap(func, bitmask, thisArg, partials, holders);
        });
        var bindKey = baseRest(function(object, key, partials) {
            var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG;
            if (partials.length) {
                var holders = replaceHolders(partials, getHolder(bindKey));
                bitmask |= WRAP_PARTIAL_FLAG;
            }
            return createWrap(key, bitmask, object, partials, holders);
        });
        function curry(func, arity, guard) {
            arity = guard ? undefined : arity;
            var result = createWrap(func, WRAP_CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
            result.placeholder = curry.placeholder;
            return result;
        }
        function curryRight(func, arity, guard) {
            arity = guard ? undefined : arity;
            var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
            result.placeholder = curryRight.placeholder;
            return result;
        }
        function debounce(func, wait, options) {
            var lastArgs, lastThis, maxWait, result, timerId, lastCallTime, lastInvokeTime = 0, leading = false, maxing = false, trailing = true;
            if (typeof func != "function") {
                throw new TypeError(FUNC_ERROR_TEXT);
            }
            wait = toNumber(wait) || 0;
            if (isObject(options)) {
                leading = !!options.leading;
                maxing = "maxWait" in options;
                maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
                trailing = "trailing" in options ? !!options.trailing : trailing;
            }
            function invokeFunc(time) {
                var args = lastArgs, thisArg = lastThis;
                lastArgs = lastThis = undefined;
                lastInvokeTime = time;
                result = func.apply(thisArg, args);
                return result;
            }
            function leadingEdge(time) {
                lastInvokeTime = time;
                timerId = setTimeout(timerExpired, wait);
                return leading ? invokeFunc(time) : result;
            }
            function remainingWait(time) {
                var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime, timeWaiting = wait - timeSinceLastCall;
                return maxing ? nativeMin(timeWaiting, maxWait - timeSinceLastInvoke) : timeWaiting;
            }
            function shouldInvoke(time) {
                var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime;
                return lastCallTime === undefined || timeSinceLastCall >= wait || timeSinceLastCall < 0 || maxing && timeSinceLastInvoke >= maxWait;
            }
            function timerExpired() {
                var time = now();
                if (shouldInvoke(time)) {
                    return trailingEdge(time);
                }
                timerId = setTimeout(timerExpired, remainingWait(time));
            }
            function trailingEdge(time) {
                timerId = undefined;
                if (trailing && lastArgs) {
                    return invokeFunc(time);
                }
                lastArgs = lastThis = undefined;
                return result;
            }
            function cancel() {
                if (timerId !== undefined) {
                    clearTimeout(timerId);
                }
                lastInvokeTime = 0;
                lastArgs = lastCallTime = lastThis = timerId = undefined;
            }
            function flush() {
                return timerId === undefined ? result : trailingEdge(now());
            }
            function debounced() {
                var time = now(), isInvoking = shouldInvoke(time);
                lastArgs = arguments;
                lastThis = this;
                lastCallTime = time;
                if (isInvoking) {
                    if (timerId === undefined) {
                        return leadingEdge(lastCallTime);
                    }
                    if (maxing) {
                        clearTimeout(timerId);
                        timerId = setTimeout(timerExpired, wait);
                        return invokeFunc(lastCallTime);
                    }
                }
                if (timerId === undefined) {
                    timerId = setTimeout(timerExpired, wait);
                }
                return result;
            }
            debounced.cancel = cancel;
            debounced.flush = flush;
            return debounced;
        }
        var defer = baseRest(function(func, args) {
            return baseDelay(func, 1, args);
        });
        var delay = baseRest(function(func, wait, args) {
            return baseDelay(func, toNumber(wait) || 0, args);
        });
        function flip(func) {
            return createWrap(func, WRAP_FLIP_FLAG);
        }
        function memoize(func, resolver) {
            if (typeof func != "function" || resolver != null && typeof resolver != "function") {
                throw new TypeError(FUNC_ERROR_TEXT);
            }
            var memoized = function() {
                var args = arguments, key = resolver ? resolver.apply(this, args) : args[0], cache = memoized.cache;
                if (cache.has(key)) {
                    return cache.get(key);
                }
                var result = func.apply(this, args);
                memoized.cache = cache.set(key, result) || cache;
                return result;
            };
            memoized.cache = new (memoize.Cache || MapCache)();
            return memoized;
        }
        memoize.Cache = MapCache;
        function negate(predicate) {
            if (typeof predicate != "function") {
                throw new TypeError(FUNC_ERROR_TEXT);
            }
            return function() {
                var args = arguments;
                switch (args.length) {
                  case 0:
                    return !predicate.call(this);

                  case 1:
                    return !predicate.call(this, args[0]);

                  case 2:
                    return !predicate.call(this, args[0], args[1]);

                  case 3:
                    return !predicate.call(this, args[0], args[1], args[2]);
                }
                return !predicate.apply(this, args);
            };
        }
        function once(func) {
            return before(2, func);
        }
        var overArgs = castRest(function(func, transforms) {
            transforms = transforms.length == 1 && isArray(transforms[0]) ? arrayMap(transforms[0], baseUnary(getIteratee())) : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee()));
            var funcsLength = transforms.length;
            return baseRest(function(args) {
                var index = -1, length = nativeMin(args.length, funcsLength);
                while (++index < length) {
                    args[index] = transforms[index].call(this, args[index]);
                }
                return apply(func, this, args);
            });
        });
        var partial = baseRest(function(func, partials) {
            var holders = replaceHolders(partials, getHolder(partial));
            return createWrap(func, WRAP_PARTIAL_FLAG, undefined, partials, holders);
        });
        var partialRight = baseRest(function(func, partials) {
            var holders = replaceHolders(partials, getHolder(partialRight));
            return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined, partials, holders);
        });
        var rearg = flatRest(function(func, indexes) {
            return createWrap(func, WRAP_REARG_FLAG, undefined, undefined, undefined, indexes);
        });
        function rest(func, start) {
            if (typeof func != "function") {
                throw new TypeError(FUNC_ERROR_TEXT);
            }
            start = start === undefined ? start : toInteger(start);
            return baseRest(func, start);
        }
        function spread(func, start) {
            if (typeof func != "function") {
                throw new TypeError(FUNC_ERROR_TEXT);
            }
            start = start == null ? 0 : nativeMax(toInteger(start), 0);
            return baseRest(function(args) {
                var array = args[start], otherArgs = castSlice(args, 0, start);
                if (array) {
                    arrayPush(otherArgs, array);
                }
                return apply(func, this, otherArgs);
            });
        }
        function throttle(func, wait, options) {
            var leading = true, trailing = true;
            if (typeof func != "function") {
                throw new TypeError(FUNC_ERROR_TEXT);
            }
            if (isObject(options)) {
                leading = "leading" in options ? !!options.leading : leading;
                trailing = "trailing" in options ? !!options.trailing : trailing;
            }
            return debounce(func, wait, {
                leading: leading,
                maxWait: wait,
                trailing: trailing
            });
        }
        function unary(func) {
            return ary(func, 1);
        }
        function wrap(value, wrapper) {
            return partial(castFunction(wrapper), value);
        }
        function castArray() {
            if (!arguments.length) {
                return [];
            }
            var value = arguments[0];
            return isArray(value) ? value : [ value ];
        }
        function clone(value) {
            return baseClone(value, CLONE_SYMBOLS_FLAG);
        }
        function cloneWith(value, customizer) {
            customizer = typeof customizer == "function" ? customizer : undefined;
            return baseClone(value, CLONE_SYMBOLS_FLAG, customizer);
        }
        function cloneDeep(value) {
            return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);
        }
        function cloneDeepWith(value, customizer) {
            customizer = typeof customizer == "function" ? customizer : undefined;
            return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer);
        }
        function conformsTo(object, source) {
            return source == null || baseConformsTo(object, source, keys(source));
        }
        function eq(value, other) {
            return value === other || value !== value && other !== other;
        }
        var gt = createRelationalOperation(baseGt);
        var gte = createRelationalOperation(function(value, other) {
            return value >= other;
        });
        var isArguments = baseIsArguments(function() {
            return arguments;
        }()) ? baseIsArguments : function(value) {
            return isObjectLike(value) && hasOwnProperty.call(value, "callee") && !propertyIsEnumerable.call(value, "callee");
        };
        var isArray = Array.isArray;
        var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer;
        function isArrayLike(value) {
            return value != null && isLength(value.length) && !isFunction(value);
        }
        function isArrayLikeObject(value) {
            return isObjectLike(value) && isArrayLike(value);
        }
        function isBoolean(value) {
            return value === true || value === false || isObjectLike(value) && baseGetTag(value) == boolTag;
        }
        var isBuffer = nativeIsBuffer || stubFalse;
        var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;
        function isElement(value) {
            return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value);
        }
        function isEmpty(value) {
            if (value == null) {
                return true;
            }
            if (isArrayLike(value) && (isArray(value) || typeof value == "string" || typeof value.splice == "function" || isBuffer(value) || isTypedArray(value) || isArguments(value))) {
                return !value.length;
            }
            var tag = getTag(value);
            if (tag == mapTag || tag == setTag) {
                return !value.size;
            }
            if (isPrototype(value)) {
                return !baseKeys(value).length;
            }
            for (var key in value) {
                if (hasOwnProperty.call(value, key)) {
                    return false;
                }
            }
            return true;
        }
        function isEqual(value, other) {
            return baseIsEqual(value, other);
        }
        function isEqualWith(value, other, customizer) {
            customizer = typeof customizer == "function" ? customizer : undefined;
            var result = customizer ? customizer(value, other) : undefined;
            return result === undefined ? baseIsEqual(value, other, undefined, customizer) : !!result;
        }
        function isError(value) {
            if (!isObjectLike(value)) {
                return false;
            }
            var tag = baseGetTag(value);
            return tag == errorTag || tag == domExcTag || typeof value.message == "string" && typeof value.name == "string" && !isPlainObject(value);
        }
        function isFinite(value) {
            return typeof value == "number" && nativeIsFinite(value);
        }
        function isFunction(value) {
            if (!isObject(value)) {
                return false;
            }
            var tag = baseGetTag(value);
            return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
        }
        function isInteger(value) {
            return typeof value == "number" && value == toInteger(value);
        }
        function isLength(value) {
            return typeof value == "number" && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
        }
        function isObject(value) {
            var type = typeof value;
            return value != null && (type == "object" || type == "function");
        }
        function isObjectLike(value) {
            return value != null && typeof value == "object";
        }
        var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;
        function isMatch(object, source) {
            return object === source || baseIsMatch(object, source, getMatchData(source));
        }
        function isMatchWith(object, source, customizer) {
            customizer = typeof customizer == "function" ? customizer : undefined;
            return baseIsMatch(object, source, getMatchData(source), customizer);
        }
        function isNaN(value) {
            return isNumber(value) && value != +value;
        }
        function isNative(value) {
            if (isMaskable(value)) {
                throw new Error(CORE_ERROR_TEXT);
            }
            return baseIsNative(value);
        }
        function isNull(value) {
            return value === null;
        }
        function isNil(value) {
            return value == null;
        }
        function isNumber(value) {
            return typeof value == "number" || isObjectLike(value) && baseGetTag(value) == numberTag;
        }
        function isPlainObject(value) {
            if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
                return false;
            }
            var proto = getPrototype(value);
            if (proto === null) {
                return true;
            }
            var Ctor = hasOwnProperty.call(proto, "constructor") && proto.constructor;
            return typeof Ctor == "function" && Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString;
        }
        var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp;
        function isSafeInteger(value) {
            return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;
        }
        var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;
        function isString(value) {
            return typeof value == "string" || !isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag;
        }
        function isSymbol(value) {
            return typeof value == "symbol" || isObjectLike(value) && baseGetTag(value) == symbolTag;
        }
        var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
        function isUndefined(value) {
            return value === undefined;
        }
        function isWeakMap(value) {
            return isObjectLike(value) && getTag(value) == weakMapTag;
        }
        function isWeakSet(value) {
            return isObjectLike(value) && baseGetTag(value) == weakSetTag;
        }
        var lt = createRelationalOperation(baseLt);
        var lte = createRelationalOperation(function(value, other) {
            return value <= other;
        });
        function toArray(value) {
            if (!value) {
                return [];
            }
            if (isArrayLike(value)) {
                return isString(value) ? stringToArray(value) : copyArray(value);
            }
            if (symIterator && value[symIterator]) {
                return iteratorToArray(value[symIterator]());
            }
            var tag = getTag(value), func = tag == mapTag ? mapToArray : tag == setTag ? setToArray : values;
            return func(value);
        }
        function toFinite(value) {
            if (!value) {
                return value === 0 ? value : 0;
            }
            value = toNumber(value);
            if (value === INFINITY || value === -INFINITY) {
                var sign = value < 0 ? -1 : 1;
                return sign * MAX_INTEGER;
            }
            return value === value ? value : 0;
        }
        function toInteger(value) {
            var result = toFinite(value), remainder = result % 1;
            return result === result ? remainder ? result - remainder : result : 0;
        }
        function toLength(value) {
            return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0;
        }
        function toNumber(value) {
            if (typeof value == "number") {
                return value;
            }
            if (isSymbol(value)) {
                return NAN;
            }
            if (isObject(value)) {
                var other = typeof value.valueOf == "function" ? value.valueOf() : value;
                value = isObject(other) ? other + "" : other;
            }
            if (typeof value != "string") {
                return value === 0 ? value : +value;
            }
            value = baseTrim(value);
            var isBinary = reIsBinary.test(value);
            return isBinary || reIsOctal.test(value) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : reIsBadHex.test(value) ? NAN : +value;
        }
        function toPlainObject(value) {
            return copyObject(value, keysIn(value));
        }
        function toSafeInteger(value) {
            return value ? baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER) : value === 0 ? value : 0;
        }
        function toString(value) {
            return value == null ? "" : baseToString(value);
        }
        var assign = createAssigner(function(object, source) {
            if (isPrototype(source) || isArrayLike(source)) {
                copyObject(source, keys(source), object);
                return;
            }
            for (var key in source) {
                if (hasOwnProperty.call(source, key)) {
                    assignValue(object, key, source[key]);
                }
            }
        });
        var assignIn = createAssigner(function(object, source) {
            copyObject(source, keysIn(source), object);
        });
        var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {
            copyObject(source, keysIn(source), object, customizer);
        });
        var assignWith = createAssigner(function(object, source, srcIndex, customizer) {
            copyObject(source, keys(source), object, customizer);
        });
        var at = flatRest(baseAt);
        function create(prototype, properties) {
            var result = baseCreate(prototype);
            return properties == null ? result : baseAssign(result, properties);
        }
        var defaults = baseRest(function(object, sources) {
            object = Object(object);
            var index = -1;
            var length = sources.length;
            var guard = length > 2 ? sources[2] : undefined;
            if (guard && isIterateeCall(sources[0], sources[1], guard)) {
                length = 1;
            }
            while (++index < length) {
                var source = sources[index];
                var props = keysIn(source);
                var propsIndex = -1;
                var propsLength = props.length;
                while (++propsIndex < propsLength) {
                    var key = props[propsIndex];
                    var value = object[key];
                    if (value === undefined || eq(value, objectProto[key]) && !hasOwnProperty.call(object, key)) {
                        object[key] = source[key];
                    }
                }
            }
            return object;
        });
        var defaultsDeep = baseRest(function(args) {
            args.push(undefined, customDefaultsMerge);
            return apply(mergeWith, undefined, args);
        });
        function findKey(object, predicate) {
            return baseFindKey(object, getIteratee(predicate, 3), baseForOwn);
        }
        function findLastKey(object, predicate) {
            return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight);
        }
        function forIn(object, iteratee) {
            return object == null ? object : baseFor(object, getIteratee(iteratee, 3), keysIn);
        }
        function forInRight(object, iteratee) {
            return object == null ? object : baseForRight(object, getIteratee(iteratee, 3), keysIn);
        }
        function forOwn(object, iteratee) {
            return object && baseForOwn(object, getIteratee(iteratee, 3));
        }
        function forOwnRight(object, iteratee) {
            return object && baseForOwnRight(object, getIteratee(iteratee, 3));
        }
        function functions(object) {
            return object == null ? [] : baseFunctions(object, keys(object));
        }
        function functionsIn(object) {
            return object == null ? [] : baseFunctions(object, keysIn(object));
        }
        function get(object, path, defaultValue) {
            var result = object == null ? undefined : baseGet(object, path);
            return result === undefined ? defaultValue : result;
        }
        function has(object, path) {
            return object != null && hasPath(object, path, baseHas);
        }
        function hasIn(object, path) {
            return object != null && hasPath(object, path, baseHasIn);
        }
        var invert = createInverter(function(result, value, key) {
            if (value != null && typeof value.toString != "function") {
                value = nativeObjectToString.call(value);
            }
            result[value] = key;
        }, constant(identity));
        var invertBy = createInverter(function(result, value, key) {
            if (value != null && typeof value.toString != "function") {
                value = nativeObjectToString.call(value);
            }
            if (hasOwnProperty.call(result, value)) {
                result[value].push(key);
            } else {
                result[value] = [ key ];
            }
        }, getIteratee);
        var invoke = baseRest(baseInvoke);
        function keys(object) {
            return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
        }
        function keysIn(object) {
            return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
        }
        function mapKeys(object, iteratee) {
            var result = {};
            iteratee = getIteratee(iteratee, 3);
            baseForOwn(object, function(value, key, object) {
                baseAssignValue(result, iteratee(value, key, object), value);
            });
            return result;
        }
        function mapValues(object, iteratee) {
            var result = {};
            iteratee = getIteratee(iteratee, 3);
            baseForOwn(object, function(value, key, object) {
                baseAssignValue(result, key, iteratee(value, key, object));
            });
            return result;
        }
        var merge = createAssigner(function(object, source, srcIndex) {
            baseMerge(object, source, srcIndex);
        });
        var mergeWith = createAssigner(function(object, source, srcIndex, customizer) {
            baseMerge(object, source, srcIndex, customizer);
        });
        var omit = flatRest(function(object, paths) {
            var result = {};
            if (object == null) {
                return result;
            }
            var isDeep = false;
            paths = arrayMap(paths, function(path) {
                path = castPath(path, object);
                isDeep || (isDeep = path.length > 1);
                return path;
            });
            copyObject(object, getAllKeysIn(object), result);
            if (isDeep) {
                result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG, customOmitClone);
            }
            var length = paths.length;
            while (length--) {
                baseUnset(result, paths[length]);
            }
            return result;
        });
        function omitBy(object, predicate) {
            return pickBy(object, negate(getIteratee(predicate)));
        }
        var pick = flatRest(function(object, paths) {
            return object == null ? {} : basePick(object, paths);
        });
        function pickBy(object, predicate) {
            if (object == null) {
                return {};
            }
            var props = arrayMap(getAllKeysIn(object), function(prop) {
                return [ prop ];
            });
            predicate = getIteratee(predicate);
            return basePickBy(object, props, function(value, path) {
                return predicate(value, path[0]);
            });
        }
        function result(object, path, defaultValue) {
            path = castPath(path, object);
            var index = -1, length = path.length;
            if (!length) {
                length = 1;
                object = undefined;
            }
            while (++index < length) {
                var value = object == null ? undefined : object[toKey(path[index])];
                if (value === undefined) {
                    index = length;
                    value = defaultValue;
                }
                object = isFunction(value) ? value.call(object) : value;
            }
            return object;
        }
        function set(object, path, value) {
            return object == null ? object : baseSet(object, path, value);
        }
        function setWith(object, path, value, customizer) {
            customizer = typeof customizer == "function" ? customizer : undefined;
            return object == null ? object : baseSet(object, path, value, customizer);
        }
        var toPairs = createToPairs(keys);
        var toPairsIn = createToPairs(keysIn);
        function transform(object, iteratee, accumulator) {
            var isArr = isArray(object), isArrLike = isArr || isBuffer(object) || isTypedArray(object);
            iteratee = getIteratee(iteratee, 4);
            if (accumulator == null) {
                var Ctor = object && object.constructor;
                if (isArrLike) {
                    accumulator = isArr ? new Ctor() : [];
                } else if (isObject(object)) {
                    accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {};
                } else {
                    accumulator = {};
                }
            }
            (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) {
                return iteratee(accumulator, value, index, object);
            });
            return accumulator;
        }
        function unset(object, path) {
            return object == null ? true : baseUnset(object, path);
        }
        function update(object, path, updater) {
            return object == null ? object : baseUpdate(object, path, castFunction(updater));
        }
        function updateWith(object, path, updater, customizer) {
            customizer = typeof customizer == "function" ? customizer : undefined;
            return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer);
        }
        function values(object) {
            return object == null ? [] : baseValues(object, keys(object));
        }
        function valuesIn(object) {
            return object == null ? [] : baseValues(object, keysIn(object));
        }
        function clamp(number, lower, upper) {
            if (upper === undefined) {
                upper = lower;
                lower = undefined;
            }
            if (upper !== undefined) {
                upper = toNumber(upper);
                upper = upper === upper ? upper : 0;
            }
            if (lower !== undefined) {
                lower = toNumber(lower);
                lower = lower === lower ? lower : 0;
            }
            return baseClamp(toNumber(number), lower, upper);
        }
        function inRange(number, start, end) {
            start = toFinite(start);
            if (end === undefined) {
                end = start;
                start = 0;
            } else {
                end = toFinite(end);
            }
            number = toNumber(number);
            return baseInRange(number, start, end);
        }
        function random(lower, upper, floating) {
            if (floating && typeof floating != "boolean" && isIterateeCall(lower, upper, floating)) {
                upper = floating = undefined;
            }
            if (floating === undefined) {
                if (typeof upper == "boolean") {
                    floating = upper;
                    upper = undefined;
                } else if (typeof lower == "boolean") {
                    floating = lower;
                    lower = undefined;
                }
            }
            if (lower === undefined && upper === undefined) {
                lower = 0;
                upper = 1;
            } else {
                lower = toFinite(lower);
                if (upper === undefined) {
                    upper = lower;
                    lower = 0;
                } else {
                    upper = toFinite(upper);
                }
            }
            if (lower > upper) {
                var temp = lower;
                lower = upper;
                upper = temp;
            }
            if (floating || lower % 1 || upper % 1) {
                var rand = nativeRandom();
                return nativeMin(lower + rand * (upper - lower + freeParseFloat("1e-" + ((rand + "").length - 1))), upper);
            }
            return baseRandom(lower, upper);
        }
        var camelCase = createCompounder(function(result, word, index) {
            word = word.toLowerCase();
            return result + (index ? capitalize(word) : word);
        });
        function capitalize(string) {
            return upperFirst(toString(string).toLowerCase());
        }
        function deburr(string) {
            string = toString(string);
            return string && string.replace(reLatin, deburrLetter).replace(reComboMark, "");
        }
        function endsWith(string, target, position) {
            string = toString(string);
            target = baseToString(target);
            var length = string.length;
            position = position === undefined ? length : baseClamp(toInteger(position), 0, length);
            var end = position;
            position -= target.length;
            return position >= 0 && string.slice(position, end) == target;
        }
        function escape(string) {
            string = toString(string);
            return string && reHasUnescapedHtml.test(string) ? string.replace(reUnescapedHtml, escapeHtmlChar) : string;
        }
        function escapeRegExp(string) {
            string = toString(string);
            return string && reHasRegExpChar.test(string) ? string.replace(reRegExpChar, "\\$&") : string;
        }
        var kebabCase = createCompounder(function(result, word, index) {
            return result + (index ? "-" : "") + word.toLowerCase();
        });
        var lowerCase = createCompounder(function(result, word, index) {
            return result + (index ? " " : "") + word.toLowerCase();
        });
        var lowerFirst = createCaseFirst("toLowerCase");
        function pad(string, length, chars) {
            string = toString(string);
            length = toInteger(length);
            var strLength = length ? stringSize(string) : 0;
            if (!length || strLength >= length) {
                return string;
            }
            var mid = (length - strLength) / 2;
            return createPadding(nativeFloor(mid), chars) + string + createPadding(nativeCeil(mid), chars);
        }
        function padEnd(string, length, chars) {
            string = toString(string);
            length = toInteger(length);
            var strLength = length ? stringSize(string) : 0;
            return length && strLength < length ? string + createPadding(length - strLength, chars) : string;
        }
        function padStart(string, length, chars) {
            string = toString(string);
            length = toInteger(length);
            var strLength = length ? stringSize(string) : 0;
            return length && strLength < length ? createPadding(length - strLength, chars) + string : string;
        }
        function parseInt(string, radix, guard) {
            if (guard || radix == null) {
                radix = 0;
            } else if (radix) {
                radix = +radix;
            }
            return nativeParseInt(toString(string).replace(reTrimStart, ""), radix || 0);
        }
        function repeat(string, n, guard) {
            if (guard ? isIterateeCall(string, n, guard) : n === undefined) {
                n = 1;
            } else {
                n = toInteger(n);
            }
            return baseRepeat(toString(string), n);
        }
        function replace() {
            var args = arguments, string = toString(args[0]);
            return args.length < 3 ? string : string.replace(args[1], args[2]);
        }
        var snakeCase = createCompounder(function(result, word, index) {
            return result + (index ? "_" : "") + word.toLowerCase();
        });
        function split(string, separator, limit) {
            if (limit && typeof limit != "number" && isIterateeCall(string, separator, limit)) {
                separator = limit = undefined;
            }
            limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0;
            if (!limit) {
                return [];
            }
            string = toString(string);
            if (string && (typeof separator == "string" || separator != null && !isRegExp(separator))) {
                separator = baseToString(separator);
                if (!separator && hasUnicode(string)) {
                    return castSlice(stringToArray(string), 0, limit);
                }
            }
            return string.split(separator, limit);
        }
        var startCase = createCompounder(function(result, word, index) {
            return result + (index ? " " : "") + upperFirst(word);
        });
        function startsWith(string, target, position) {
            string = toString(string);
            position = position == null ? 0 : baseClamp(toInteger(position), 0, string.length);
            target = baseToString(target);
            return string.slice(position, position + target.length) == target;
        }
        function template(string, options, guard) {
            var settings = lodash.templateSettings;
            if (guard && isIterateeCall(string, options, guard)) {
                options = undefined;
            }
            string = toString(string);
            options = assignInWith({}, options, settings, customDefaultsAssignIn);
            var imports = assignInWith({}, options.imports, settings.imports, customDefaultsAssignIn), importsKeys = keys(imports), importsValues = baseValues(imports, importsKeys);
            var isEscaping, isEvaluating, index = 0, interpolate = options.interpolate || reNoMatch, source = "__p += '";
            var reDelimiters = RegExp((options.escape || reNoMatch).source + "|" + interpolate.source + "|" + (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + "|" + (options.evaluate || reNoMatch).source + "|$", "g");
            var sourceURL = "//# sourceURL=" + (hasOwnProperty.call(options, "sourceURL") ? (options.sourceURL + "").replace(/\s/g, " ") : "lodash.templateSources[" + ++templateCounter + "]") + "\n";
            string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
                interpolateValue || (interpolateValue = esTemplateValue);
                source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
                if (escapeValue) {
                    isEscaping = true;
                    source += "' +\n__e(" + escapeValue + ") +\n'";
                }
                if (evaluateValue) {
                    isEvaluating = true;
                    source += "';\n" + evaluateValue + ";\n__p += '";
                }
                if (interpolateValue) {
                    source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
                }
                index = offset + match.length;
                return match;
            });
            source += "';\n";
            var variable = hasOwnProperty.call(options, "variable") && options.variable;
            if (!variable) {
                source = "with (obj) {\n" + source + "\n}\n";
            } else if (reForbiddenIdentifierChars.test(variable)) {
                throw new Error(INVALID_TEMPL_VAR_ERROR_TEXT);
            }
            source = (isEvaluating ? source.replace(reEmptyStringLeading, "") : source).replace(reEmptyStringMiddle, "$1").replace(reEmptyStringTrailing, "$1;");
            source = "function(" + (variable || "obj") + ") {\n" + (variable ? "" : "obj || (obj = {});\n") + "var __t, __p = ''" + (isEscaping ? ", __e = _.escape" : "") + (isEvaluating ? ", __j = Array.prototype.join;\n" + "function print() { __p += __j.call(arguments, '') }\n" : ";\n") + source + "return __p\n}";
            var result = attempt(function() {
                return Function(importsKeys, sourceURL + "return " + source).apply(undefined, importsValues);
            });
            result.source = source;
            if (isError(result)) {
                throw result;
            }
            return result;
        }
        function toLower(value) {
            return toString(value).toLowerCase();
        }
        function toUpper(value) {
            return toString(value).toUpperCase();
        }
        function trim(string, chars, guard) {
            string = toString(string);
            if (string && (guard || chars === undefined)) {
                return baseTrim(string);
            }
            if (!string || !(chars = baseToString(chars))) {
                return string;
            }
            var strSymbols = stringToArray(string), chrSymbols = stringToArray(chars), start = charsStartIndex(strSymbols, chrSymbols), end = charsEndIndex(strSymbols, chrSymbols) + 1;
            return castSlice(strSymbols, start, end).join("");
        }
        function trimEnd(string, chars, guard) {
            string = toString(string);
            if (string && (guard || chars === undefined)) {
                return string.slice(0, trimmedEndIndex(string) + 1);
            }
            if (!string || !(chars = baseToString(chars))) {
                return string;
            }
            var strSymbols = stringToArray(string), end = charsEndIndex(strSymbols, stringToArray(chars)) + 1;
            return castSlice(strSymbols, 0, end).join("");
        }
        function trimStart(string, chars, guard) {
            string = toString(string);
            if (string && (guard || chars === undefined)) {
                return string.replace(reTrimStart, "");
            }
            if (!string || !(chars = baseToString(chars))) {
                return string;
            }
            var strSymbols = stringToArray(string), start = charsStartIndex(strSymbols, stringToArray(chars));
            return castSlice(strSymbols, start).join("");
        }
        function truncate(string, options) {
            var length = DEFAULT_TRUNC_LENGTH, omission = DEFAULT_TRUNC_OMISSION;
            if (isObject(options)) {
                var separator = "separator" in options ? options.separator : separator;
                length = "length" in options ? toInteger(options.length) : length;
                omission = "omission" in options ? baseToString(options.omission) : omission;
            }
            string = toString(string);
            var strLength = string.length;
            if (hasUnicode(string)) {
                var strSymbols = stringToArray(string);
                strLength = strSymbols.length;
            }
            if (length >= strLength) {
                return string;
            }
            var end = length - stringSize(omission);
            if (end < 1) {
                return omission;
            }
            var result = strSymbols ? castSlice(strSymbols, 0, end).join("") : string.slice(0, end);
            if (separator === undefined) {
                return result + omission;
            }
            if (strSymbols) {
                end += result.length - end;
            }
            if (isRegExp(separator)) {
                if (string.slice(end).search(separator)) {
                    var match, substring = result;
                    if (!separator.global) {
                        separator = RegExp(separator.source, toString(reFlags.exec(separator)) + "g");
                    }
                    separator.lastIndex = 0;
                    while (match = separator.exec(substring)) {
                        var newEnd = match.index;
                    }
                    result = result.slice(0, newEnd === undefined ? end : newEnd);
                }
            } else if (string.indexOf(baseToString(separator), end) != end) {
                var index = result.lastIndexOf(separator);
                if (index > -1) {
                    result = result.slice(0, index);
                }
            }
            return result + omission;
        }
        function unescape(string) {
            string = toString(string);
            return string && reHasEscapedHtml.test(string) ? string.replace(reEscapedHtml, unescapeHtmlChar) : string;
        }
        var upperCase = createCompounder(function(result, word, index) {
            return result + (index ? " " : "") + word.toUpperCase();
        });
        var upperFirst = createCaseFirst("toUpperCase");
        function words(string, pattern, guard) {
            string = toString(string);
            pattern = guard ? undefined : pattern;
            if (pattern === undefined) {
                return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);
            }
            return string.match(pattern) || [];
        }
        var attempt = baseRest(function(func, args) {
            try {
                return apply(func, undefined, args);
            } catch (e) {
                return isError(e) ? e : new Error(e);
            }
        });
        var bindAll = flatRest(function(object, methodNames) {
            arrayEach(methodNames, function(key) {
                key = toKey(key);
                baseAssignValue(object, key, bind(object[key], object));
            });
            return object;
        });
        function cond(pairs) {
            var length = pairs == null ? 0 : pairs.length, toIteratee = getIteratee();
            pairs = !length ? [] : arrayMap(pairs, function(pair) {
                if (typeof pair[1] != "function") {
                    throw new TypeError(FUNC_ERROR_TEXT);
                }
                return [ toIteratee(pair[0]), pair[1] ];
            });
            return baseRest(function(args) {
                var index = -1;
                while (++index < length) {
                    var pair = pairs[index];
                    if (apply(pair[0], this, args)) {
                        return apply(pair[1], this, args);
                    }
                }
            });
        }
        function conforms(source) {
            return baseConforms(baseClone(source, CLONE_DEEP_FLAG));
        }
        function constant(value) {
            return function() {
                return value;
            };
        }
        function defaultTo(value, defaultValue) {
            return value == null || value !== value ? defaultValue : value;
        }
        var flow = createFlow();
        var flowRight = createFlow(true);
        function identity(value) {
            return value;
        }
        function iteratee(func) {
            return baseIteratee(typeof func == "function" ? func : baseClone(func, CLONE_DEEP_FLAG));
        }
        function matches(source) {
            return baseMatches(baseClone(source, CLONE_DEEP_FLAG));
        }
        function matchesProperty(path, srcValue) {
            return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG));
        }
        var method = baseRest(function(path, args) {
            return function(object) {
                return baseInvoke(object, path, args);
            };
        });
        var methodOf = baseRest(function(object, args) {
            return function(path) {
                return baseInvoke(object, path, args);
            };
        });
        function mixin(object, source, options) {
            var props = keys(source), methodNames = baseFunctions(source, props);
            if (options == null && !(isObject(source) && (methodNames.length || !props.length))) {
                options = source;
                source = object;
                object = this;
                methodNames = baseFunctions(source, keys(source));
            }
            var chain = !(isObject(options) && "chain" in options) || !!options.chain, isFunc = isFunction(object);
            arrayEach(methodNames, function(methodName) {
                var func = source[methodName];
                object[methodName] = func;
                if (isFunc) {
                    object.prototype[methodName] = function() {
                        var chainAll = this.__chain__;
                        if (chain || chainAll) {
                            var result = object(this.__wrapped__), actions = result.__actions__ = copyArray(this.__actions__);
                            actions.push({
                                func: func,
                                args: arguments,
                                thisArg: object
                            });
                            result.__chain__ = chainAll;
                            return result;
                        }
                        return func.apply(object, arrayPush([ this.value() ], arguments));
                    };
                }
            });
            return object;
        }
        function noConflict() {
            if (root._ === this) {
                root._ = oldDash;
            }
            return this;
        }
        function noop() {}
        function nthArg(n) {
            n = toInteger(n);
            return baseRest(function(args) {
                return baseNth(args, n);
            });
        }
        var over = createOver(arrayMap);
        var overEvery = createOver(arrayEvery);
        var overSome = createOver(arraySome);
        function property(path) {
            return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
        }
        function propertyOf(object) {
            return function(path) {
                return object == null ? undefined : baseGet(object, path);
            };
        }
        var range = createRange();
        var rangeRight = createRange(true);
        function stubArray() {
            return [];
        }
        function stubFalse() {
            return false;
        }
        function stubObject() {
            return {};
        }
        function stubString() {
            return "";
        }
        function stubTrue() {
            return true;
        }
        function times(n, iteratee) {
            n = toInteger(n);
            if (n < 1 || n > MAX_SAFE_INTEGER) {
                return [];
            }
            var index = MAX_ARRAY_LENGTH, length = nativeMin(n, MAX_ARRAY_LENGTH);
            iteratee = getIteratee(iteratee);
            n -= MAX_ARRAY_LENGTH;
            var result = baseTimes(length, iteratee);
            while (++index < n) {
                iteratee(index);
            }
            return result;
        }
        function toPath(value) {
            if (isArray(value)) {
                return arrayMap(value, toKey);
            }
            return isSymbol(value) ? [ value ] : copyArray(stringToPath(toString(value)));
        }
        function uniqueId(prefix) {
            var id = ++idCounter;
            return toString(prefix) + id;
        }
        var add = createMathOperation(function(augend, addend) {
            return augend + addend;
        }, 0);
        var ceil = createRound("ceil");
        var divide = createMathOperation(function(dividend, divisor) {
            return dividend / divisor;
        }, 1);
        var floor = createRound("floor");
        function max(array) {
            return array && array.length ? baseExtremum(array, identity, baseGt) : undefined;
        }
        function maxBy(array, iteratee) {
            return array && array.length ? baseExtremum(array, getIteratee(iteratee, 2), baseGt) : undefined;
        }
        function mean(array) {
            return baseMean(array, identity);
        }
        function meanBy(array, iteratee) {
            return baseMean(array, getIteratee(iteratee, 2));
        }
        function min(array) {
            return array && array.length ? baseExtremum(array, identity, baseLt) : undefined;
        }
        function minBy(array, iteratee) {
            return array && array.length ? baseExtremum(array, getIteratee(iteratee, 2), baseLt) : undefined;
        }
        var multiply = createMathOperation(function(multiplier, multiplicand) {
            return multiplier * multiplicand;
        }, 1);
        var round = createRound("round");
        var subtract = createMathOperation(function(minuend, subtrahend) {
            return minuend - subtrahend;
        }, 0);
        function sum(array) {
            return array && array.length ? baseSum(array, identity) : 0;
        }
        function sumBy(array, iteratee) {
            return array && array.length ? baseSum(array, getIteratee(iteratee, 2)) : 0;
        }
        lodash.after = after;
        lodash.ary = ary;
        lodash.assign = assign;
        lodash.assignIn = assignIn;
        lodash.assignInWith = assignInWith;
        lodash.assignWith = assignWith;
        lodash.at = at;
        lodash.before = before;
        lodash.bind = bind;
        lodash.bindAll = bindAll;
        lodash.bindKey = bindKey;
        lodash.castArray = castArray;
        lodash.chain = chain;
        lodash.chunk = chunk;
        lodash.compact = compact;
        lodash.concat = concat;
        lodash.cond = cond;
        lodash.conforms = conforms;
        lodash.constant = constant;
        lodash.countBy = countBy;
        lodash.create = create;
        lodash.curry = curry;
        lodash.curryRight = curryRight;
        lodash.debounce = debounce;
        lodash.defaults = defaults;
        lodash.defaultsDeep = defaultsDeep;
        lodash.defer = defer;
        lodash.delay = delay;
        lodash.difference = difference;
        lodash.differenceBy = differenceBy;
        lodash.differenceWith = differenceWith;
        lodash.drop = drop;
        lodash.dropRight = dropRight;
        lodash.dropRightWhile = dropRightWhile;
        lodash.dropWhile = dropWhile;
        lodash.fill = fill;
        lodash.filter = filter;
        lodash.flatMap = flatMap;
        lodash.flatMapDeep = flatMapDeep;
        lodash.flatMapDepth = flatMapDepth;
        lodash.flatten = flatten;
        lodash.flattenDeep = flattenDeep;
        lodash.flattenDepth = flattenDepth;
        lodash.flip = flip;
        lodash.flow = flow;
        lodash.flowRight = flowRight;
        lodash.fromPairs = fromPairs;
        lodash.functions = functions;
        lodash.functionsIn = functionsIn;
        lodash.groupBy = groupBy;
        lodash.initial = initial;
        lodash.intersection = intersection;
        lodash.intersectionBy = intersectionBy;
        lodash.intersectionWith = intersectionWith;
        lodash.invert = invert;
        lodash.invertBy = invertBy;
        lodash.invokeMap = invokeMap;
        lodash.iteratee = iteratee;
        lodash.keyBy = keyBy;
        lodash.keys = keys;
        lodash.keysIn = keysIn;
        lodash.map = map;
        lodash.mapKeys = mapKeys;
        lodash.mapValues = mapValues;
        lodash.matches = matches;
        lodash.matchesProperty = matchesProperty;
        lodash.memoize = memoize;
        lodash.merge = merge;
        lodash.mergeWith = mergeWith;
        lodash.method = method;
        lodash.methodOf = methodOf;
        lodash.mixin = mixin;
        lodash.negate = negate;
        lodash.nthArg = nthArg;
        lodash.omit = omit;
        lodash.omitBy = omitBy;
        lodash.once = once;
        lodash.orderBy = orderBy;
        lodash.over = over;
        lodash.overArgs = overArgs;
        lodash.overEvery = overEvery;
        lodash.overSome = overSome;
        lodash.partial = partial;
        lodash.partialRight = partialRight;
        lodash.partition = partition;
        lodash.pick = pick;
        lodash.pickBy = pickBy;
        lodash.property = property;
        lodash.propertyOf = propertyOf;
        lodash.pull = pull;
        lodash.pullAll = pullAll;
        lodash.pullAllBy = pullAllBy;
        lodash.pullAllWith = pullAllWith;
        lodash.pullAt = pullAt;
        lodash.range = range;
        lodash.rangeRight = rangeRight;
        lodash.rearg = rearg;
        lodash.reject = reject;
        lodash.remove = remove;
        lodash.rest = rest;
        lodash.reverse = reverse;
        lodash.sampleSize = sampleSize;
        lodash.set = set;
        lodash.setWith = setWith;
        lodash.shuffle = shuffle;
        lodash.slice = slice;
        lodash.sortBy = sortBy;
        lodash.sortedUniq = sortedUniq;
        lodash.sortedUniqBy = sortedUniqBy;
        lodash.split = split;
        lodash.spread = spread;
        lodash.tail = tail;
        lodash.take = take;
        lodash.takeRight = takeRight;
        lodash.takeRightWhile = takeRightWhile;
        lodash.takeWhile = takeWhile;
        lodash.tap = tap;
        lodash.throttle = throttle;
        lodash.thru = thru;
        lodash.toArray = toArray;
        lodash.toPairs = toPairs;
        lodash.toPairsIn = toPairsIn;
        lodash.toPath = toPath;
        lodash.toPlainObject = toPlainObject;
        lodash.transform = transform;
        lodash.unary = unary;
        lodash.union = union;
        lodash.unionBy = unionBy;
        lodash.unionWith = unionWith;
        lodash.uniq = uniq;
        lodash.uniqBy = uniqBy;
        lodash.uniqWith = uniqWith;
        lodash.unset = unset;
        lodash.unzip = unzip;
        lodash.unzipWith = unzipWith;
        lodash.update = update;
        lodash.updateWith = updateWith;
        lodash.values = values;
        lodash.valuesIn = valuesIn;
        lodash.without = without;
        lodash.words = words;
        lodash.wrap = wrap;
        lodash.xor = xor;
        lodash.xorBy = xorBy;
        lodash.xorWith = xorWith;
        lodash.zip = zip;
        lodash.zipObject = zipObject;
        lodash.zipObjectDeep = zipObjectDeep;
        lodash.zipWith = zipWith;
        lodash.entries = toPairs;
        lodash.entriesIn = toPairsIn;
        lodash.extend = assignIn;
        lodash.extendWith = assignInWith;
        mixin(lodash, lodash);
        lodash.add = add;
        lodash.attempt = attempt;
        lodash.camelCase = camelCase;
        lodash.capitalize = capitalize;
        lodash.ceil = ceil;
        lodash.clamp = clamp;
        lodash.clone = clone;
        lodash.cloneDeep = cloneDeep;
        lodash.cloneDeepWith = cloneDeepWith;
        lodash.cloneWith = cloneWith;
        lodash.conformsTo = conformsTo;
        lodash.deburr = deburr;
        lodash.defaultTo = defaultTo;
        lodash.divide = divide;
        lodash.endsWith = endsWith;
        lodash.eq = eq;
        lodash.escape = escape;
        lodash.escapeRegExp = escapeRegExp;
        lodash.every = every;
        lodash.find = find;
        lodash.findIndex = findIndex;
        lodash.findKey = findKey;
        lodash.findLast = findLast;
        lodash.findLastIndex = findLastIndex;
        lodash.findLastKey = findLastKey;
        lodash.floor = floor;
        lodash.forEach = forEach;
        lodash.forEachRight = forEachRight;
        lodash.forIn = forIn;
        lodash.forInRight = forInRight;
        lodash.forOwn = forOwn;
        lodash.forOwnRight = forOwnRight;
        lodash.get = get;
        lodash.gt = gt;
        lodash.gte = gte;
        lodash.has = has;
        lodash.hasIn = hasIn;
        lodash.head = head;
        lodash.identity = identity;
        lodash.includes = includes;
        lodash.indexOf = indexOf;
        lodash.inRange = inRange;
        lodash.invoke = invoke;
        lodash.isArguments = isArguments;
        lodash.isArray = isArray;
        lodash.isArrayBuffer = isArrayBuffer;
        lodash.isArrayLike = isArrayLike;
        lodash.isArrayLikeObject = isArrayLikeObject;
        lodash.isBoolean = isBoolean;
        lodash.isBuffer = isBuffer;
        lodash.isDate = isDate;
        lodash.isElement = isElement;
        lodash.isEmpty = isEmpty;
        lodash.isEqual = isEqual;
        lodash.isEqualWith = isEqualWith;
        lodash.isError = isError;
        lodash.isFinite = isFinite;
        lodash.isFunction = isFunction;
        lodash.isInteger = isInteger;
        lodash.isLength = isLength;
        lodash.isMap = isMap;
        lodash.isMatch = isMatch;
        lodash.isMatchWith = isMatchWith;
        lodash.isNaN = isNaN;
        lodash.isNative = isNative;
        lodash.isNil = isNil;
        lodash.isNull = isNull;
        lodash.isNumber = isNumber;
        lodash.isObject = isObject;
        lodash.isObjectLike = isObjectLike;
        lodash.isPlainObject = isPlainObject;
        lodash.isRegExp = isRegExp;
        lodash.isSafeInteger = isSafeInteger;
        lodash.isSet = isSet;
        lodash.isString = isString;
        lodash.isSymbol = isSymbol;
        lodash.isTypedArray = isTypedArray;
        lodash.isUndefined = isUndefined;
        lodash.isWeakMap = isWeakMap;
        lodash.isWeakSet = isWeakSet;
        lodash.join = join;
        lodash.kebabCase = kebabCase;
        lodash.last = last;
        lodash.lastIndexOf = lastIndexOf;
        lodash.lowerCase = lowerCase;
        lodash.lowerFirst = lowerFirst;
        lodash.lt = lt;
        lodash.lte = lte;
        lodash.max = max;
        lodash.maxBy = maxBy;
        lodash.mean = mean;
        lodash.meanBy = meanBy;
        lodash.min = min;
        lodash.minBy = minBy;
        lodash.stubArray = stubArray;
        lodash.stubFalse = stubFalse;
        lodash.stubObject = stubObject;
        lodash.stubString = stubString;
        lodash.stubTrue = stubTrue;
        lodash.multiply = multiply;
        lodash.nth = nth;
        lodash.noConflict = noConflict;
        lodash.noop = noop;
        lodash.now = now;
        lodash.pad = pad;
        lodash.padEnd = padEnd;
        lodash.padStart = padStart;
        lodash.parseInt = parseInt;
        lodash.random = random;
        lodash.reduce = reduce;
        lodash.reduceRight = reduceRight;
        lodash.repeat = repeat;
        lodash.replace = replace;
        lodash.result = result;
        lodash.round = round;
        lodash.runInContext = runInContext;
        lodash.sample = sample;
        lodash.size = size;
        lodash.snakeCase = snakeCase;
        lodash.some = some;
        lodash.sortedIndex = sortedIndex;
        lodash.sortedIndexBy = sortedIndexBy;
        lodash.sortedIndexOf = sortedIndexOf;
        lodash.sortedLastIndex = sortedLastIndex;
        lodash.sortedLastIndexBy = sortedLastIndexBy;
        lodash.sortedLastIndexOf = sortedLastIndexOf;
        lodash.startCase = startCase;
        lodash.startsWith = startsWith;
        lodash.subtract = subtract;
        lodash.sum = sum;
        lodash.sumBy = sumBy;
        lodash.template = template;
        lodash.times = times;
        lodash.toFinite = toFinite;
        lodash.toInteger = toInteger;
        lodash.toLength = toLength;
        lodash.toLower = toLower;
        lodash.toNumber = toNumber;
        lodash.toSafeInteger = toSafeInteger;
        lodash.toString = toString;
        lodash.toUpper = toUpper;
        lodash.trim = trim;
        lodash.trimEnd = trimEnd;
        lodash.trimStart = trimStart;
        lodash.truncate = truncate;
        lodash.unescape = unescape;
        lodash.uniqueId = uniqueId;
        lodash.upperCase = upperCase;
        lodash.upperFirst = upperFirst;
        lodash.each = forEach;
        lodash.eachRight = forEachRight;
        lodash.first = head;
        mixin(lodash, function() {
            var source = {};
            baseForOwn(lodash, function(func, methodName) {
                if (!hasOwnProperty.call(lodash.prototype, methodName)) {
                    source[methodName] = func;
                }
            });
            return source;
        }(), {
            chain: false
        });
        lodash.VERSION = VERSION;
        arrayEach([ "bind", "bindKey", "curry", "curryRight", "partial", "partialRight" ], function(methodName) {
            lodash[methodName].placeholder = lodash;
        });
        arrayEach([ "drop", "take" ], function(methodName, index) {
            LazyWrapper.prototype[methodName] = function(n) {
                n = n === undefined ? 1 : nativeMax(toInteger(n), 0);
                var result = this.__filtered__ && !index ? new LazyWrapper(this) : this.clone();
                if (result.__filtered__) {
                    result.__takeCount__ = nativeMin(n, result.__takeCount__);
                } else {
                    result.__views__.push({
                        size: nativeMin(n, MAX_ARRAY_LENGTH),
                        type: methodName + (result.__dir__ < 0 ? "Right" : "")
                    });
                }
                return result;
            };
            LazyWrapper.prototype[methodName + "Right"] = function(n) {
                return this.reverse()[methodName](n).reverse();
            };
        });
        arrayEach([ "filter", "map", "takeWhile" ], function(methodName, index) {
            var type = index + 1, isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;
            LazyWrapper.prototype[methodName] = function(iteratee) {
                var result = this.clone();
                result.__iteratees__.push({
                    iteratee: getIteratee(iteratee, 3),
                    type: type
                });
                result.__filtered__ = result.__filtered__ || isFilter;
                return result;
            };
        });
        arrayEach([ "head", "last" ], function(methodName, index) {
            var takeName = "take" + (index ? "Right" : "");
            LazyWrapper.prototype[methodName] = function() {
                return this[takeName](1).value()[0];
            };
        });
        arrayEach([ "initial", "tail" ], function(methodName, index) {
            var dropName = "drop" + (index ? "" : "Right");
            LazyWrapper.prototype[methodName] = function() {
                return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
            };
        });
        LazyWrapper.prototype.compact = function() {
            return this.filter(identity);
        };
        LazyWrapper.prototype.find = function(predicate) {
            return this.filter(predicate).head();
        };
        LazyWrapper.prototype.findLast = function(predicate) {
            return this.reverse().find(predicate);
        };
        LazyWrapper.prototype.invokeMap = baseRest(function(path, args) {
            if (typeof path == "function") {
                return new LazyWrapper(this);
            }
            return this.map(function(value) {
                return baseInvoke(value, path, args);
            });
        });
        LazyWrapper.prototype.reject = function(predicate) {
            return this.filter(negate(getIteratee(predicate)));
        };
        LazyWrapper.prototype.slice = function(start, end) {
            start = toInteger(start);
            var result = this;
            if (result.__filtered__ && (start > 0 || end < 0)) {
                return new LazyWrapper(result);
            }
            if (start < 0) {
                result = result.takeRight(-start);
            } else if (start) {
                result = result.drop(start);
            }
            if (end !== undefined) {
                end = toInteger(end);
                result = end < 0 ? result.dropRight(-end) : result.take(end - start);
            }
            return result;
        };
        LazyWrapper.prototype.takeRightWhile = function(predicate) {
            return this.reverse().takeWhile(predicate).reverse();
        };
        LazyWrapper.prototype.toArray = function() {
            return this.take(MAX_ARRAY_LENGTH);
        };
        baseForOwn(LazyWrapper.prototype, function(func, methodName) {
            var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName), isTaker = /^(?:head|last)$/.test(methodName), lodashFunc = lodash[isTaker ? "take" + (methodName == "last" ? "Right" : "") : methodName], retUnwrapped = isTaker || /^find/.test(methodName);
            if (!lodashFunc) {
                return;
            }
            lodash.prototype[methodName] = function() {
                var value = this.__wrapped__, args = isTaker ? [ 1 ] : arguments, isLazy = value instanceof LazyWrapper, iteratee = args[0], useLazy = isLazy || isArray(value);
                var interceptor = function(value) {
                    var result = lodashFunc.apply(lodash, arrayPush([ value ], args));
                    return isTaker && chainAll ? result[0] : result;
                };
                if (useLazy && checkIteratee && typeof iteratee == "function" && iteratee.length != 1) {
                    isLazy = useLazy = false;
                }
                var chainAll = this.__chain__, isHybrid = !!this.__actions__.length, isUnwrapped = retUnwrapped && !chainAll, onlyLazy = isLazy && !isHybrid;
                if (!retUnwrapped && useLazy) {
                    value = onlyLazy ? value : new LazyWrapper(this);
                    var result = func.apply(value, args);
                    result.__actions__.push({
                        func: thru,
                        args: [ interceptor ],
                        thisArg: undefined
                    });
                    return new LodashWrapper(result, chainAll);
                }
                if (isUnwrapped && onlyLazy) {
                    return func.apply(this, args);
                }
                result = this.thru(interceptor);
                return isUnwrapped ? isTaker ? result.value()[0] : result.value() : result;
            };
        });
        arrayEach([ "pop", "push", "shift", "sort", "splice", "unshift" ], function(methodName) {
            var func = arrayProto[methodName], chainName = /^(?:push|sort|unshift)$/.test(methodName) ? "tap" : "thru", retUnwrapped = /^(?:pop|shift)$/.test(methodName);
            lodash.prototype[methodName] = function() {
                var args = arguments;
                if (retUnwrapped && !this.__chain__) {
                    var value = this.value();
                    return func.apply(isArray(value) ? value : [], args);
                }
                return this[chainName](function(value) {
                    return func.apply(isArray(value) ? value : [], args);
                });
            };
        });
        baseForOwn(LazyWrapper.prototype, function(func, methodName) {
            var lodashFunc = lodash[methodName];
            if (lodashFunc) {
                var key = lodashFunc.name + "";
                if (!hasOwnProperty.call(realNames, key)) {
                    realNames[key] = [];
                }
                realNames[key].push({
                    name: methodName,
                    func: lodashFunc
                });
            }
        });
        realNames[createHybrid(undefined, WRAP_BIND_KEY_FLAG).name] = [ {
            name: "wrapper",
            func: undefined
        } ];
        LazyWrapper.prototype.clone = lazyClone;
        LazyWrapper.prototype.reverse = lazyReverse;
        LazyWrapper.prototype.value = lazyValue;
        lodash.prototype.at = wrapperAt;
        lodash.prototype.chain = wrapperChain;
        lodash.prototype.commit = wrapperCommit;
        lodash.prototype.next = wrapperNext;
        lodash.prototype.plant = wrapperPlant;
        lodash.prototype.reverse = wrapperReverse;
        lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;
        lodash.prototype.first = lodash.prototype.head;
        if (symIterator) {
            lodash.prototype[symIterator] = wrapperToIterator;
        }
        return lodash;
    };
    var _ = runInContext();
    if (typeof define == "function" && typeof define.amd == "object" && define.amd) {
        root._ = _;
        define(function() {
            return _;
        });
    } else if (freeModule) {
        (freeModule.exports = _)._ = _;
        freeExports._ = _;
    } else {
        root._ = _;
    }
}).call(this);

(function($) {
    var __slice = Array.prototype.slice;
    var i18n = {
        dict: null,
        load: function(i18n_dict) {
            if (this.dict !== null) {
                $.extend(this.dict, i18n_dict);
            } else {
                this.dict = i18n_dict;
            }
        },
        _: function(str) {
            dict = this.dict;
            if (dict && dict.hasOwnProperty(str)) {
                str = dict[str];
            }
            args = __slice.call(arguments);
            args[0] = str;
            return this.printf.apply(this, args);
        },
        printf: function(str, args) {
            if (arguments.length < 2) return str;
            args = $.isArray(args) ? args : __slice.call(arguments, 1);
            return str.replace(/([^%]|^)%(?:(\d+)\$)?s/g, function(p0, p, position) {
                if (position) {
                    return p + args[parseInt(position) - 1];
                }
                return p + args.shift();
            }).replace(/%%s/g, "%s");
        }
    };
    $.fn._t = function(str, params) {
        return $(this).html(i18n._.apply(i18n, arguments));
    };
    $.i18n = i18n;
})(jQuery);

(function($) {
    if (typeof $.fn.each2 == "undefined") {
        $.extend($.fn, {
            each2: function(c) {
                var j = $([ 0 ]), i = -1, l = this.length;
                while (++i < l && (j.context = j[0] = this[i]) && c.call(j[0], i, j) !== false);
                return this;
            }
        });
    }
})(jQuery);

(function($, undefined) {
    "use strict";
    if (window.Select2 !== undefined) {
        return;
    }
    var AbstractSelect2, SingleSelect2, MultiSelect2, nextUid, sizer, lastMousePosition = {
        x: 0,
        y: 0
    }, $document, scrollBarDimensions, KEY = {
        TAB: 9,
        ENTER: 13,
        ESC: 27,
        SPACE: 32,
        LEFT: 37,
        UP: 38,
        RIGHT: 39,
        DOWN: 40,
        SHIFT: 16,
        CTRL: 17,
        ALT: 18,
        PAGE_UP: 33,
        PAGE_DOWN: 34,
        HOME: 36,
        END: 35,
        BACKSPACE: 8,
        DELETE: 46,
        isArrow: function(k) {
            k = k.which ? k.which : k;
            switch (k) {
              case KEY.LEFT:
              case KEY.RIGHT:
              case KEY.UP:
              case KEY.DOWN:
                return true;
            }
            return false;
        },
        isControl: function(e) {
            var k = e.which;
            switch (k) {
              case KEY.SHIFT:
              case KEY.CTRL:
              case KEY.ALT:
                return true;
            }
            if (e.metaKey) return true;
            return false;
        },
        isFunctionKey: function(k) {
            k = k.which ? k.which : k;
            return k >= 112 && k <= 123;
        }
    }, MEASURE_SCROLLBAR_TEMPLATE = "<div class='select2-measure-scrollbar'></div>", DIACRITICS = {
        "Ⓐ": "A",
        "Ａ": "A",
        "À": "A",
        "Á": "A",
        "Â": "A",
        "Ầ": "A",
        "Ấ": "A",
        "Ẫ": "A",
        "Ẩ": "A",
        "Ã": "A",
        "Ā": "A",
        "Ă": "A",
        "Ằ": "A",
        "Ắ": "A",
        "Ẵ": "A",
        "Ẳ": "A",
        "Ȧ": "A",
        "Ǡ": "A",
        "Ä": "A",
        "Ǟ": "A",
        "Ả": "A",
        "Å": "A",
        "Ǻ": "A",
        "Ǎ": "A",
        "Ȁ": "A",
        "Ȃ": "A",
        "Ạ": "A",
        "Ậ": "A",
        "Ặ": "A",
        "Ḁ": "A",
        "Ą": "A",
        "Ⱥ": "A",
        "Ɐ": "A",
        "Ꜳ": "AA",
        "Æ": "AE",
        "Ǽ": "AE",
        "Ǣ": "AE",
        "Ꜵ": "AO",
        "Ꜷ": "AU",
        "Ꜹ": "AV",
        "Ꜻ": "AV",
        "Ꜽ": "AY",
        "Ⓑ": "B",
        "Ｂ": "B",
        "Ḃ": "B",
        "Ḅ": "B",
        "Ḇ": "B",
        "Ƀ": "B",
        "Ƃ": "B",
        "Ɓ": "B",
        "Ⓒ": "C",
        "Ｃ": "C",
        "Ć": "C",
        "Ĉ": "C",
        "Ċ": "C",
        "Č": "C",
        "Ç": "C",
        "Ḉ": "C",
        "Ƈ": "C",
        "Ȼ": "C",
        "Ꜿ": "C",
        "Ⓓ": "D",
        "Ｄ": "D",
        "Ḋ": "D",
        "Ď": "D",
        "Ḍ": "D",
        "Ḑ": "D",
        "Ḓ": "D",
        "Ḏ": "D",
        "Đ": "D",
        "Ƌ": "D",
        "Ɗ": "D",
        "Ɖ": "D",
        "Ꝺ": "D",
        "Ǳ": "DZ",
        "Ǆ": "DZ",
        "ǲ": "Dz",
        "ǅ": "Dz",
        "Ⓔ": "E",
        "Ｅ": "E",
        "È": "E",
        "É": "E",
        "Ê": "E",
        "Ề": "E",
        "Ế": "E",
        "Ễ": "E",
        "Ể": "E",
        "Ẽ": "E",
        "Ē": "E",
        "Ḕ": "E",
        "Ḗ": "E",
        "Ĕ": "E",
        "Ė": "E",
        "Ë": "E",
        "Ẻ": "E",
        "Ě": "E",
        "Ȅ": "E",
        "Ȇ": "E",
        "Ẹ": "E",
        "Ệ": "E",
        "Ȩ": "E",
        "Ḝ": "E",
        "Ę": "E",
        "Ḙ": "E",
        "Ḛ": "E",
        "Ɛ": "E",
        "Ǝ": "E",
        "Ⓕ": "F",
        "Ｆ": "F",
        "Ḟ": "F",
        "Ƒ": "F",
        "Ꝼ": "F",
        "Ⓖ": "G",
        "Ｇ": "G",
        "Ǵ": "G",
        "Ĝ": "G",
        "Ḡ": "G",
        "Ğ": "G",
        "Ġ": "G",
        "Ǧ": "G",
        "Ģ": "G",
        "Ǥ": "G",
        "Ɠ": "G",
        "Ꞡ": "G",
        "Ᵹ": "G",
        "Ꝿ": "G",
        "Ⓗ": "H",
        "Ｈ": "H",
        "Ĥ": "H",
        "Ḣ": "H",
        "Ḧ": "H",
        "Ȟ": "H",
        "Ḥ": "H",
        "Ḩ": "H",
        "Ḫ": "H",
        "Ħ": "H",
        "Ⱨ": "H",
        "Ⱶ": "H",
        "Ɥ": "H",
        "Ⓘ": "I",
        "Ｉ": "I",
        "Ì": "I",
        "Í": "I",
        "Î": "I",
        "Ĩ": "I",
        "Ī": "I",
        "Ĭ": "I",
        "İ": "I",
        "Ï": "I",
        "Ḯ": "I",
        "Ỉ": "I",
        "Ǐ": "I",
        "Ȉ": "I",
        "Ȋ": "I",
        "Ị": "I",
        "Į": "I",
        "Ḭ": "I",
        "Ɨ": "I",
        "Ⓙ": "J",
        "Ｊ": "J",
        "Ĵ": "J",
        "Ɉ": "J",
        "Ⓚ": "K",
        "Ｋ": "K",
        "Ḱ": "K",
        "Ǩ": "K",
        "Ḳ": "K",
        "Ķ": "K",
        "Ḵ": "K",
        "Ƙ": "K",
        "Ⱪ": "K",
        "Ꝁ": "K",
        "Ꝃ": "K",
        "Ꝅ": "K",
        "Ꞣ": "K",
        "Ⓛ": "L",
        "Ｌ": "L",
        "Ŀ": "L",
        "Ĺ": "L",
        "Ľ": "L",
        "Ḷ": "L",
        "Ḹ": "L",
        "Ļ": "L",
        "Ḽ": "L",
        "Ḻ": "L",
        "Ł": "L",
        "Ƚ": "L",
        "Ɫ": "L",
        "Ⱡ": "L",
        "Ꝉ": "L",
        "Ꝇ": "L",
        "Ꞁ": "L",
        "Ǉ": "LJ",
        "ǈ": "Lj",
        "Ⓜ": "M",
        "Ｍ": "M",
        "Ḿ": "M",
        "Ṁ": "M",
        "Ṃ": "M",
        "Ɱ": "M",
        "Ɯ": "M",
        "Ⓝ": "N",
        "Ｎ": "N",
        "Ǹ": "N",
        "Ń": "N",
        "Ñ": "N",
        "Ṅ": "N",
        "Ň": "N",
        "Ṇ": "N",
        "Ņ": "N",
        "Ṋ": "N",
        "Ṉ": "N",
        "Ƞ": "N",
        "Ɲ": "N",
        "Ꞑ": "N",
        "Ꞥ": "N",
        "Ǌ": "NJ",
        "ǋ": "Nj",
        "Ⓞ": "O",
        "Ｏ": "O",
        "Ò": "O",
        "Ó": "O",
        "Ô": "O",
        "Ồ": "O",
        "Ố": "O",
        "Ỗ": "O",
        "Ổ": "O",
        "Õ": "O",
        "Ṍ": "O",
        "Ȭ": "O",
        "Ṏ": "O",
        "Ō": "O",
        "Ṑ": "O",
        "Ṓ": "O",
        "Ŏ": "O",
        "Ȯ": "O",
        "Ȱ": "O",
        "Ö": "O",
        "Ȫ": "O",
        "Ỏ": "O",
        "Ő": "O",
        "Ǒ": "O",
        "Ȍ": "O",
        "Ȏ": "O",
        "Ơ": "O",
        "Ờ": "O",
        "Ớ": "O",
        "Ỡ": "O",
        "Ở": "O",
        "Ợ": "O",
        "Ọ": "O",
        "Ộ": "O",
        "Ǫ": "O",
        "Ǭ": "O",
        "Ø": "O",
        "Ǿ": "O",
        "Ɔ": "O",
        "Ɵ": "O",
        "Ꝋ": "O",
        "Ꝍ": "O",
        "Ƣ": "OI",
        "Ꝏ": "OO",
        "Ȣ": "OU",
        "Ⓟ": "P",
        "Ｐ": "P",
        "Ṕ": "P",
        "Ṗ": "P",
        "Ƥ": "P",
        "Ᵽ": "P",
        "Ꝑ": "P",
        "Ꝓ": "P",
        "Ꝕ": "P",
        "Ⓠ": "Q",
        "Ｑ": "Q",
        "Ꝗ": "Q",
        "Ꝙ": "Q",
        "Ɋ": "Q",
        "Ⓡ": "R",
        "Ｒ": "R",
        "Ŕ": "R",
        "Ṙ": "R",
        "Ř": "R",
        "Ȑ": "R",
        "Ȓ": "R",
        "Ṛ": "R",
        "Ṝ": "R",
        "Ŗ": "R",
        "Ṟ": "R",
        "Ɍ": "R",
        "Ɽ": "R",
        "Ꝛ": "R",
        "Ꞧ": "R",
        "Ꞃ": "R",
        "Ⓢ": "S",
        "Ｓ": "S",
        "ẞ": "S",
        "Ś": "S",
        "Ṥ": "S",
        "Ŝ": "S",
        "Ṡ": "S",
        "Š": "S",
        "Ṧ": "S",
        "Ṣ": "S",
        "Ṩ": "S",
        "Ș": "S",
        "Ş": "S",
        "Ȿ": "S",
        "Ꞩ": "S",
        "Ꞅ": "S",
        "Ⓣ": "T",
        "Ｔ": "T",
        "Ṫ": "T",
        "Ť": "T",
        "Ṭ": "T",
        "Ț": "T",
        "Ţ": "T",
        "Ṱ": "T",
        "Ṯ": "T",
        "Ŧ": "T",
        "Ƭ": "T",
        "Ʈ": "T",
        "Ⱦ": "T",
        "Ꞇ": "T",
        "Ꜩ": "TZ",
        "Ⓤ": "U",
        "Ｕ": "U",
        "Ù": "U",
        "Ú": "U",
        "Û": "U",
        "Ũ": "U",
        "Ṹ": "U",
        "Ū": "U",
        "Ṻ": "U",
        "Ŭ": "U",
        "Ü": "U",
        "Ǜ": "U",
        "Ǘ": "U",
        "Ǖ": "U",
        "Ǚ": "U",
        "Ủ": "U",
        "Ů": "U",
        "Ű": "U",
        "Ǔ": "U",
        "Ȕ": "U",
        "Ȗ": "U",
        "Ư": "U",
        "Ừ": "U",
        "Ứ": "U",
        "Ữ": "U",
        "Ử": "U",
        "Ự": "U",
        "Ụ": "U",
        "Ṳ": "U",
        "Ų": "U",
        "Ṷ": "U",
        "Ṵ": "U",
        "Ʉ": "U",
        "Ⓥ": "V",
        "Ｖ": "V",
        "Ṽ": "V",
        "Ṿ": "V",
        "Ʋ": "V",
        "Ꝟ": "V",
        "Ʌ": "V",
        "Ꝡ": "VY",
        "Ⓦ": "W",
        "Ｗ": "W",
        "Ẁ": "W",
        "Ẃ": "W",
        "Ŵ": "W",
        "Ẇ": "W",
        "Ẅ": "W",
        "Ẉ": "W",
        "Ⱳ": "W",
        "Ⓧ": "X",
        "Ｘ": "X",
        "Ẋ": "X",
        "Ẍ": "X",
        "Ⓨ": "Y",
        "Ｙ": "Y",
        "Ỳ": "Y",
        "Ý": "Y",
        "Ŷ": "Y",
        "Ỹ": "Y",
        "Ȳ": "Y",
        "Ẏ": "Y",
        "Ÿ": "Y",
        "Ỷ": "Y",
        "Ỵ": "Y",
        "Ƴ": "Y",
        "Ɏ": "Y",
        "Ỿ": "Y",
        "Ⓩ": "Z",
        "Ｚ": "Z",
        "Ź": "Z",
        "Ẑ": "Z",
        "Ż": "Z",
        "Ž": "Z",
        "Ẓ": "Z",
        "Ẕ": "Z",
        "Ƶ": "Z",
        "Ȥ": "Z",
        "Ɀ": "Z",
        "Ⱬ": "Z",
        "Ꝣ": "Z",
        "ⓐ": "a",
        "ａ": "a",
        "ẚ": "a",
        "à": "a",
        "á": "a",
        "â": "a",
        "ầ": "a",
        "ấ": "a",
        "ẫ": "a",
        "ẩ": "a",
        "ã": "a",
        "ā": "a",
        "ă": "a",
        "ằ": "a",
        "ắ": "a",
        "ẵ": "a",
        "ẳ": "a",
        "ȧ": "a",
        "ǡ": "a",
        "ä": "a",
        "ǟ": "a",
        "ả": "a",
        "å": "a",
        "ǻ": "a",
        "ǎ": "a",
        "ȁ": "a",
        "ȃ": "a",
        "ạ": "a",
        "ậ": "a",
        "ặ": "a",
        "ḁ": "a",
        "ą": "a",
        "ⱥ": "a",
        "ɐ": "a",
        "ꜳ": "aa",
        "æ": "ae",
        "ǽ": "ae",
        "ǣ": "ae",
        "ꜵ": "ao",
        "ꜷ": "au",
        "ꜹ": "av",
        "ꜻ": "av",
        "ꜽ": "ay",
        "ⓑ": "b",
        "ｂ": "b",
        "ḃ": "b",
        "ḅ": "b",
        "ḇ": "b",
        "ƀ": "b",
        "ƃ": "b",
        "ɓ": "b",
        "ⓒ": "c",
        "ｃ": "c",
        "ć": "c",
        "ĉ": "c",
        "ċ": "c",
        "č": "c",
        "ç": "c",
        "ḉ": "c",
        "ƈ": "c",
        "ȼ": "c",
        "ꜿ": "c",
        "ↄ": "c",
        "ⓓ": "d",
        "ｄ": "d",
        "ḋ": "d",
        "ď": "d",
        "ḍ": "d",
        "ḑ": "d",
        "ḓ": "d",
        "ḏ": "d",
        "đ": "d",
        "ƌ": "d",
        "ɖ": "d",
        "ɗ": "d",
        "ꝺ": "d",
        "ǳ": "dz",
        "ǆ": "dz",
        "ⓔ": "e",
        "ｅ": "e",
        "è": "e",
        "é": "e",
        "ê": "e",
        "ề": "e",
        "ế": "e",
        "ễ": "e",
        "ể": "e",
        "ẽ": "e",
        "ē": "e",
        "ḕ": "e",
        "ḗ": "e",
        "ĕ": "e",
        "ė": "e",
        "ë": "e",
        "ẻ": "e",
        "ě": "e",
        "ȅ": "e",
        "ȇ": "e",
        "ẹ": "e",
        "ệ": "e",
        "ȩ": "e",
        "ḝ": "e",
        "ę": "e",
        "ḙ": "e",
        "ḛ": "e",
        "ɇ": "e",
        "ɛ": "e",
        "ǝ": "e",
        "ⓕ": "f",
        "ｆ": "f",
        "ḟ": "f",
        "ƒ": "f",
        "ꝼ": "f",
        "ⓖ": "g",
        "ｇ": "g",
        "ǵ": "g",
        "ĝ": "g",
        "ḡ": "g",
        "ğ": "g",
        "ġ": "g",
        "ǧ": "g",
        "ģ": "g",
        "ǥ": "g",
        "ɠ": "g",
        "ꞡ": "g",
        "ᵹ": "g",
        "ꝿ": "g",
        "ⓗ": "h",
        "ｈ": "h",
        "ĥ": "h",
        "ḣ": "h",
        "ḧ": "h",
        "ȟ": "h",
        "ḥ": "h",
        "ḩ": "h",
        "ḫ": "h",
        "ẖ": "h",
        "ħ": "h",
        "ⱨ": "h",
        "ⱶ": "h",
        "ɥ": "h",
        "ƕ": "hv",
        "ⓘ": "i",
        "ｉ": "i",
        "ì": "i",
        "í": "i",
        "î": "i",
        "ĩ": "i",
        "ī": "i",
        "ĭ": "i",
        "ï": "i",
        "ḯ": "i",
        "ỉ": "i",
        "ǐ": "i",
        "ȉ": "i",
        "ȋ": "i",
        "ị": "i",
        "į": "i",
        "ḭ": "i",
        "ɨ": "i",
        "ı": "i",
        "ⓙ": "j",
        "ｊ": "j",
        "ĵ": "j",
        "ǰ": "j",
        "ɉ": "j",
        "ⓚ": "k",
        "ｋ": "k",
        "ḱ": "k",
        "ǩ": "k",
        "ḳ": "k",
        "ķ": "k",
        "ḵ": "k",
        "ƙ": "k",
        "ⱪ": "k",
        "ꝁ": "k",
        "ꝃ": "k",
        "ꝅ": "k",
        "ꞣ": "k",
        "ⓛ": "l",
        "ｌ": "l",
        "ŀ": "l",
        "ĺ": "l",
        "ľ": "l",
        "ḷ": "l",
        "ḹ": "l",
        "ļ": "l",
        "ḽ": "l",
        "ḻ": "l",
        "ſ": "l",
        "ł": "l",
        "ƚ": "l",
        "ɫ": "l",
        "ⱡ": "l",
        "ꝉ": "l",
        "ꞁ": "l",
        "ꝇ": "l",
        "ǉ": "lj",
        "ⓜ": "m",
        "ｍ": "m",
        "ḿ": "m",
        "ṁ": "m",
        "ṃ": "m",
        "ɱ": "m",
        "ɯ": "m",
        "ⓝ": "n",
        "ｎ": "n",
        "ǹ": "n",
        "ń": "n",
        "ñ": "n",
        "ṅ": "n",
        "ň": "n",
        "ṇ": "n",
        "ņ": "n",
        "ṋ": "n",
        "ṉ": "n",
        "ƞ": "n",
        "ɲ": "n",
        "ŉ": "n",
        "ꞑ": "n",
        "ꞥ": "n",
        "ǌ": "nj",
        "ⓞ": "o",
        "ｏ": "o",
        "ò": "o",
        "ó": "o",
        "ô": "o",
        "ồ": "o",
        "ố": "o",
        "ỗ": "o",
        "ổ": "o",
        "õ": "o",
        "ṍ": "o",
        "ȭ": "o",
        "ṏ": "o",
        "ō": "o",
        "ṑ": "o",
        "ṓ": "o",
        "ŏ": "o",
        "ȯ": "o",
        "ȱ": "o",
        "ö": "o",
        "ȫ": "o",
        "ỏ": "o",
        "ő": "o",
        "ǒ": "o",
        "ȍ": "o",
        "ȏ": "o",
        "ơ": "o",
        "ờ": "o",
        "ớ": "o",
        "ỡ": "o",
        "ở": "o",
        "ợ": "o",
        "ọ": "o",
        "ộ": "o",
        "ǫ": "o",
        "ǭ": "o",
        "ø": "o",
        "ǿ": "o",
        "ɔ": "o",
        "ꝋ": "o",
        "ꝍ": "o",
        "ɵ": "o",
        "ƣ": "oi",
        "ȣ": "ou",
        "ꝏ": "oo",
        "ⓟ": "p",
        "ｐ": "p",
        "ṕ": "p",
        "ṗ": "p",
        "ƥ": "p",
        "ᵽ": "p",
        "ꝑ": "p",
        "ꝓ": "p",
        "ꝕ": "p",
        "ⓠ": "q",
        "ｑ": "q",
        "ɋ": "q",
        "ꝗ": "q",
        "ꝙ": "q",
        "ⓡ": "r",
        "ｒ": "r",
        "ŕ": "r",
        "ṙ": "r",
        "ř": "r",
        "ȑ": "r",
        "ȓ": "r",
        "ṛ": "r",
        "ṝ": "r",
        "ŗ": "r",
        "ṟ": "r",
        "ɍ": "r",
        "ɽ": "r",
        "ꝛ": "r",
        "ꞧ": "r",
        "ꞃ": "r",
        "ⓢ": "s",
        "ｓ": "s",
        "ß": "s",
        "ś": "s",
        "ṥ": "s",
        "ŝ": "s",
        "ṡ": "s",
        "š": "s",
        "ṧ": "s",
        "ṣ": "s",
        "ṩ": "s",
        "ș": "s",
        "ş": "s",
        "ȿ": "s",
        "ꞩ": "s",
        "ꞅ": "s",
        "ẛ": "s",
        "ⓣ": "t",
        "ｔ": "t",
        "ṫ": "t",
        "ẗ": "t",
        "ť": "t",
        "ṭ": "t",
        "ț": "t",
        "ţ": "t",
        "ṱ": "t",
        "ṯ": "t",
        "ŧ": "t",
        "ƭ": "t",
        "ʈ": "t",
        "ⱦ": "t",
        "ꞇ": "t",
        "ꜩ": "tz",
        "ⓤ": "u",
        "ｕ": "u",
        "ù": "u",
        "ú": "u",
        "û": "u",
        "ũ": "u",
        "ṹ": "u",
        "ū": "u",
        "ṻ": "u",
        "ŭ": "u",
        "ü": "u",
        "ǜ": "u",
        "ǘ": "u",
        "ǖ": "u",
        "ǚ": "u",
        "ủ": "u",
        "ů": "u",
        "ű": "u",
        "ǔ": "u",
        "ȕ": "u",
        "ȗ": "u",
        "ư": "u",
        "ừ": "u",
        "ứ": "u",
        "ữ": "u",
        "ử": "u",
        "ự": "u",
        "ụ": "u",
        "ṳ": "u",
        "ų": "u",
        "ṷ": "u",
        "ṵ": "u",
        "ʉ": "u",
        "ⓥ": "v",
        "ｖ": "v",
        "ṽ": "v",
        "ṿ": "v",
        "ʋ": "v",
        "ꝟ": "v",
        "ʌ": "v",
        "ꝡ": "vy",
        "ⓦ": "w",
        "ｗ": "w",
        "ẁ": "w",
        "ẃ": "w",
        "ŵ": "w",
        "ẇ": "w",
        "ẅ": "w",
        "ẘ": "w",
        "ẉ": "w",
        "ⱳ": "w",
        "ⓧ": "x",
        "ｘ": "x",
        "ẋ": "x",
        "ẍ": "x",
        "ⓨ": "y",
        "ｙ": "y",
        "ỳ": "y",
        "ý": "y",
        "ŷ": "y",
        "ỹ": "y",
        "ȳ": "y",
        "ẏ": "y",
        "ÿ": "y",
        "ỷ": "y",
        "ẙ": "y",
        "ỵ": "y",
        "ƴ": "y",
        "ɏ": "y",
        "ỿ": "y",
        "ⓩ": "z",
        "ｚ": "z",
        "ź": "z",
        "ẑ": "z",
        "ż": "z",
        "ž": "z",
        "ẓ": "z",
        "ẕ": "z",
        "ƶ": "z",
        "ȥ": "z",
        "ɀ": "z",
        "ⱬ": "z",
        "ꝣ": "z",
        "Ά": "Α",
        "Έ": "Ε",
        "Ή": "Η",
        "Ί": "Ι",
        "Ϊ": "Ι",
        "Ό": "Ο",
        "Ύ": "Υ",
        "Ϋ": "Υ",
        "Ώ": "Ω",
        "ά": "α",
        "έ": "ε",
        "ή": "η",
        "ί": "ι",
        "ϊ": "ι",
        "ΐ": "ι",
        "ό": "ο",
        "ύ": "υ",
        "ϋ": "υ",
        "ΰ": "υ",
        "ω": "ω",
        "ς": "σ"
    };
    $document = $(document);
    nextUid = function() {
        var counter = 1;
        return function() {
            return counter++;
        };
    }();
    function reinsertElement(element) {
        var placeholder = $(document.createTextNode(""));
        element.before(placeholder);
        placeholder.before(element);
        placeholder.remove();
    }
    function stripDiacritics(str) {
        function match(a) {
            return DIACRITICS[a] || a;
        }
        return str.replace(/[^\u0000-\u007E]/g, match);
    }
    function indexOf(value, array) {
        var i = 0, l = array.length;
        for (;i < l; i = i + 1) {
            if (equal(value, array[i])) return i;
        }
        return -1;
    }
    function measureScrollbar() {
        var $template = $(MEASURE_SCROLLBAR_TEMPLATE);
        $template.appendTo($(document.body));
        var dim = {
            width: $template.width() - $template[0].clientWidth,
            height: $template.height() - $template[0].clientHeight
        };
        $template.remove();
        return dim;
    }
    function equal(a, b) {
        if (a === b) return true;
        if (a === undefined || b === undefined) return false;
        if (a === null || b === null) return false;
        if (a.constructor === String) return a + "" === b + "";
        if (b.constructor === String) return b + "" === a + "";
        return false;
    }
    function splitVal(string, separator, transform) {
        var val, i, l;
        if (string === null || string.length < 1) return [];
        val = string.split(separator);
        for (i = 0, l = val.length; i < l; i = i + 1) val[i] = transform(val[i]);
        return val;
    }
    function getSideBorderPadding(element) {
        return element.outerWidth(false) - element.width();
    }
    function installKeyUpChangeEvent(element) {
        var key = "keyup-change-value";
        element.on("keydown", function() {
            if ($.data(element, key) === undefined) {
                $.data(element, key, element.val());
            }
        });
        element.on("keyup", function() {
            var val = $.data(element, key);
            if (val !== undefined && element.val() !== val) {
                $.removeData(element, key);
                element.trigger("keyup-change");
            }
        });
    }
    function installFilteredMouseMove(element) {
        element.on("mousemove", function(e) {
            var lastpos = lastMousePosition;
            if (lastpos === undefined || lastpos.x !== e.pageX || lastpos.y !== e.pageY) {
                $(e.target).trigger("mousemove-filtered", e);
            }
        });
    }
    function debounce(quietMillis, fn, ctx) {
        ctx = ctx || undefined;
        var timeout;
        return function() {
            var args = arguments;
            window.clearTimeout(timeout);
            timeout = window.setTimeout(function() {
                fn.apply(ctx, args);
            }, quietMillis);
        };
    }
    function installDebouncedScroll(threshold, element) {
        var notify = debounce(threshold, function(e) {
            element.trigger("scroll-debounced", e);
        });
        element.on("scroll", function(e) {
            if (indexOf(e.target, element.get()) >= 0) notify(e);
        });
    }
    function focus($el) {
        if ($el[0] === document.activeElement) return;
        window.setTimeout(function() {
            var el = $el[0], pos = $el.val().length, range;
            $el.focus();
            var isVisible = el.offsetWidth > 0 || el.offsetHeight > 0;
            if (isVisible && el === document.activeElement) {
                if (el.setSelectionRange) {
                    el.setSelectionRange(pos, pos);
                } else if (el.createTextRange) {
                    range = el.createTextRange();
                    range.collapse(false);
                    range.select();
                }
            }
        }, 0);
    }
    function getCursorInfo(el) {
        el = $(el)[0];
        var offset = 0;
        var length = 0;
        if ("selectionStart" in el) {
            offset = el.selectionStart;
            length = el.selectionEnd - offset;
        } else if ("selection" in document) {
            el.focus();
            var sel = document.selection.createRange();
            length = document.selection.createRange().text.length;
            sel.moveStart("character", -el.value.length);
            offset = sel.text.length - length;
        }
        return {
            offset: offset,
            length: length
        };
    }
    function killEvent(event) {
        event.preventDefault();
        event.stopPropagation();
    }
    function killEventImmediately(event) {
        event.preventDefault();
        event.stopImmediatePropagation();
    }
    function measureTextWidth(e) {
        if (!sizer) {
            var style = e[0].currentStyle || window.getComputedStyle(e[0], null);
            sizer = $(document.createElement("div")).css({
                position: "absolute",
                left: "-10000px",
                top: "-10000px",
                display: "none",
                fontSize: style.fontSize,
                fontFamily: style.fontFamily,
                fontStyle: style.fontStyle,
                fontWeight: style.fontWeight,
                letterSpacing: style.letterSpacing,
                textTransform: style.textTransform,
                whiteSpace: "nowrap"
            });
            sizer.attr("class", "select2-sizer");
            $(document.body).append(sizer);
        }
        sizer.text(e.val());
        return sizer.width();
    }
    function syncCssClasses(dest, src, adapter) {
        var classes, replacements = [], adapted;
        classes = $.trim(dest.attr("class"));
        if (classes) {
            classes = "" + classes;
            $(classes.split(/\s+/)).each2(function() {
                if (this.indexOf("select2-") === 0) {
                    replacements.push(this);
                }
            });
        }
        classes = $.trim(src.attr("class"));
        if (classes) {
            classes = "" + classes;
            $(classes.split(/\s+/)).each2(function() {
                if (this.indexOf("select2-") !== 0) {
                    adapted = adapter(this);
                    if (adapted) {
                        replacements.push(adapted);
                    }
                }
            });
        }
        dest.attr("class", replacements.join(" "));
    }
    function markMatch(text, term, markup, escapeMarkup) {
        var match = stripDiacritics(text.toUpperCase()).indexOf(stripDiacritics(term.toUpperCase())), tl = term.length;
        if (match < 0) {
            markup.push(escapeMarkup(text));
            return;
        }
        markup.push(escapeMarkup(text.substring(0, match)));
        markup.push("<span class='select2-match'>");
        markup.push(escapeMarkup(text.substring(match, match + tl)));
        markup.push("</span>");
        markup.push(escapeMarkup(text.substring(match + tl, text.length)));
    }
    function defaultEscapeMarkup(markup) {
        var replace_map = {
            "\\": "&#92;",
            "&": "&amp;",
            "<": "&lt;",
            ">": "&gt;",
            '"': "&quot;",
            "'": "&#39;",
            "/": "&#47;"
        };
        return String(markup).replace(/[&<>"'\/\\]/g, function(match) {
            return replace_map[match];
        });
    }
    function ajax(options) {
        var timeout, handler = null, quietMillis = options.quietMillis || 100, ajaxUrl = options.url, self = this;
        return function(query) {
            window.clearTimeout(timeout);
            timeout = window.setTimeout(function() {
                var data = options.data, url = ajaxUrl, transport = options.transport || $.fn.select2.ajaxDefaults.transport, deprecated = {
                    type: options.type || "GET",
                    cache: options.cache || false,
                    jsonpCallback: options.jsonpCallback || undefined,
                    dataType: options.dataType || "json"
                }, params = $.extend({}, $.fn.select2.ajaxDefaults.params, deprecated);
                data = data ? data.call(self, query.term, query.page, query.context) : null;
                url = typeof url === "function" ? url.call(self, query.term, query.page, query.context) : url;
                if (handler && typeof handler.abort === "function") {
                    handler.abort();
                }
                if (options.params) {
                    if ($.isFunction(options.params)) {
                        $.extend(params, options.params.call(self));
                    } else {
                        $.extend(params, options.params);
                    }
                }
                $.extend(params, {
                    url: url,
                    dataType: options.dataType,
                    data: data,
                    success: function(data) {
                        var results = options.results(data, query.page, query);
                        query.callback(results);
                    },
                    error: function(jqXHR, textStatus, errorThrown) {
                        var results = {
                            hasError: true,
                            jqXHR: jqXHR,
                            textStatus: textStatus,
                            errorThrown: errorThrown
                        };
                        query.callback(results);
                    }
                });
                handler = transport.call(self, params);
            }, quietMillis);
        };
    }
    function local(options) {
        var data = options, dataText, tmp, text = function(item) {
            return "" + item.text;
        };
        if ($.isArray(data)) {
            tmp = data;
            data = {
                results: tmp
            };
        }
        if ($.isFunction(data) === false) {
            tmp = data;
            data = function() {
                return tmp;
            };
        }
        var dataItem = data();
        if (dataItem.text) {
            text = dataItem.text;
            if (!$.isFunction(text)) {
                dataText = dataItem.text;
                text = function(item) {
                    return item[dataText];
                };
            }
        }
        return function(query) {
            var t = query.term, filtered = {
                results: []
            }, process;
            if (t === "") {
                query.callback(data());
                return;
            }
            process = function(datum, collection) {
                var group, attr;
                datum = datum[0];
                if (datum.children) {
                    group = {};
                    for (attr in datum) {
                        if (datum.hasOwnProperty(attr)) group[attr] = datum[attr];
                    }
                    group.children = [];
                    $(datum.children).each2(function(i, childDatum) {
                        process(childDatum, group.children);
                    });
                    if (group.children.length || query.matcher(t, text(group), datum)) {
                        collection.push(group);
                    }
                } else {
                    if (query.matcher(t, text(datum), datum)) {
                        collection.push(datum);
                    }
                }
            };
            $(data().results).each2(function(i, datum) {
                process(datum, filtered.results);
            });
            query.callback(filtered);
        };
    }
    function tags(data) {
        var isFunc = $.isFunction(data);
        return function(query) {
            var t = query.term, filtered = {
                results: []
            };
            var result = isFunc ? data(query) : data;
            if ($.isArray(result)) {
                $(result).each(function() {
                    var isObject = this.text !== undefined, text = isObject ? this.text : this;
                    if (t === "" || query.matcher(t, text)) {
                        filtered.results.push(isObject ? this : {
                            id: this,
                            text: this
                        });
                    }
                });
                query.callback(filtered);
            }
        };
    }
    function checkFormatter(formatter, formatterName) {
        if ($.isFunction(formatter)) return true;
        if (!formatter) return false;
        if (typeof formatter === "string") return true;
        throw new Error(formatterName + " must be a string, function, or falsy value");
    }
    function evaluate(val, context) {
        if ($.isFunction(val)) {
            var args = Array.prototype.slice.call(arguments, 2);
            return val.apply(context, args);
        }
        return val;
    }
    function countResults(results) {
        var count = 0;
        $.each(results, function(i, item) {
            if ($(item.element).is("optgroup")) {
                count += countResults(item.children);
            } else {
                if (item.children && item.children.length) {
                    count += countResults(item.children);
                }
                count++;
            }
        });
        return count;
    }
    function defaultTokenizer(input, selection, selectCallback, opts) {
        var original = input, dupe = false, token, index, i, l, separator;
        if (!opts.createSearchChoice || !opts.tokenSeparators || opts.tokenSeparators.length < 1) return undefined;
        while (true) {
            index = -1;
            for (i = 0, l = opts.tokenSeparators.length; i < l; i++) {
                separator = opts.tokenSeparators[i];
                index = input.indexOf(separator);
                if (index >= 0) break;
            }
            if (index < 0) break;
            token = input.substring(0, index);
            input = input.substring(index + separator.length);
            if (token.length > 0) {
                token = opts.createSearchChoice.call(this, token, selection);
                if (token !== undefined && token !== null && opts.id(token) !== undefined && opts.id(token) !== null) {
                    dupe = false;
                    for (i = 0, l = selection.length; i < l; i++) {
                        if (equal(opts.id(token), opts.id(selection[i]))) {
                            dupe = true;
                            break;
                        }
                    }
                    if (!dupe) selectCallback(token);
                }
            }
        }
        if (original !== input) return input;
    }
    function cleanupJQueryElements() {
        var self = this;
        $.each(arguments, function(i, element) {
            self[element].remove();
            self[element] = null;
        });
    }
    function clazz(SuperClass, methods) {
        var constructor = function() {};
        constructor.prototype = new SuperClass();
        constructor.prototype.constructor = constructor;
        constructor.prototype.parent = SuperClass.prototype;
        constructor.prototype = $.extend(constructor.prototype, methods);
        return constructor;
    }
    AbstractSelect2 = clazz(Object, {
        bind: function(func) {
            var self = this;
            return function() {
                func.apply(self, arguments);
            };
        },
        init: function(opts) {
            var results, search, resultsSelector = ".select2-results";
            this.opts = opts = this.prepareOpts(opts);
            this.id = opts.id;
            if (opts.element.data("select2") !== undefined && opts.element.data("select2") !== null) {
                opts.element.data("select2").destroy();
            }
            this.container = this.createContainer();
            this.liveRegion = $(".select2-hidden-accessible");
            if (this.liveRegion.length == 0) {
                this.liveRegion = $("<span>", {
                    role: "status",
                    "aria-live": "polite"
                }).addClass("select2-hidden-accessible").appendTo($(document.body));
            }
            this.containerId = "s2id_" + (opts.element.attr("id") || "autogen" + nextUid());
            this.containerEventName = this.containerId.replace(/([.])/g, "_").replace(/([;&,\-\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g, "\\$1");
            this.container.attr("id", this.containerId);
            this.container.attr("title", opts.element.attr("title"));
            this.body = $(document.body);
            syncCssClasses(this.container, this.opts.element, this.opts.adaptContainerCssClass);
            this.container.attr("style", opts.element.attr("style"));
            this.container.css(evaluate(opts.containerCss, this.opts.element));
            this.container.addClass(evaluate(opts.containerCssClass, this.opts.element));
            this.elementTabIndex = this.opts.element.attr("tabindex");
            this.opts.element.data("select2", this).attr("tabindex", "-1").before(this.container).on("click.select2", killEvent);
            this.container.data("select2", this);
            this.dropdown = this.container.find(".select2-drop");
            syncCssClasses(this.dropdown, this.opts.element, this.opts.adaptDropdownCssClass);
            this.dropdown.addClass(evaluate(opts.dropdownCssClass, this.opts.element));
            this.dropdown.data("select2", this);
            this.dropdown.on("click", killEvent);
            this.results = results = this.container.find(resultsSelector);
            this.search = search = this.container.find("input.select2-input");
            this.queryCount = 0;
            this.resultsPage = 0;
            this.context = null;
            this.initContainer();
            this.container.on("click", function(e) {
                if (e.target && $(e.target).is(".select2-search-choice *")) {
                    return;
                }
                return killEvent(e);
            });
            installFilteredMouseMove(this.results);
            this.dropdown.on("mousemove-filtered", resultsSelector, this.bind(this.highlightUnderEvent));
            this.dropdown.on("touchstart touchmove touchend", resultsSelector, this.bind(function(event) {
                this._touchEvent = true;
                this.highlightUnderEvent(event);
            }));
            this.dropdown.on("touchmove", resultsSelector, this.bind(this.touchMoved));
            this.dropdown.on("touchstart touchend", resultsSelector, this.bind(this.clearTouchMoved));
            this.dropdown.on("click", this.bind(function(event) {
                if (this._touchEvent) {
                    this._touchEvent = false;
                    this.selectHighlighted();
                }
            }));
            installDebouncedScroll(80, this.results);
            this.dropdown.on("scroll-debounced", resultsSelector, this.bind(this.loadMoreIfNeeded));
            $(this.container).on("change", ".select2-input", function(e) {
                e.stopPropagation();
            });
            $(this.dropdown).on("change", ".select2-input", function(e) {
                e.stopPropagation();
            });
            if ($.fn.mousewheel) {
                results.mousewheel(function(e, delta, deltaX, deltaY) {
                    var top = results.scrollTop();
                    if (deltaY > 0 && top - deltaY <= 0) {
                        results.scrollTop(0);
                        killEvent(e);
                    } else if (deltaY < 0 && results.get(0).scrollHeight - results.scrollTop() + deltaY <= results.height()) {
                        results.scrollTop(results.get(0).scrollHeight - results.height());
                        killEvent(e);
                    }
                });
            }
            installKeyUpChangeEvent(search);
            search.on("keyup-change input paste", this.bind(this.updateResults));
            search.on("focus", function() {
                search.addClass("select2-focused");
            });
            search.on("blur", function() {
                search.removeClass("select2-focused");
            });
            this.dropdown.on("mouseup", resultsSelector, this.bind(function(e) {
                if ($(e.target).closest(".select2-result-selectable").length > 0) {
                    this.highlightUnderEvent(e);
                    this.selectHighlighted(e);
                }
            }));
            this.dropdown.on("click mouseup mousedown touchstart touchend focusin", function(e) {
                var replacement = $.Event(e.type + ".sortable");
                e.stopPropagation();
                $(e.target).trigger(replacement);
            });
            this.nextSearchTerm = undefined;
            if ($.isFunction(this.opts.initSelection)) {
                this.initSelection();
                this.monitorSource();
            }
            if (opts.maximumInputLength !== null) {
                this.search.attr("maxlength", opts.maximumInputLength);
            }
            var disabled = opts.element.prop("disabled");
            if (disabled === undefined) disabled = false;
            this.enable(!disabled);
            var readonly = opts.element.prop("readonly");
            if (readonly === undefined) readonly = false;
            this.readonly(readonly);
            scrollBarDimensions = scrollBarDimensions || measureScrollbar();
            this.autofocus = opts.element.prop("autofocus");
            opts.element.prop("autofocus", false);
            if (this.autofocus) this.focus();
            this.search.attr("placeholder", opts.searchInputPlaceholder);
        },
        destroy: function() {
            var element = this.opts.element, select2 = element.data("select2"), self = this;
            this.close();
            if (element.length && element[0].detachEvent && self._sync) {
                element.each(function() {
                    if (self._sync) {
                        this.detachEvent("onpropertychange", self._sync);
                    }
                });
            }
            if (this.propertyObserver) {
                this.propertyObserver.disconnect();
                this.propertyObserver = null;
            }
            this._sync = null;
            if (select2 !== undefined) {
                select2.container.remove();
                select2.liveRegion.remove();
                select2.dropdown.remove();
                element.show().removeData("select2").off(".select2").prop("autofocus", this.autofocus || false);
                if (this.elementTabIndex) {
                    element.attr({
                        tabindex: this.elementTabIndex
                    });
                } else {
                    element.removeAttr("tabindex");
                }
                element.show();
            }
            cleanupJQueryElements.call(this, "container", "liveRegion", "dropdown", "results", "search");
        },
        optionToData: function(element) {
            if (element.is("option")) {
                return {
                    id: element.prop("value"),
                    text: element.text(),
                    element: element.get(),
                    css: element.attr("class"),
                    disabled: element.prop("disabled"),
                    locked: equal(element.attr("locked"), "locked") || equal(element.data("locked"), true)
                };
            } else if (element.is("optgroup")) {
                return {
                    text: element.attr("label"),
                    children: [],
                    element: element.get(),
                    css: element.attr("class")
                };
            }
        },
        prepareOpts: function(opts) {
            var element, select, idKey, ajaxUrl, self = this;
            element = opts.element;
            if (element.get(0).tagName.toLowerCase() === "select") {
                this.select = select = opts.element;
            }
            if (select) {
                $.each([ "id", "multiple", "ajax", "query", "createSearchChoice", "initSelection", "data", "tags" ], function() {
                    if (this in opts) {
                        throw new Error("Option '" + this + "' is not allowed for Select2 when attached to a <select> element.");
                    }
                });
            }
            opts = $.extend({}, {
                populateResults: function(container, results, query) {
                    var populate, id = this.opts.id, liveRegion = this.liveRegion;
                    populate = function(results, container, depth) {
                        var i, l, result, selectable, disabled, compound, node, label, innerContainer, formatted;
                        results = opts.sortResults(results, container, query);
                        var nodes = [];
                        for (i = 0, l = results.length; i < l; i = i + 1) {
                            result = results[i];
                            disabled = result.disabled === true;
                            selectable = !disabled && id(result) !== undefined;
                            compound = result.children && result.children.length > 0;
                            node = $("<li></li>");
                            node.addClass("select2-results-dept-" + depth);
                            node.addClass("select2-result");
                            node.addClass(selectable ? "select2-result-selectable" : "select2-result-unselectable");
                            if (disabled) {
                                node.addClass("select2-disabled");
                            }
                            if (compound) {
                                node.addClass("select2-result-with-children");
                            }
                            node.addClass(self.opts.formatResultCssClass(result));
                            node.attr("role", "presentation");
                            label = $(document.createElement("div"));
                            label.addClass("select2-result-label");
                            label.attr("id", "select2-result-label-" + nextUid());
                            label.attr("role", "option");
                            formatted = opts.formatResult(result, label, query, self.opts.escapeMarkup);
                            if (formatted !== undefined) {
                                label.html(formatted);
                                node.append(label);
                            }
                            if (compound) {
                                innerContainer = $("<ul></ul>");
                                innerContainer.addClass("select2-result-sub");
                                populate(result.children, innerContainer, depth + 1);
                                node.append(innerContainer);
                            }
                            node.data("select2-data", result);
                            nodes.push(node[0]);
                        }
                        container.append(nodes);
                        liveRegion.text(opts.formatMatches(results.length));
                    };
                    populate(results, container, 0);
                }
            }, $.fn.select2.defaults, opts);
            if (typeof opts.id !== "function") {
                idKey = opts.id;
                opts.id = function(e) {
                    return e[idKey];
                };
            }
            if ($.isArray(opts.element.data("select2Tags"))) {
                if ("tags" in opts) {
                    throw "tags specified as both an attribute 'data-select2-tags' and in options of Select2 " + opts.element.attr("id");
                }
                opts.tags = opts.element.data("select2Tags");
            }
            if (select) {
                var supportTree = select.hasClass("js-tree-select");
                opts.query = this.bind(function(query) {
                    var data = {
                        results: [],
                        more: false
                    }, term = query.term, children, placeholderOption, process;
                    children = element.children();
                    if (this.getPlaceholder() !== undefined && children.length > 0) {
                        placeholderOption = this.getPlaceholderOption();
                        if (placeholderOption) {
                            children = children.not(placeholderOption);
                        }
                    }
                    if (supportTree) {
                        var collect = function(options) {
                            var tree = [];
                            var parent = null;
                            options.each2(function(i, option) {
                                var item = {
                                    element: $(option[0]),
                                    id: parseInt(option.data("id")),
                                    children: []
                                };
                                if (option.is("option")) {
                                    if (parent && parent.id == parseInt(option.data("parent-id"))) {
                                        parent.children.push(item);
                                    } else {
                                        parent = item;
                                        tree.push(item);
                                    }
                                } else if (option.is("optgroup")) {
                                    item.children = collect(option.children());
                                    tree.push(item);
                                    parent = null;
                                }
                            });
                            return tree;
                        };
                        process = function(tree, collection) {
                            tree.forEach(function(item) {
                                if (item.element.is("option")) {
                                    var children = [];
                                    process(item.children, children);
                                    if (query.matcher(term, item.element.text(), item.element)) {
                                        collection.push($.extend(self.optionToData(item.element), {
                                            children: children
                                        }));
                                    } else if (children.length > 0) {
                                        collection.push($.extend(self.optionToData(item.element), {
                                            disabled: true,
                                            children: children
                                        }));
                                    }
                                } else if (item.element.is("optgroup")) {
                                    var group = self.optionToData(item.element);
                                    process(item.children, group.children);
                                    if (group.children.length > 0) {
                                        collection.push(group);
                                    }
                                }
                            });
                        };
                        process(collect(children), data.results);
                    } else {
                        process = function(element, collection) {
                            var group;
                            if (element.is("option")) {
                                if (query.matcher(term, element.text(), element)) {
                                    collection.push(self.optionToData(element));
                                }
                            } else if (element.is("optgroup")) {
                                group = self.optionToData(element);
                                element.children().each2(function(i, elm) {
                                    process(elm, group.children);
                                });
                                if (group.children.length > 0) {
                                    collection.push(group);
                                }
                            }
                        };
                        children.each2(function(i, elm) {
                            process(elm, data.results);
                        });
                    }
                    query.callback(data);
                });
                opts.id = function(e) {
                    return e.id;
                };
            } else {
                if (!("query" in opts)) {
                    if ("ajax" in opts) {
                        ajaxUrl = opts.element.data("ajax-url");
                        if (ajaxUrl && ajaxUrl.length > 0) {
                            opts.ajax.url = ajaxUrl;
                        }
                        opts.query = ajax.call(opts.element, opts.ajax);
                    } else if ("data" in opts) {
                        opts.query = local(opts.data);
                    } else if ("tags" in opts) {
                        opts.query = tags(opts.tags);
                        if (opts.createSearchChoice === undefined) {
                            opts.createSearchChoice = function(term) {
                                return {
                                    id: $.trim(term),
                                    text: $.trim(term)
                                };
                            };
                        }
                        if (opts.initSelection === undefined) {
                            opts.initSelection = function(element, callback) {
                                var data = [];
                                $(splitVal(element.val(), opts.separator, opts.transformVal)).each(function() {
                                    var obj = {
                                        id: this,
                                        text: this
                                    }, tags = opts.tags;
                                    if ($.isFunction(tags)) tags = tags();
                                    $(tags).each(function() {
                                        if (equal(this.id, obj.id)) {
                                            obj = this;
                                            return false;
                                        }
                                    });
                                    data.push(obj);
                                });
                                callback(data);
                            };
                        }
                    }
                }
            }
            if (typeof opts.query !== "function") {
                throw "query function not defined for Select2 " + opts.element.attr("id");
            }
            if (opts.createSearchChoicePosition === "top") {
                opts.createSearchChoicePosition = function(list, item) {
                    list.unshift(item);
                };
            } else if (opts.createSearchChoicePosition === "bottom") {
                opts.createSearchChoicePosition = function(list, item) {
                    list.push(item);
                };
            } else if (typeof opts.createSearchChoicePosition !== "function") {
                throw "invalid createSearchChoicePosition option must be 'top', 'bottom' or a custom function";
            }
            return opts;
        },
        monitorSource: function() {
            var el = this.opts.element, observer, self = this;
            el.on("change.select2", this.bind(function(e) {
                if (this.opts.element.data("select2-change-triggered") !== true) {
                    this.initSelection();
                }
            }));
            this._sync = this.bind(function() {
                var disabled = el.prop("disabled");
                if (disabled === undefined) disabled = false;
                this.enable(!disabled);
                var readonly = el.prop("readonly");
                if (readonly === undefined) readonly = false;
                this.readonly(readonly);
                if (this.container) {
                    syncCssClasses(this.container, this.opts.element, this.opts.adaptContainerCssClass);
                    this.container.addClass(evaluate(this.opts.containerCssClass, this.opts.element));
                }
                if (this.dropdown) {
                    syncCssClasses(this.dropdown, this.opts.element, this.opts.adaptDropdownCssClass);
                    this.dropdown.addClass(evaluate(this.opts.dropdownCssClass, this.opts.element));
                }
            });
            if (el.length && el[0].attachEvent) {
                el.each(function() {
                    this.attachEvent("onpropertychange", self._sync);
                });
            }
            observer = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
            if (observer !== undefined) {
                if (this.propertyObserver) {
                    delete this.propertyObserver;
                    this.propertyObserver = null;
                }
                this.propertyObserver = new observer(function(mutations) {
                    $.each(mutations, self._sync);
                });
                this.propertyObserver.observe(el.get(0), {
                    attributes: true,
                    subtree: false
                });
            }
        },
        triggerSelect: function(data) {
            var evt = $.Event("select2-selecting", {
                val: this.id(data),
                object: data,
                choice: data
            });
            this.opts.element.trigger(evt);
            return !evt.isDefaultPrevented();
        },
        triggerChange: function(details) {
            details = details || {};
            details = $.extend({}, details, {
                type: "change",
                val: this.val()
            });
            this.opts.element.data("select2-change-triggered", true);
            this.opts.element.trigger(details);
            this.opts.element.data("select2-change-triggered", false);
            this.opts.element.click();
            if (this.opts.blurOnChange) this.opts.element.blur();
        },
        isInterfaceEnabled: function() {
            return this.enabledInterface === true;
        },
        enableInterface: function() {
            var enabled = this._enabled && !this._readonly, disabled = !enabled;
            if (enabled === this.enabledInterface) return false;
            this.container.toggleClass("select2-container-disabled", disabled);
            this.close();
            this.enabledInterface = enabled;
            return true;
        },
        enable: function(enabled) {
            if (enabled === undefined) enabled = true;
            if (this._enabled === enabled) return;
            this._enabled = enabled;
            this.opts.element.prop("disabled", !enabled);
            this.enableInterface();
        },
        disable: function() {
            this.enable(false);
        },
        readonly: function(enabled) {
            if (enabled === undefined) enabled = false;
            if (this._readonly === enabled) return;
            this._readonly = enabled;
            this.opts.element.prop("readonly", enabled);
            this.enableInterface();
        },
        opened: function() {
            return this.container ? this.container.hasClass("select2-dropdown-open") : false;
        },
        positionDropdown: function() {
            var $dropdown = this.dropdown, container = this.container, offset = container.offset(), height = container.outerHeight(false), width = container.outerWidth(false), dropHeight = $dropdown.outerHeight(false), $window = $(window), windowWidth = $window.width(), windowHeight = $window.height(), viewPortRight = $window.scrollLeft() + windowWidth, viewportBottom = $window.scrollTop() + windowHeight, dropTop = offset.top + height, dropLeft = offset.left, enoughRoomBelow = dropTop + dropHeight <= viewportBottom, enoughRoomAbove = offset.top - dropHeight >= $window.scrollTop(), dropWidth = $dropdown.outerWidth(false), enoughRoomOnRight = function() {
                return dropLeft + dropWidth <= viewPortRight;
            }, enoughRoomOnLeft = function() {
                return offset.left + viewPortRight + container.outerWidth(false) > dropWidth;
            }, aboveNow = $dropdown.hasClass("select2-drop-above"), bodyOffset, above, changeDirection, css, resultsListNode;
            if (aboveNow) {
                above = true;
                if (!enoughRoomAbove && enoughRoomBelow) {
                    changeDirection = true;
                    above = false;
                }
            } else {
                above = false;
                if (!enoughRoomBelow && enoughRoomAbove) {
                    changeDirection = true;
                    above = true;
                }
            }
            if (changeDirection) {
                $dropdown.hide();
                offset = this.container.offset();
                height = this.container.outerHeight(false);
                width = this.container.outerWidth(false);
                dropHeight = $dropdown.outerHeight(false);
                viewPortRight = $window.scrollLeft() + windowWidth;
                viewportBottom = $window.scrollTop() + windowHeight;
                dropTop = offset.top + height;
                dropLeft = offset.left;
                dropWidth = $dropdown.outerWidth(false);
                $dropdown.show();
                this.focusSearch();
            }
            if (this.opts.dropdownAutoWidth) {
                resultsListNode = $(".select2-results", $dropdown)[0];
                $dropdown.addClass("select2-drop-auto-width");
                $dropdown.css("width", "");
                dropWidth = $dropdown.outerWidth(false) + (resultsListNode.scrollHeight === resultsListNode.clientHeight ? 0 : scrollBarDimensions.width);
                dropWidth > width ? width = dropWidth : dropWidth = width;
                dropHeight = $dropdown.outerHeight(false);
            } else {
                this.container.removeClass("select2-drop-auto-width");
            }
            if (this.body.css("position") !== "static") {
                bodyOffset = this.body.offset();
                dropTop -= bodyOffset.top;
                dropLeft -= bodyOffset.left;
            }
            if (!enoughRoomOnRight() && enoughRoomOnLeft()) {
                dropLeft = offset.left + this.container.outerWidth(false) - dropWidth;
            }
            css = {
                left: dropLeft,
                width: width
            };
            if (above) {
                css.top = offset.top - dropHeight;
                css.bottom = "auto";
                this.container.addClass("select2-drop-above");
                $dropdown.addClass("select2-drop-above");
            } else {
                css.top = dropTop;
                css.bottom = "auto";
                this.container.removeClass("select2-drop-above");
                $dropdown.removeClass("select2-drop-above");
            }
            css = $.extend(css, evaluate(this.opts.dropdownCss, this.opts.element));
            $dropdown.css(css);
        },
        shouldOpen: function() {
            var event;
            if (this.opened()) return false;
            if (this._enabled === false || this._readonly === true) return false;
            event = $.Event("select2-opening");
            this.opts.element.trigger(event);
            return !event.isDefaultPrevented();
        },
        clearDropdownAlignmentPreference: function() {
            this.container.removeClass("select2-drop-above");
            this.dropdown.removeClass("select2-drop-above");
        },
        open: function() {
            if (!this.shouldOpen()) return false;
            this.opening();
            $document.on("mousemove.select2Event", function(e) {
                lastMousePosition.x = e.pageX;
                lastMousePosition.y = e.pageY;
            });
            return true;
        },
        opening: function() {
            var cid = this.containerEventName, scroll = "scroll." + cid, resize = "resize." + cid, orient = "orientationchange." + cid, mask;
            this.container.addClass("select2-dropdown-open").addClass("select2-container-active");
            this.clearDropdownAlignmentPreference();
            if (this.dropdown[0] !== this.body.children().last()[0]) {
                this.dropdown.detach().appendTo(this.body);
            }
            mask = $("#select2-drop-mask");
            if (mask.length === 0) {
                mask = $(document.createElement("div"));
                mask.attr("id", "select2-drop-mask").attr("class", "select2-drop-mask");
                mask.hide();
                mask.appendTo(this.body);
                mask.on("mousedown touchstart click", function(e) {
                    reinsertElement(mask);
                    var dropdown = $("#select2-drop"), self;
                    if (dropdown.length > 0) {
                        self = dropdown.data("select2");
                        if (self.opts.selectOnBlur) {
                            self.selectHighlighted({
                                noFocus: true
                            });
                        }
                        self.close();
                        e.preventDefault();
                        e.stopPropagation();
                    }
                });
            }
            if (this.dropdown.prev()[0] !== mask[0]) {
                this.dropdown.before(mask);
            }
            $("#select2-drop").removeAttr("id");
            this.dropdown.attr("id", "select2-drop");
            mask.show();
            this.positionDropdown();
            this.dropdown.show();
            this.positionDropdown();
            this.dropdown.addClass("select2-drop-active");
            var that = this;
            this.container.parents().add(window).each(function() {
                $(this).on(resize + " " + scroll + " " + orient, function(e) {
                    if (that.opened()) that.positionDropdown();
                });
            });
        },
        close: function() {
            if (!this.opened()) return;
            var cid = this.containerEventName, scroll = "scroll." + cid, resize = "resize." + cid, orient = "orientationchange." + cid;
            this.container.parents().add(window).each(function() {
                $(this).off(scroll).off(resize).off(orient);
            });
            this.clearDropdownAlignmentPreference();
            $("#select2-drop-mask").hide();
            this.dropdown.removeAttr("id");
            this.dropdown.hide();
            this.container.removeClass("select2-dropdown-open").removeClass("select2-container-active");
            this.results.empty();
            $document.off("mousemove.select2Event");
            this.clearSearch();
            this.search.removeClass("select2-active");
            this.opts.element.trigger($.Event("select2-close"));
        },
        externalSearch: function(term) {
            this.open();
            this.search.val(term);
            this.updateResults(false);
        },
        clearSearch: function() {},
        getMaximumSelectionSize: function() {
            return evaluate(this.opts.maximumSelectionSize, this.opts.element);
        },
        ensureHighlightVisible: function() {
            var results = this.results, children, index, child, hb, rb, y, more, topOffset;
            index = this.highlight();
            if (index < 0) return;
            if (index == 0) {
                results.scrollTop(0);
                return;
            }
            children = this.findHighlightableChoices().find(".select2-result-label");
            child = $(children[index]);
            topOffset = (child.offset() || {}).top || 0;
            hb = topOffset + child.outerHeight(true);
            if (index === children.length - 1) {
                more = results.find("li.select2-more-results");
                if (more.length > 0) {
                    hb = more.offset().top + more.outerHeight(true);
                }
            }
            rb = results.offset().top + results.outerHeight(false);
            if (hb > rb) {
                results.scrollTop(results.scrollTop() + (hb - rb));
            }
            y = topOffset - results.offset().top;
            if (y < 0 && child.css("display") != "none") {
                results.scrollTop(results.scrollTop() + y);
            }
        },
        findHighlightableChoices: function() {
            return this.results.find(".select2-result-selectable:not(.select2-disabled):not(.select2-selected)");
        },
        moveHighlight: function(delta) {
            var choices = this.findHighlightableChoices(), index = this.highlight();
            while (index > -1 && index < choices.length) {
                index += delta;
                var choice = $(choices[index]);
                if (choice.hasClass("select2-result-selectable") && !choice.hasClass("select2-disabled") && !choice.hasClass("select2-selected")) {
                    this.highlight(index);
                    break;
                }
            }
        },
        highlight: function(index) {
            var choices = this.findHighlightableChoices(), choice, data;
            if (arguments.length === 0) {
                return indexOf(choices.filter(".select2-highlighted")[0], choices.get());
            }
            if (index >= choices.length) index = choices.length - 1;
            if (index < 0) index = 0;
            this.removeHighlight();
            choice = $(choices[index]);
            choice.addClass("select2-highlighted");
            this.search.attr("aria-activedescendant", choice.find(".select2-result-label").attr("id"));
            this.ensureHighlightVisible();
            this.liveRegion.text(choice.text());
            data = choice.data("select2-data");
            if (data) {
                this.opts.element.trigger({
                    type: "select2-highlight",
                    val: this.id(data),
                    choice: data
                });
            }
        },
        removeHighlight: function() {
            this.results.find(".select2-highlighted").removeClass("select2-highlighted");
        },
        touchMoved: function() {
            this._touchMoved = true;
        },
        clearTouchMoved: function() {
            this._touchMoved = false;
        },
        countSelectableResults: function() {
            return this.findHighlightableChoices().length;
        },
        highlightUnderEvent: function(event) {
            var el = $(event.target).closest(".select2-result-selectable");
            if (el.length > 0 && !el.is(".select2-highlighted")) {
                var choices = this.findHighlightableChoices();
                this.highlight(choices.index(el));
            } else if (el.length == 0) {
                this.removeHighlight();
            }
        },
        loadMoreIfNeeded: function() {
            var results = this.results, more = results.find("li.select2-more-results"), below, page = this.resultsPage + 1, self = this, term = this.search.val(), context = this.context;
            if (more.length === 0) return;
            below = more.offset().top - results.offset().top - results.height();
            if (below <= this.opts.loadMorePadding) {
                more.addClass("select2-active");
                this.opts.query({
                    element: this.opts.element,
                    term: term,
                    page: page,
                    context: context,
                    matcher: this.opts.matcher,
                    callback: this.bind(function(data) {
                        if (!self.opened()) return;
                        self.opts.populateResults.call(this, results, data.results, {
                            term: term,
                            page: page,
                            context: context
                        });
                        self.postprocessResults(data, false, false);
                        if (data.more === true) {
                            more.detach().appendTo(results).html(self.opts.escapeMarkup(evaluate(self.opts.formatLoadMore, self.opts.element, page + 1)));
                            window.setTimeout(function() {
                                self.loadMoreIfNeeded();
                            }, 10);
                        } else {
                            more.remove();
                        }
                        self.positionDropdown();
                        self.resultsPage = page;
                        self.context = data.context;
                        this.opts.element.trigger({
                            type: "select2-loaded",
                            items: data
                        });
                    })
                });
            }
        },
        tokenize: function() {},
        updateResults: function(initial) {
            var search = this.search, results = this.results, opts = this.opts, data, self = this, input, term = search.val(), lastTerm = $.data(this.container, "select2-last-term"), queryNumber;
            if (initial !== true && lastTerm && equal(term, lastTerm)) return;
            $.data(this.container, "select2-last-term", term);
            if (initial !== true && (this.showSearchInput === false || !this.opened())) {
                return;
            }
            function postRender() {
                search.removeClass("select2-active");
                self.positionDropdown();
                if (results.find(".select2-no-results,.select2-selection-limit,.select2-searching").length) {
                    self.liveRegion.text(results.text());
                } else {
                    self.liveRegion.text(self.opts.formatMatches(results.find('.select2-result-selectable:not(".select2-selected")').length));
                }
            }
            function render(html) {
                results.html(html);
                postRender();
            }
            queryNumber = ++this.queryCount;
            var maxSelSize = this.getMaximumSelectionSize();
            if (maxSelSize >= 1) {
                data = this.data();
                if ($.isArray(data) && data.length >= maxSelSize && checkFormatter(opts.formatSelectionTooBig, "formatSelectionTooBig")) {
                    render("<li class='select2-selection-limit'>" + evaluate(opts.formatSelectionTooBig, opts.element, maxSelSize) + "</li>");
                    return;
                }
            }
            if (search.val().length < opts.minimumInputLength) {
                if (checkFormatter(opts.formatInputTooShort, "formatInputTooShort")) {
                    render("<li class='select2-no-results'>" + evaluate(opts.formatInputTooShort, opts.element, search.val(), opts.minimumInputLength) + "</li>");
                } else {
                    render("");
                }
                if (initial && this.showSearch) this.showSearch(true);
                return;
            }
            if (opts.maximumInputLength && search.val().length > opts.maximumInputLength) {
                if (checkFormatter(opts.formatInputTooLong, "formatInputTooLong")) {
                    render("<li class='select2-no-results'>" + evaluate(opts.formatInputTooLong, opts.element, search.val(), opts.maximumInputLength) + "</li>");
                } else {
                    render("");
                }
                return;
            }
            if (opts.formatSearching && this.findHighlightableChoices().length === 0) {
                render("<li class='select2-searching'>" + evaluate(opts.formatSearching, opts.element) + "</li>");
            }
            search.addClass("select2-active");
            this.removeHighlight();
            input = this.tokenize();
            if (input != undefined && input != null) {
                search.val(input);
            }
            this.resultsPage = 1;
            opts.query({
                element: opts.element,
                term: search.val(),
                page: this.resultsPage,
                context: null,
                matcher: opts.matcher,
                callback: this.bind(function(data) {
                    var def;
                    if (queryNumber != this.queryCount) {
                        return;
                    }
                    if (!this.opened()) {
                        this.search.removeClass("select2-active");
                        return;
                    }
                    if (data.hasError !== undefined && checkFormatter(opts.formatAjaxError, "formatAjaxError")) {
                        render("<li class='select2-ajax-error'>" + evaluate(opts.formatAjaxError, opts.element, data.jqXHR, data.textStatus, data.errorThrown) + "</li>");
                        return;
                    }
                    this.context = data.context === undefined ? null : data.context;
                    if (this.opts.createSearchChoice && search.val() !== "") {
                        def = this.opts.createSearchChoice.call(self, search.val(), data.results);
                        if (def !== undefined && def !== null && self.id(def) !== undefined && self.id(def) !== null) {
                            if ($(data.results).filter(function() {
                                return equal(self.id(this), self.id(def));
                            }).length === 0) {
                                this.opts.createSearchChoicePosition(data.results, def);
                            }
                        }
                    }
                    if (data.results.length === 0 && checkFormatter(opts.formatNoMatches, "formatNoMatches")) {
                        render("<li class='select2-no-results'>" + evaluate(opts.formatNoMatches, opts.element, search.val()) + "</li>");
                        return;
                    }
                    results.empty();
                    self.opts.populateResults.call(this, results, data.results, {
                        term: search.val(),
                        page: this.resultsPage,
                        context: null
                    });
                    if (data.more === true && checkFormatter(opts.formatLoadMore, "formatLoadMore")) {
                        results.append("<li class='select2-more-results'>" + opts.escapeMarkup(evaluate(opts.formatLoadMore, opts.element, this.resultsPage)) + "</li>");
                        window.setTimeout(function() {
                            self.loadMoreIfNeeded();
                        }, 10);
                    }
                    this.postprocessResults(data, initial);
                    postRender();
                    this.opts.element.trigger({
                        type: "select2-loaded",
                        items: data
                    });
                })
            });
        },
        cancel: function() {
            this.close();
        },
        blur: function() {
            if (this.opts.selectOnBlur) this.selectHighlighted({
                noFocus: true
            });
            this.close();
            this.container.removeClass("select2-container-active");
            if (this.search[0] === document.activeElement) {
                this.search.blur();
            }
            this.clearSearch();
            this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus");
        },
        focusSearch: function() {
            focus(this.search);
        },
        selectHighlighted: function(options) {
            if (this._touchMoved) {
                this.clearTouchMoved();
                return;
            }
            var index = this.highlight(), highlighted = this.results.find(".select2-highlighted"), data = highlighted.closest(".select2-result").data("select2-data");
            if (data) {
                this.highlight(index);
                this.onSelect(data, options);
            } else if (options && options.noFocus) {
                this.close();
            }
        },
        getPlaceholder: function() {
            var placeholderOption;
            return this.opts.element.attr("placeholder") || this.opts.element.attr("data-placeholder") || this.opts.element.data("placeholder") || this.opts.placeholder || ((placeholderOption = this.getPlaceholderOption()) !== undefined ? placeholderOption.text() : undefined);
        },
        getPlaceholderOption: function() {
            if (this.select) {
                var firstOption = this.select.children("option").first();
                if (this.opts.placeholderOption !== undefined) {
                    return this.opts.placeholderOption === "first" && firstOption || typeof this.opts.placeholderOption === "function" && this.opts.placeholderOption(this.select);
                } else if ($.trim(firstOption.text()) === "" && firstOption.val() === "") {
                    return firstOption;
                }
            }
        },
        initContainerWidth: function() {
            function resolveContainerWidth() {
                var style, attrs, matches, i, l, attr;
                if (this.opts.width === "off") {
                    return null;
                } else if (this.opts.width === "element") {
                    return this.opts.element.outerWidth(false) === 0 ? "auto" : this.opts.element.outerWidth(false) + "px";
                } else if (this.opts.width === "copy" || this.opts.width === "resolve") {
                    style = this.opts.element.attr("style");
                    if (style !== undefined) {
                        attrs = style.split(";");
                        for (i = 0, l = attrs.length; i < l; i = i + 1) {
                            attr = attrs[i].replace(/\s/g, "");
                            matches = attr.match(/^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i);
                            if (matches !== null && matches.length >= 1) return matches[1];
                        }
                    }
                    if (this.opts.width === "resolve") {
                        style = this.opts.element.css("width");
                        if (style.indexOf("%") > 0) return style;
                        return this.opts.element.outerWidth(false) === 0 ? "auto" : this.opts.element.outerWidth(false) + "px";
                    }
                    return null;
                } else if ($.isFunction(this.opts.width)) {
                    return this.opts.width();
                } else {
                    return this.opts.width;
                }
            }
            var width = resolveContainerWidth.call(this);
            if (width !== null) {
                this.container.css("width", width);
            }
        }
    });
    SingleSelect2 = clazz(AbstractSelect2, {
        createContainer: function() {
            var container = $(document.createElement("div")).attr({
                class: "select2-container"
            }).html([ "<a href='javascript:void(0)' class='select2-choice' tabindex='-1'>", "   <span class='select2-chosen'>&#160;</span><abbr class='select2-search-choice-close'></abbr>", "   <span class='select2-arrow' role='presentation'><b role='presentation'></b></span>", "</a>", "<label for='' class='select2-offscreen'></label>", "<input class='select2-focusser select2-offscreen' type='text' aria-haspopup='true' role='button' />", "<div class='select2-drop select2-display-none'>", "   <div class='select2-search'>", "       <label for='' class='select2-offscreen'></label>", "       <input type='text' autocomplete='off' autocorrect='off' autocapitalize='off' spellcheck='false' class='select2-input' role='combobox' aria-expanded='true'", "       aria-autocomplete='list' />", "   </div>", "   <ul class='select2-results' role='listbox'>", "   </ul>", "</div>" ].join(""));
            return container;
        },
        enableInterface: function() {
            if (this.parent.enableInterface.apply(this, arguments)) {
                this.focusser.prop("disabled", !this.isInterfaceEnabled());
            }
        },
        opening: function() {
            var el, range, len;
            if (this.opts.minimumResultsForSearch >= 0) {
                this.showSearch(true);
            }
            this.parent.opening.apply(this, arguments);
            if (this.showSearchInput !== false) {
                this.search.val(this.focusser.val());
            }
            if (this.opts.shouldFocusInput(this)) {
                this.search.focus();
                el = this.search.get(0);
                if (el.createTextRange) {
                    range = el.createTextRange();
                    range.collapse(false);
                    range.select();
                } else if (el.setSelectionRange) {
                    len = this.search.val().length;
                    el.setSelectionRange(len, len);
                }
            }
            if (this.search.val() === "") {
                if (this.nextSearchTerm != undefined) {
                    this.search.val(this.nextSearchTerm);
                    this.search.select();
                }
            }
            this.focusser.prop("disabled", true).val("");
            this.updateResults(true);
            this.opts.element.trigger($.Event("select2-open"));
        },
        close: function() {
            if (!this.opened()) return;
            this.parent.close.apply(this, arguments);
            this.focusser.prop("disabled", false);
            if (this.opts.shouldFocusInput(this)) {
                this.focusser.focus();
            }
        },
        focus: function() {
            if (this.opened()) {
                this.close();
            } else {
                this.focusser.prop("disabled", false);
                if (this.opts.shouldFocusInput(this)) {
                    this.focusser.focus();
                }
            }
        },
        isFocused: function() {
            return this.container.hasClass("select2-container-active");
        },
        cancel: function() {
            this.parent.cancel.apply(this, arguments);
            this.focusser.prop("disabled", false);
            if (this.opts.shouldFocusInput(this)) {
                this.focusser.focus();
            }
        },
        destroy: function() {
            $("label[for='" + this.focusser.attr("id") + "']").attr("for", this.opts.element.attr("id"));
            this.parent.destroy.apply(this, arguments);
            cleanupJQueryElements.call(this, "selection", "focusser");
        },
        initContainer: function() {
            var selection, container = this.container, dropdown = this.dropdown, idSuffix = nextUid(), elementLabel;
            if (this.opts.minimumResultsForSearch < 0) {
                this.showSearch(false);
            } else {
                this.showSearch(true);
            }
            this.selection = selection = container.find(".select2-choice");
            this.focusser = container.find(".select2-focusser");
            selection.find(".select2-chosen").attr("id", "select2-chosen-" + idSuffix);
            this.focusser.attr("aria-labelledby", "select2-chosen-" + idSuffix);
            this.results.attr("id", "select2-results-" + idSuffix);
            this.search.attr("aria-owns", "select2-results-" + idSuffix);
            this.focusser.attr("id", "s2id_autogen" + idSuffix);
            elementLabel = $("label[for='" + this.opts.element.attr("id") + "']");
            this.opts.element.focus(this.bind(function() {
                this.focus();
            }));
            this.focusser.prev().text(elementLabel.text()).attr("for", this.focusser.attr("id"));
            var originalTitle = this.opts.element.attr("title");
            this.opts.element.attr("title", originalTitle || elementLabel.text());
            this.focusser.attr("tabindex", this.elementTabIndex);
            this.search.attr("id", this.focusser.attr("id") + "_search");
            this.search.prev().text($("label[for='" + this.focusser.attr("id") + "']").text()).attr("for", this.search.attr("id"));
            this.search.on("keydown", this.bind(function(e) {
                if (!this.isInterfaceEnabled()) return;
                if (229 == e.keyCode) return;
                if (e.which === KEY.PAGE_UP || e.which === KEY.PAGE_DOWN) {
                    killEvent(e);
                    return;
                }
                switch (e.which) {
                  case KEY.UP:
                  case KEY.DOWN:
                    this.moveHighlight(e.which === KEY.UP ? -1 : 1);
                    killEvent(e);
                    return;

                  case KEY.ENTER:
                    this.selectHighlighted();
                    killEvent(e);
                    return;

                  case KEY.TAB:
                    this.selectHighlighted({
                        noFocus: true
                    });
                    return;

                  case KEY.ESC:
                    this.cancel(e);
                    killEvent(e);
                    return;
                }
            }));
            this.search.on("blur", this.bind(function(e) {
                if (document.activeElement === this.body.get(0)) {
                    window.setTimeout(this.bind(function() {
                        if (this.opened()) {
                            this.search.focus();
                        }
                    }), 0);
                }
            }));
            this.focusser.on("keydown", this.bind(function(e) {
                if (!this.isInterfaceEnabled()) return;
                if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC) {
                    return;
                }
                if (this.opts.openOnEnter === false && e.which === KEY.ENTER) {
                    killEvent(e);
                    return;
                }
                if (e.which == KEY.DOWN || e.which == KEY.UP || e.which == KEY.ENTER && this.opts.openOnEnter) {
                    if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) return;
                    this.open();
                    killEvent(e);
                    return;
                }
                if (e.which == KEY.DELETE || e.which == KEY.BACKSPACE) {
                    if (this.opts.allowClear) {
                        this.clear();
                    }
                    killEvent(e);
                    return;
                }
            }));
            installKeyUpChangeEvent(this.focusser);
            this.focusser.on("keyup-change input", this.bind(function(e) {
                if (this.opts.minimumResultsForSearch >= 0) {
                    e.stopPropagation();
                    if (this.opened()) return;
                    this.open();
                }
            }));
            selection.on("mousedown touchstart", "abbr", this.bind(function(e) {
                if (!this.isInterfaceEnabled()) {
                    return;
                }
                this.clear();
                killEventImmediately(e);
                this.close();
                if (this.selection) {
                    this.selection.focus();
                }
            }));
            selection.on("mousedown touchstart", this.bind(function(e) {
                reinsertElement(selection);
                if (!this.container.hasClass("select2-container-active")) {
                    this.opts.element.trigger($.Event("select2-focus"));
                }
                if (this.opened()) {
                    this.close();
                } else if (this.isInterfaceEnabled()) {
                    this.open();
                }
                killEvent(e);
            }));
            dropdown.on("mousedown touchstart", this.bind(function() {
                if (this.opts.shouldFocusInput(this)) {
                    this.search.focus();
                }
            }));
            selection.on("focus", this.bind(function(e) {
                killEvent(e);
            }));
            this.focusser.on("focus", this.bind(function() {
                if (!this.container.hasClass("select2-container-active")) {
                    this.opts.element.trigger($.Event("select2-focus"));
                }
                this.container.addClass("select2-container-active");
            })).on("blur", this.bind(function() {
                if (!this.opened()) {
                    this.container.removeClass("select2-container-active");
                    this.opts.element.trigger($.Event("select2-blur"));
                }
            }));
            this.search.on("focus", this.bind(function() {
                if (!this.container.hasClass("select2-container-active")) {
                    this.opts.element.trigger($.Event("select2-focus"));
                }
                this.container.addClass("select2-container-active");
            }));
            this.initContainerWidth();
            this.opts.element.hide();
            this.setPlaceholder();
        },
        clear: function(triggerChange) {
            var data = this.selection.data("select2-data");
            if (data) {
                var evt = $.Event("select2-clearing");
                this.opts.element.trigger(evt);
                if (evt.isDefaultPrevented()) {
                    return;
                }
                var placeholderOption = this.getPlaceholderOption();
                this.opts.element.val(placeholderOption ? placeholderOption.val() : "");
                this.selection.find(".select2-chosen").empty();
                this.selection.removeData("select2-data");
                this.setPlaceholder();
                if (triggerChange !== false) {
                    this.opts.element.trigger({
                        type: "select2-removed",
                        val: this.id(data),
                        choice: data
                    });
                    this.triggerChange({
                        removed: data
                    });
                }
            }
        },
        initSelection: function() {
            var selected;
            if (this.isPlaceholderOptionSelected()) {
                this.updateSelection(null);
                this.close();
                this.setPlaceholder();
            } else {
                var self = this;
                this.opts.initSelection.call(null, this.opts.element, function(selected) {
                    if (selected !== undefined && selected !== null) {
                        self.updateSelection(selected);
                        self.close();
                        self.setPlaceholder();
                        self.nextSearchTerm = self.opts.nextSearchTerm(selected, self.search.val());
                    }
                });
            }
        },
        isPlaceholderOptionSelected: function() {
            var placeholderOption;
            if (this.getPlaceholder() === undefined) return false;
            return (placeholderOption = this.getPlaceholderOption()) !== undefined && placeholderOption.prop("selected") || this.opts.element.val() === "" || this.opts.element.val() === undefined || this.opts.element.val() === null;
        },
        prepareOpts: function() {
            var opts = this.parent.prepareOpts.apply(this, arguments), self = this;
            if (opts.element.get(0).tagName.toLowerCase() === "select") {
                opts.initSelection = function(element, callback) {
                    var selected = element.find("option").filter(function() {
                        return this.selected && !this.disabled;
                    });
                    callback(self.optionToData(selected));
                };
            } else if ("data" in opts) {
                opts.initSelection = opts.initSelection || function(element, callback) {
                    var id = element.val();
                    var match = null;
                    opts.query({
                        matcher: function(term, text, el) {
                            var is_match = equal(id, opts.id(el));
                            if (is_match) {
                                match = el;
                            }
                            return is_match;
                        },
                        callback: !$.isFunction(callback) ? $.noop : function() {
                            callback(match);
                        }
                    });
                };
            }
            return opts;
        },
        getPlaceholder: function() {
            if (this.select) {
                if (this.getPlaceholderOption() === undefined) {
                    return undefined;
                }
            }
            return this.parent.getPlaceholder.apply(this, arguments);
        },
        setPlaceholder: function() {
            var placeholder = this.getPlaceholder();
            if (this.isPlaceholderOptionSelected() && placeholder !== undefined) {
                if (this.select && this.getPlaceholderOption() === undefined) return;
                this.selection.find(".select2-chosen").html(this.opts.escapeMarkup(placeholder));
                this.selection.addClass("select2-default");
                this.container.removeClass("select2-allowclear");
            }
        },
        postprocessResults: function(data, initial, noHighlightUpdate) {
            var selected = 0, self = this, showSearchInput = true;
            this.findHighlightableChoices().each2(function(i, elm) {
                if (equal(self.id(elm.data("select2-data")), self.opts.element.val())) {
                    selected = i;
                    return false;
                }
            });
            if (noHighlightUpdate !== false) {
                if (initial === true && selected >= 0) {
                    this.highlight(selected);
                } else {
                    this.highlight(0);
                }
            }
            if (initial === true) {
                var min = this.opts.minimumResultsForSearch;
                if (min >= 0) {
                    this.showSearch(countResults(data.results) >= min);
                }
            }
        },
        showSearch: function(showSearchInput) {
            if (this.showSearchInput === showSearchInput) return;
            this.showSearchInput = showSearchInput;
            this.dropdown.find(".select2-search").toggleClass("select2-search-hidden", !showSearchInput);
            this.dropdown.find(".select2-search").toggleClass("select2-offscreen", !showSearchInput);
            $(this.dropdown, this.container).toggleClass("select2-with-searchbox", showSearchInput);
        },
        onSelect: function(data, options) {
            if (!this.triggerSelect(data)) {
                return;
            }
            var old = this.opts.element.val(), oldData = this.data();
            this.opts.element.val(this.id(data));
            this.updateSelection(data);
            this.opts.element.trigger({
                type: "select2-selected",
                val: this.id(data),
                choice: data
            });
            this.nextSearchTerm = this.opts.nextSearchTerm(data, this.search.val());
            this.close();
            if ((!options || !options.noFocus) && this.opts.shouldFocusInput(this)) {
                this.focusser.focus();
            }
            if (!equal(old, this.id(data))) {
                this.triggerChange({
                    added: data,
                    removed: oldData
                });
            }
        },
        updateSelection: function(data) {
            var container = this.selection.find(".select2-chosen"), formatted, cssClass;
            this.selection.data("select2-data", data);
            container.empty();
            if (data !== null) {
                formatted = this.opts.formatSelection(data, container, this.opts.escapeMarkup);
                container.prop("title", $(data.element).prop("title") || data.text);
            }
            if (formatted !== undefined) {
                container.append(formatted);
            }
            cssClass = this.opts.formatSelectionCssClass(data, container);
            if (cssClass !== undefined) {
                container.addClass(cssClass);
            }
            this.selection.removeClass("select2-default");
            if (this.opts.allowClear && this.getPlaceholder() !== undefined) {
                this.container.addClass("select2-allowclear");
            }
        },
        val: function() {
            var val, triggerChange = false, data = null, self = this, oldData = this.data();
            if (arguments.length === 0) {
                return this.opts.element.val();
            }
            val = arguments[0];
            if (arguments.length > 1) {
                triggerChange = arguments[1];
            }
            if (this.select) {
                this.select.val(val).find("option").filter(function() {
                    return this.selected;
                }).each2(function(i, elm) {
                    data = self.optionToData(elm);
                    return false;
                });
                this.updateSelection(data);
                this.setPlaceholder();
                if (triggerChange) {
                    this.triggerChange({
                        added: data,
                        removed: oldData
                    });
                }
            } else {
                if (!val && val !== 0) {
                    this.clear(triggerChange);
                    return;
                }
                if (this.opts.initSelection === undefined) {
                    throw new Error("cannot call val() if initSelection() is not defined");
                }
                this.opts.element.val(val);
                this.opts.initSelection(this.opts.element, function(data) {
                    self.opts.element.val(!data ? "" : self.id(data));
                    self.updateSelection(data);
                    self.setPlaceholder();
                    if (triggerChange) {
                        self.triggerChange({
                            added: data,
                            removed: oldData
                        });
                    }
                });
            }
        },
        clearSearch: function() {
            this.search.val("");
            this.focusser.val("");
        },
        data: function(value) {
            var data, triggerChange = false;
            if (arguments.length === 0) {
                data = this.selection.data("select2-data");
                if (data == undefined) data = null;
                return data;
            } else {
                if (arguments.length > 1) {
                    triggerChange = arguments[1];
                }
                if (!value) {
                    this.clear(triggerChange);
                } else {
                    data = this.data();
                    this.opts.element.val(!value ? "" : this.id(value));
                    this.updateSelection(value);
                    if (triggerChange) {
                        this.triggerChange({
                            added: value,
                            removed: data
                        });
                    }
                }
            }
        }
    });
    MultiSelect2 = clazz(AbstractSelect2, {
        createContainer: function() {
            var container = $(document.createElement("div")).attr({
                class: "select2-container select2-container-multi"
            }).html([ "<ul class='select2-choices'>", "  <li class='select2-search-field'>", "    <label for='' class='select2-offscreen'></label>", "    <input type='text' autocomplete='off' autocorrect='off' autocapitalize='off' spellcheck='false' class='select2-input'>", "  </li>", "</ul>", "<div class='select2-drop select2-drop-multi select2-display-none'>", "   <ul class='select2-results'>", "   </ul>", "</div>" ].join(""));
            return container;
        },
        prepareOpts: function() {
            var opts = this.parent.prepareOpts.apply(this, arguments), self = this;
            if (opts.element.get(0).tagName.toLowerCase() === "select") {
                opts.initSelection = function(element, callback) {
                    var data = [];
                    element.find("option").filter(function() {
                        return this.selected && !this.disabled;
                    }).each2(function(i, elm) {
                        data.push(self.optionToData(elm));
                    });
                    callback(data);
                };
            } else if ("data" in opts) {
                opts.initSelection = opts.initSelection || function(element, callback) {
                    var ids = splitVal(element.val(), opts.separator, opts.transformVal);
                    var matches = [];
                    opts.query({
                        matcher: function(term, text, el) {
                            var is_match = $.grep(ids, function(id) {
                                return equal(id, opts.id(el));
                            }).length;
                            if (is_match) {
                                matches.push(el);
                            }
                            return is_match;
                        },
                        callback: !$.isFunction(callback) ? $.noop : function() {
                            var ordered = [];
                            for (var i = 0; i < ids.length; i++) {
                                var id = ids[i];
                                for (var j = 0; j < matches.length; j++) {
                                    var match = matches[j];
                                    if (equal(id, opts.id(match))) {
                                        ordered.push(match);
                                        matches.splice(j, 1);
                                        break;
                                    }
                                }
                            }
                            callback(ordered);
                        }
                    });
                };
            }
            return opts;
        },
        selectChoice: function(choice) {
            var selected = this.container.find(".select2-search-choice-focus");
            if (selected.length && choice && choice[0] == selected[0]) {} else {
                if (selected.length) {
                    this.opts.element.trigger("choice-deselected", selected);
                }
                selected.removeClass("select2-search-choice-focus");
                if (choice && choice.length) {
                    this.close();
                    choice.addClass("select2-search-choice-focus");
                    this.opts.element.trigger("choice-selected", choice);
                }
            }
        },
        destroy: function() {
            $("label[for='" + this.search.attr("id") + "']").attr("for", this.opts.element.attr("id"));
            this.parent.destroy.apply(this, arguments);
            cleanupJQueryElements.call(this, "searchContainer", "selection");
        },
        initContainer: function() {
            var selector = ".select2-choices", selection;
            this.searchContainer = this.container.find(".select2-search-field");
            this.selection = selection = this.container.find(selector);
            var _this = this;
            this.selection.on("click", ".select2-container:not(.select2-container-disabled) .select2-search-choice:not(.select2-locked)", function(e) {
                _this.search[0].focus();
                _this.selectChoice($(this));
            });
            this.search.attr("id", "s2id_autogen" + nextUid());
            this.search.prev().text($("label[for='" + this.opts.element.attr("id") + "']").text()).attr("for", this.search.attr("id"));
            this.opts.element.focus(this.bind(function() {
                this.focus();
            }));
            this.search.on("input paste", this.bind(function() {
                if (this.search.attr("placeholder") && this.search.val().length == 0) return;
                if (!this.isInterfaceEnabled()) return;
                if (!this.opened()) {
                    this.open();
                }
            }));
            this.search.attr("tabindex", this.elementTabIndex);
            this.keydowns = 0;
            this.search.on("keydown", this.bind(function(e) {
                if (!this.isInterfaceEnabled()) return;
                ++this.keydowns;
                var selected = selection.find(".select2-search-choice-focus");
                var prev = selected.prev(".select2-search-choice:not(.select2-locked)");
                var next = selected.next(".select2-search-choice:not(.select2-locked)");
                var pos = getCursorInfo(this.search);
                if (selected.length && (e.which == KEY.LEFT || e.which == KEY.RIGHT || e.which == KEY.BACKSPACE || e.which == KEY.DELETE || e.which == KEY.ENTER)) {
                    var selectedChoice = selected;
                    if (e.which == KEY.LEFT && prev.length) {
                        selectedChoice = prev;
                    } else if (e.which == KEY.RIGHT) {
                        selectedChoice = next.length ? next : null;
                    } else if (e.which === KEY.BACKSPACE) {
                        if (this.unselect(selected.first())) {
                            this.search.width(10);
                            selectedChoice = prev.length ? prev : next;
                        }
                    } else if (e.which == KEY.DELETE) {
                        if (this.unselect(selected.first())) {
                            this.search.width(10);
                            selectedChoice = next.length ? next : null;
                        }
                    } else if (e.which == KEY.ENTER) {
                        selectedChoice = null;
                    }
                    this.selectChoice(selectedChoice);
                    killEvent(e);
                    if (!selectedChoice || !selectedChoice.length) {
                        this.open();
                    }
                    return;
                } else if ((e.which === KEY.BACKSPACE && this.keydowns == 1 || e.which == KEY.LEFT) && (pos.offset == 0 && !pos.length)) {
                    this.selectChoice(selection.find(".select2-search-choice:not(.select2-locked)").last());
                    killEvent(e);
                    return;
                } else {
                    this.selectChoice(null);
                }
                if (this.opened()) {
                    switch (e.which) {
                      case KEY.UP:
                      case KEY.DOWN:
                        this.moveHighlight(e.which === KEY.UP ? -1 : 1);
                        killEvent(e);
                        return;

                      case KEY.ENTER:
                        this.selectHighlighted();
                        killEvent(e);
                        return;

                      case KEY.TAB:
                        this.selectHighlighted({
                            noFocus: true
                        });
                        this.close();
                        return;

                      case KEY.ESC:
                        this.cancel(e);
                        killEvent(e);
                        return;
                    }
                }
                if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.BACKSPACE || e.which === KEY.ESC) {
                    return;
                }
                if (e.which === KEY.ENTER) {
                    if (this.opts.openOnEnter === false) {
                        return;
                    } else if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {
                        return;
                    }
                }
                this.open();
                if (e.which === KEY.PAGE_UP || e.which === KEY.PAGE_DOWN) {
                    killEvent(e);
                }
                if (e.which === KEY.ENTER) {
                    killEvent(e);
                }
            }));
            this.search.on("keyup", this.bind(function(e) {
                this.keydowns = 0;
                this.resizeSearch();
            }));
            this.search.on("blur", this.bind(function(e) {
                this.container.removeClass("select2-container-active");
                this.search.removeClass("select2-focused");
                this.selectChoice(null);
                if (!this.opened()) this.clearSearch();
                e.stopImmediatePropagation();
                this.opts.element.trigger($.Event("select2-blur"));
            }));
            this.container.on("click", selector, this.bind(function(e) {
                if (!this.isInterfaceEnabled()) return;
                if ($(e.target).closest(".select2-search-choice").length > 0) {
                    return;
                }
                this.selectChoice(null);
                this.clearPlaceholder();
                if (!this.container.hasClass("select2-container-active")) {
                    this.opts.element.trigger($.Event("select2-focus"));
                }
                this.open();
                this.focusSearch();
                e.preventDefault();
            }));
            this.container.on("focus", selector, this.bind(function() {
                if (!this.isInterfaceEnabled()) return;
                if (!this.container.hasClass("select2-container-active")) {
                    this.opts.element.trigger($.Event("select2-focus"));
                }
                this.container.addClass("select2-container-active");
                this.dropdown.addClass("select2-drop-active");
                this.clearPlaceholder();
            }));
            this.initContainerWidth();
            this.opts.element.hide();
            this.clearSearch();
        },
        enableInterface: function() {
            if (this.parent.enableInterface.apply(this, arguments)) {
                this.search.prop("disabled", !this.isInterfaceEnabled());
            }
        },
        initSelection: function() {
            var data;
            if (this.opts.element.val() === "" && this.opts.element.text() === "") {
                this.updateSelection([]);
                this.close();
                this.clearSearch();
            }
            if (this.select || this.opts.element.val() !== "") {
                var self = this;
                this.opts.initSelection.call(null, this.opts.element, function(data) {
                    if (data !== undefined && data !== null) {
                        self.updateSelection(data);
                        self.close();
                        self.clearSearch();
                    }
                });
            }
        },
        clearSearch: function() {
            var placeholder = this.getPlaceholder(), maxWidth = this.getMaxSearchWidth();
            if (placeholder !== undefined && this.getVal().length === 0 && this.search.hasClass("select2-focused") === false) {
                this.search.val(placeholder).addClass("select2-default");
                this.search.width(maxWidth > 0 ? maxWidth : this.container.css("width"));
            } else {
                this.search.val("").width(10);
            }
        },
        clearPlaceholder: function() {
            if (this.search.hasClass("select2-default")) {
                this.search.val("").removeClass("select2-default");
            }
        },
        opening: function() {
            this.clearPlaceholder();
            this.resizeSearch();
            this.parent.opening.apply(this, arguments);
            this.focusSearch();
            if (this.search.val() === "") {
                if (this.nextSearchTerm != undefined) {
                    this.search.val(this.nextSearchTerm);
                    this.search.select();
                }
            }
            this.updateResults(true);
            if (this.opts.shouldFocusInput(this)) {
                this.search.focus();
            }
            this.opts.element.trigger($.Event("select2-open"));
        },
        close: function() {
            if (!this.opened()) return;
            this.parent.close.apply(this, arguments);
        },
        focus: function() {
            this.close();
            this.search.focus();
        },
        isFocused: function() {
            return this.search.hasClass("select2-focused");
        },
        updateSelection: function(data) {
            var ids = [], filtered = [], self = this;
            $(data).each(function() {
                if (indexOf(self.id(this), ids) < 0) {
                    ids.push(self.id(this));
                    filtered.push(this);
                }
            });
            data = filtered;
            this.selection.find(".select2-search-choice").remove();
            $(data).each(function() {
                self.addSelectedChoice(this);
            });
            self.postprocessResults();
        },
        tokenize: function() {
            var input = this.search.val();
            input = this.opts.tokenizer.call(this, input, this.data(), this.bind(this.onSelect), this.opts);
            if (input != null && input != undefined) {
                this.search.val(input);
                if (input.length > 0) {
                    this.open();
                }
            }
        },
        onSelect: function(data, options) {
            if (!this.triggerSelect(data) || data.text === "") {
                return;
            }
            this.addSelectedChoice(data);
            this.opts.element.trigger({
                type: "selected",
                val: this.id(data),
                choice: data
            });
            this.nextSearchTerm = this.opts.nextSearchTerm(data, this.search.val());
            this.clearSearch();
            this.updateResults();
            if (this.select || !this.opts.closeOnSelect) this.postprocessResults(data, false, this.opts.closeOnSelect === true);
            if (this.opts.closeOnSelect) {
                this.close();
                this.search.width(10);
            } else {
                if (this.countSelectableResults() > 0) {
                    this.search.width(10);
                    this.resizeSearch();
                    if (this.getMaximumSelectionSize() > 0 && this.val().length >= this.getMaximumSelectionSize()) {
                        this.updateResults(true);
                    } else {
                        if (this.nextSearchTerm != undefined) {
                            this.search.val(this.nextSearchTerm);
                            this.updateResults();
                            this.search.select();
                        }
                    }
                    this.positionDropdown();
                } else {
                    this.close();
                    this.search.width(10);
                }
            }
            this.triggerChange({
                added: data
            });
            if (!options || !options.noFocus) this.focusSearch();
        },
        cancel: function() {
            this.close();
            this.focusSearch();
        },
        addSelectedChoice: function(data) {
            var enableChoice = !data.locked, enabledItem = $("<li class='select2-search-choice'>" + "    <div></div>" + "    <a href='#' class='select2-search-choice-close' tabindex='-1'></a>" + "</li>"), disabledItem = $("<li class='select2-search-choice select2-locked'>" + "<div></div>" + "</li>");
            var choice = enableChoice ? enabledItem : disabledItem, id = this.id(data), val = this.getVal(), formatted, cssClass;
            formatted = this.opts.formatSelection(data, choice.find("div"), this.opts.escapeMarkup);
            if (formatted != undefined) {
                choice.find("div").replaceWith($("<div></div>").html(formatted));
            }
            if (this.opts.inlineTags) {
                choice.addClass("select2-search-choice-inlined");
            }
            cssClass = this.opts.formatSelectionCssClass(data, choice.find("div"));
            if (cssClass != undefined) {
                choice.addClass(cssClass);
            }
            if (enableChoice) {
                choice.find(".select2-search-choice-close").on("mousedown", killEvent).on("click dblclick", this.bind(function(e) {
                    if (!this.isInterfaceEnabled()) return;
                    this.unselect($(e.target));
                    this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus");
                    killEvent(e);
                    this.close();
                    this.focusSearch();
                })).on("focus", this.bind(function() {
                    if (!this.isInterfaceEnabled()) return;
                    this.container.addClass("select2-container-active");
                    this.dropdown.addClass("select2-drop-active");
                }));
            }
            choice.data("select2-data", data);
            choice.insertBefore(this.searchContainer);
            val.push(id);
            this.setVal(val);
        },
        unselect: function(selected) {
            var val = this.getVal(), data, index;
            selected = selected.closest(".select2-search-choice");
            if (selected.length === 0) {
                throw "Invalid argument: " + selected + ". Must be .select2-search-choice";
            }
            data = selected.data("select2-data");
            if (!data) {
                return;
            }
            var evt = $.Event("select2-removing");
            evt.val = this.id(data);
            evt.choice = data;
            this.opts.element.trigger(evt);
            if (evt.isDefaultPrevented()) {
                return false;
            }
            while ((index = indexOf(this.id(data), val)) >= 0) {
                val.splice(index, 1);
                this.setVal(val);
                if (this.select) this.postprocessResults();
            }
            selected.remove();
            this.opts.element.trigger({
                type: "select2-removed",
                val: this.id(data),
                choice: data
            });
            this.triggerChange({
                removed: data
            });
            return true;
        },
        postprocessResults: function(data, initial, noHighlightUpdate) {
            var val = this.getVal(), choices = this.results.find(".select2-result"), compound = this.results.find(".select2-result-with-children"), self = this;
            choices.each2(function(i, choice) {
                var id = self.id(choice.data("select2-data"));
                if (indexOf(id, val) >= 0) {
                    if (choice.is("optgroup")) {
                        choice.addClass("select2-selected");
                        choice.find(".select2-result-selectable").addClass("select2-selected");
                    } else {
                        if (choice.find(".select2-result-selectable").length > 0) {
                            choice.addClass("select2-disabled");
                        } else {
                            choice.addClass("select2-selected");
                        }
                    }
                }
            });
            compound.each2(function(i, choice) {
                if (choice.find(".select2-result-selectable:not(.select2-selected)").length === 0) {
                    if (!choice.is(".select2-result-selectable") || choice.is(".select2-disabled")) {
                        choice.addClass("select2-selected");
                    }
                }
            });
            if (this.highlight() == -1 && noHighlightUpdate !== false && this.opts.closeOnSelect === true) {
                self.highlight(0);
            }
            if (!this.opts.createSearchChoice && !choices.filter(".select2-result:not(.select2-selected)").length > 0) {
                if (!data || data && !data.more && this.results.find(".select2-no-results").length === 0) {
                    if (checkFormatter(self.opts.formatNoMatches, "formatNoMatches")) {
                        this.results.append("<li class='select2-no-results'>" + evaluate(self.opts.formatNoMatches, self.opts.element, self.search.val()) + "</li>");
                    }
                }
            }
        },
        getMaxSearchWidth: function() {
            return this.selection.width() - getSideBorderPadding(this.search);
        },
        resizeSearch: function() {
            var minimumWidth, left, maxWidth, containerLeft, searchWidth, sideBorderPadding = getSideBorderPadding(this.search);
            minimumWidth = measureTextWidth(this.search) + 10;
            left = this.search.offset().left;
            maxWidth = this.selection.width();
            containerLeft = this.selection.offset().left;
            searchWidth = maxWidth - (left - containerLeft) - sideBorderPadding;
            if (searchWidth < minimumWidth) {
                searchWidth = maxWidth - sideBorderPadding;
            }
            if (searchWidth < 40) {
                searchWidth = maxWidth - sideBorderPadding;
            }
            if (searchWidth <= 0) {
                searchWidth = minimumWidth;
            }
            this.search.width(Math.floor(searchWidth));
        },
        getVal: function() {
            var val;
            if (this.select) {
                val = this.select.val();
                return val === null ? [] : val;
            } else {
                val = this.opts.element.val();
                return splitVal(val, this.opts.separator, this.opts.transformVal);
            }
        },
        setVal: function(val) {
            var unique;
            if (this.select) {
                this.select.val(val);
            } else {
                unique = [];
                $(val).each(function() {
                    if (indexOf(this, unique) < 0) unique.push(this);
                });
                this.opts.element.val(unique.length === 0 ? "" : unique.join(this.opts.separator));
            }
        },
        buildChangeDetails: function(old, current) {
            var current = current.slice(0), old = old.slice(0);
            for (var i = 0; i < current.length; i++) {
                for (var j = 0; j < old.length; j++) {
                    if (equal(this.opts.id(current[i]), this.opts.id(old[j]))) {
                        current.splice(i, 1);
                        if (i > 0) {
                            i--;
                        }
                        old.splice(j, 1);
                        j--;
                    }
                }
            }
            return {
                added: current,
                removed: old
            };
        },
        val: function(val, triggerChange) {
            var oldData, self = this;
            if (arguments.length === 0) {
                return this.getVal();
            }
            oldData = this.data();
            if (!oldData.length) oldData = [];
            if (!val && val !== 0) {
                this.opts.element.val("");
                this.updateSelection([]);
                this.clearSearch();
                if (triggerChange) {
                    this.triggerChange({
                        added: this.data(),
                        removed: oldData
                    });
                }
                return;
            }
            this.setVal(val);
            if (this.select) {
                this.opts.initSelection(this.select, this.bind(this.updateSelection));
                if (triggerChange) {
                    this.triggerChange(this.buildChangeDetails(oldData, this.data()));
                }
            } else {
                if (this.opts.initSelection === undefined) {
                    throw new Error("val() cannot be called if initSelection() is not defined");
                }
                this.opts.initSelection(this.opts.element, function(data) {
                    var ids = $.map(data, self.id);
                    self.setVal(ids);
                    self.updateSelection(data);
                    self.clearSearch();
                    if (triggerChange) {
                        self.triggerChange(self.buildChangeDetails(oldData, self.data()));
                    }
                });
            }
            this.clearSearch();
        },
        onSortStart: function() {
            if (this.select) {
                throw new Error("Sorting of elements is not supported when attached to <select>. Attach to <input type='hidden'/> instead.");
            }
            this.search.width(0);
            this.searchContainer.hide();
        },
        onSortEnd: function() {
            var val = [], self = this;
            this.searchContainer.show();
            this.searchContainer.appendTo(this.searchContainer.parent());
            this.resizeSearch();
            this.selection.find(".select2-search-choice").each(function() {
                val.push(self.opts.id($(this).data("select2-data")));
            });
            this.setVal(val);
            this.triggerChange();
        },
        data: function(values, triggerChange) {
            var self = this, ids, old;
            if (arguments.length === 0) {
                return this.selection.children(".select2-search-choice").map(function() {
                    return $(this).data("select2-data");
                }).get();
            } else {
                old = this.data();
                if (!values) {
                    values = [];
                }
                ids = $.map(values, function(e) {
                    return self.opts.id(e);
                });
                this.setVal(ids);
                this.updateSelection(values);
                this.clearSearch();
                if (triggerChange) {
                    this.triggerChange(this.buildChangeDetails(old, this.data()));
                }
            }
        }
    });
    $.fn.select2 = function() {
        var args = Array.prototype.slice.call(arguments, 0), opts, select2, method, value, multiple, allowedMethods = [ "val", "destroy", "opened", "open", "close", "focus", "isFocused", "container", "dropdown", "onSortStart", "onSortEnd", "enable", "disable", "readonly", "positionDropdown", "data", "search" ], valueMethods = [ "opened", "isFocused", "container", "dropdown" ], propertyMethods = [ "val", "data" ], methodsMap = {
            search: "externalSearch"
        };
        this.each(function() {
            if (args.length === 0 || typeof args[0] === "object") {
                opts = args.length === 0 ? {} : $.extend({}, args[0]);
                opts.element = $(this);
                if (opts.element.get(0).tagName.toLowerCase() === "select") {
                    multiple = opts.element.prop("multiple");
                } else {
                    multiple = opts.multiple || false;
                    if ("tags" in opts) {
                        opts.multiple = multiple = true;
                    }
                }
                select2 = multiple ? new window.Select2["class"].multi() : new window.Select2["class"].single();
                select2.init(opts);
            } else if (typeof args[0] === "string") {
                if (indexOf(args[0], allowedMethods) < 0) {
                    throw "Unknown method: " + args[0];
                }
                value = undefined;
                select2 = $(this).data("select2");
                if (select2 === undefined) return;
                method = args[0];
                if (method === "container") {
                    value = select2.container;
                } else if (method === "dropdown") {
                    value = select2.dropdown;
                } else {
                    if (methodsMap[method]) method = methodsMap[method];
                    value = select2[method].apply(select2, args.slice(1));
                }
                if (indexOf(args[0], valueMethods) >= 0 || indexOf(args[0], propertyMethods) >= 0 && args.length == 1) {
                    return false;
                }
            } else {
                throw "Invalid arguments to select2 plugin: " + args;
            }
        });
        return value === undefined ? this : value;
    };
    $.fn.select2.defaults = {
        width: "copy",
        loadMorePadding: 0,
        closeOnSelect: true,
        openOnEnter: true,
        containerCss: {},
        dropdownCss: {},
        containerCssClass: "",
        dropdownCssClass: "",
        formatResult: function(result, container, query, escapeMarkup) {
            var markup = [];
            markMatch(this.text(result), query.term, markup, escapeMarkup);
            return markup.join("");
        },
        transformVal: function(val) {
            return $.trim(val);
        },
        formatSelection: function(data, container, escapeMarkup) {
            return data ? escapeMarkup(this.text(data)) : undefined;
        },
        sortResults: function(results, container, query) {
            return results;
        },
        formatResultCssClass: function(data) {
            return data.css;
        },
        formatSelectionCssClass: function(data, container) {
            return undefined;
        },
        minimumResultsForSearch: 0,
        minimumInputLength: 0,
        maximumInputLength: null,
        maximumSelectionSize: 0,
        id: function(e) {
            return e == undefined ? null : e.id;
        },
        text: function(e) {
            if (e && this.data && this.data.text) {
                if ($.isFunction(this.data.text)) {
                    return this.data.text(e);
                } else {
                    return e[this.data.text];
                }
            } else {
                return e.text;
            }
        },
        matcher: function(term, text) {
            return stripDiacritics("" + text).toUpperCase().indexOf(stripDiacritics("" + term).toUpperCase()) >= 0;
        },
        separator: ",",
        tokenSeparators: [],
        tokenizer: defaultTokenizer,
        escapeMarkup: defaultEscapeMarkup,
        blurOnChange: false,
        selectOnBlur: false,
        adaptContainerCssClass: function(c) {
            return c;
        },
        adaptDropdownCssClass: function(c) {
            return null;
        },
        nextSearchTerm: function(selectedObject, currentSearchTerm) {
            return undefined;
        },
        searchInputPlaceholder: "",
        createSearchChoicePosition: "top",
        shouldFocusInput: function(instance) {
            var supportsTouchEvents = "ontouchstart" in window || navigator.msMaxTouchPoints > 0;
            if (!supportsTouchEvents) {
                return true;
            }
            if (instance.opts.minimumResultsForSearch < 0) {
                return false;
            }
            return true;
        }
    };
    $.fn.select2.locales = [];
    $.fn.select2.locales["en"] = {
        formatMatches: function(matches) {
            if (matches === 1) {
                return "One result is available, press enter to select it.";
            }
            return matches + " results are available, use up and down arrow keys to navigate.";
        },
        formatNoMatches: function() {
            return "No matches found";
        },
        formatAjaxError: function(jqXHR, textStatus, errorThrown) {
            return "Loading failed";
        },
        formatInputTooShort: function(input, min) {
            var n = min - input.length;
            return "Please enter " + n + " or more character" + (n == 1 ? "" : "s");
        },
        formatInputTooLong: function(input, max) {
            var n = input.length - max;
            return "Please delete " + n + " character" + (n == 1 ? "" : "s");
        },
        formatSelectionTooBig: function(limit) {
            return "You can only select " + limit + " item" + (limit == 1 ? "" : "s");
        },
        formatLoadMore: function(pageNumber) {
            return "Loading more results…";
        },
        formatSearching: function() {
            return "Searching…";
        }
    };
    $.extend($.fn.select2.defaults, $.fn.select2.locales["en"]);
    $.fn.select2.ajaxDefaults = {
        transport: $.ajax,
        params: {
            type: "GET",
            cache: false,
            dataType: "json"
        }
    };
    window.Select2 = {
        query: {
            ajax: ajax,
            local: local,
            tags: tags
        },
        util: {
            debounce: debounce,
            markMatch: markMatch,
            escapeMarkup: defaultEscapeMarkup,
            stripDiacritics: stripDiacritics
        },
        class: {
            abstract: AbstractSelect2,
            single: SingleSelect2,
            multi: MultiSelect2
        }
    };
})(jQuery);

var EndlessScroll;

EndlessScroll = function() {
    var defaults;
    EndlessScroll.name = "EndlessScroll";
    defaults = {
        bottomPixels: 50,
        fireOnce: true,
        fireDelay: 150,
        loader: "Loading...",
        content: "",
        insertAfter: "div:last",
        intervalFrequency: 250,
        resetCounter: function() {
            return false;
        },
        callback: function() {
            return true;
        },
        ceaseFire: function() {
            return false;
        }
    };
    function EndlessScroll(scope, options) {
        var _this = this;
        this.options = $.extend({}, defaults, options);
        this.firing = true;
        this.fired = false;
        this.fireSequence = 0;
        this.didScroll = false;
        this.isScrollable = true;
        this.target = scope;
        this.targetId = "";
        this.content = "";
        this.innerWrap = $(".endless_scroll_inner_wrap", this.target);
        if (this.options.data) {
            this.options.content = this.options.data;
        }
        $(scope).scroll(function() {
            _this.didScroll = true;
            _this.target = scope;
            return _this.targetId = $(_this.target).attr("id");
        });
    }
    EndlessScroll.prototype.run = function() {
        var _this = this;
        return setInterval(function() {
            if (_this.shouldTryFiring()) {
                _this.didScroll = false;
                if (_this.ceaseFireWhenNecessary()) {
                    return;
                }
                if (_this.shouldBeFiring()) {
                    _this.resetFireSequenceWhenNecessary();
                    _this.acknowledgeFiring();
                    _this.insertLoader();
                    if (_this.hasContent()) {
                        _this.showContent();
                        _this.fireCallback();
                        _this.delayFireingWhenNecessary();
                    }
                    return _this.removeLoader();
                }
            }
        }, this.options.intervalFrequency);
    };
    EndlessScroll.prototype.shouldTryFiring = function() {
        return this.didScroll && this.firing === true;
    };
    EndlessScroll.prototype.ceaseFireWhenNecessary = function() {
        if (this.options.ceaseFire.apply(this.target, [ this.fireSequence ])) {
            this.firing = false;
            return true;
        } else {
            return false;
        }
    };
    EndlessScroll.prototype.wrapContainer = function() {
        if (this.innerWrap.length === 0) {
            return this.innerWrap = $(this.target).wrapInner('<div class="endless_scroll_inner_wrap" />').find(".endless_scroll_inner_wrap");
        }
    };
    EndlessScroll.prototype.isScrollableOrNot = function() {
        if (this.target === document || this.target === window) {
            return this.isScrollable = $(document).height() - $(window).height() <= $(window).scrollTop() + this.options.bottomPixels;
        } else {
            this.wrapContainer();
            return this.isScrollable = this.innerWrap.length > 0 && this.innerWrap.height() - $(this.target).height() <= $(this.target).scrollTop() + this.options.bottomPixels;
        }
    };
    EndlessScroll.prototype.shouldBeFiring = function() {
        this.isScrollableOrNot();
        return this.isScrollable && (this.options.fireOnce === false || this.options.fireOnce === true && this.fired !== true);
    };
    EndlessScroll.prototype.resetFireSequenceWhenNecessary = function() {
        if (this.options.resetCounter.apply(this.target) === true) {
            return this.fireSequence = 0;
        }
    };
    EndlessScroll.prototype.acknowledgeFiring = function() {
        this.fired = true;
        return this.fireSequence++;
    };
    EndlessScroll.prototype.insertLoader = function() {
        return $(this.options.insertAfter).after('<div class="endless_scroll_loader_' + this.targetId + ' endless_scroll_loader">' + this.options.loader + "</div>");
    };
    EndlessScroll.prototype.removeLoader = function() {
        return $(".endless_scroll_loader_" + this.targetId).fadeOut(function() {
            return $(this).remove();
        });
    };
    EndlessScroll.prototype.hasContent = function() {
        if (typeof this.options.content === "function") {
            this.content = this.options.content.apply(this.target, [ this.fireSequence ]);
        } else {
            this.content = this.options.content;
        }
        return this.content !== false;
    };
    EndlessScroll.prototype.showContent = function() {
        $(this.options.insertAfter).after('<div id="endless_scroll_content">' + this.content + "</div>");
        return $("#endless_scroll_content").hide().fadeIn(250, function() {
            return $(this).removeAttr("id");
        });
    };
    EndlessScroll.prototype.fireCallback = function() {
        return this.options.callback.apply(this.target, [ this.fireSequence ]);
    };
    EndlessScroll.prototype.delayFireingWhenNecessary = function() {
        var _this = this;
        if (this.options.fireDelay > 0) {
            $("body").after('<div id="endless_scroll_marker"></div>');
            return $("#endless_scroll_marker").fadeTo(this.options.fireDelay, 1, function() {
                $("#endless_scroll_marker").remove();
                return _this.fired = false;
            });
        } else {
            return this.fired = false;
        }
    };
    return EndlessScroll;
}();

(function($) {
    return $.fn.endlessScroll = function(options) {
        return new EndlessScroll(this, options).run();
    };
})(jQuery);

(function($) {
    var singleDs = [];
    var dirty = "dirty";
    var clean = "clean";
    var dataInitialValue = "dirtyInitialValue";
    var dataIsDirty = "isDirty";
    var getSingleton = function(id) {
        var result;
        singleDs.forEach(function(e) {
            if (e.id === id) {
                result = e;
            }
        });
        return result;
    };
    const destroy = function(d) {
        singleDs = singleDs.filter(function(e) {
            return e !== d;
        });
        d.isDirty = false;
    };
    var setSubmitEvents = function(d) {
        d.form.on("submit", function() {
            d.submitting = true;
        });
        if (d.options.preventLeaving) {
            $(window).on("beforeunload", function(event) {
                if (d.isDirty && !d.submitting) {
                    event.preventDefault();
                    return d.options.leavingMessage;
                }
            });
        }
    };
    var setNamespacedEvents = function(d) {
        d.form.find("input, select, textarea").on("change.dirty click.dirty keyup.dirty keydown.dirty blur.dirty", function(e) {
            d.checkValues(e);
        });
        d.form.on("dirty", function() {
            d.options.onDirty();
        });
        d.form.on("clean", function() {
            d.options.onClean();
        });
    };
    var clearNamespacedEvents = function(d) {
        d.form.find("input, select, textarea").off("change.dirty click.dirty keyup.dirty keydown.dirty blur.dirty");
        d.form.off("dirty");
        d.form.off("clean");
    };
    var Dirty = function(form, options) {
        this.form = form;
        this.isDirty = false;
        this.options = options;
        this.history = [ clean, clean ];
        this.id = $(form).attr("id");
        singleDs.push(this);
    };
    Dirty.prototype = {
        init: function() {
            this.saveInitialValues();
            this.setEvents();
        },
        statuses: {
            dirty: dirty,
            clean: clean,
            dataInitialValue: dataInitialValue,
            dataIsDirty: dataIsDirty
        },
        isRadioOrCheckbox: function(el) {
            return $(el).is(":radio, :checkbox");
        },
        isFileInput: function(el) {
            return $(el).is(":file");
        },
        saveInitialValues: function() {
            var d = this;
            this.form.find("input, select, textarea").each(function(_, e) {
                var isRadioOrCheckbox = d.isRadioOrCheckbox(e);
                var isFile = d.isFileInput(e);
                if (isRadioOrCheckbox) {
                    var isChecked = $(e).is(":checked") ? "checked" : "unchecked";
                    $(e).data(dataInitialValue, isChecked);
                } else if (isFile) {
                    $(e).data(dataInitialValue, JSON.stringify(e.files));
                } else {
                    $(e).data(dataInitialValue, $(e).val() || "");
                }
            });
        },
        refreshEvents: function() {
            var d = this;
            clearNamespacedEvents(d);
            setNamespacedEvents(d);
        },
        showDirtyFields: function() {
            var d = this;
            return d.form.find("input, select, textarea").filter(function(_, e) {
                return $(e).data(dataIsDirty);
            });
        },
        setEvents: function() {
            var d = this;
            setSubmitEvents(d);
            setNamespacedEvents(d);
        },
        isFieldDirty: function($field) {
            var initialValue = $field.data(dataInitialValue);
            if (initialValue == null) {
                initialValue = "";
            }
            var currentValue = $field.val();
            if (currentValue == null) {
                currentValue = "";
            }
            var boolRegex = /^(true|false)$/i;
            var isBoolValue = boolRegex.test(initialValue) && boolRegex.test(currentValue);
            if (isBoolValue) {
                var regex = new RegExp("^" + initialValue + "$", "i");
                return !regex.test(currentValue);
            }
            return currentValue !== initialValue;
        },
        isFileInputDirty: function($field) {
            var initialValue = $field.data(dataInitialValue);
            var plainField = $field[0];
            var currentValue = JSON.stringify(plainField.files);
            return currentValue !== initialValue;
        },
        isCheckboxDirty: function($field) {
            var initialValue = $field.data(dataInitialValue);
            var currentValue = $field.is(":checked") ? "checked" : "unchecked";
            return initialValue !== currentValue;
        },
        checkValues: function(e) {
            var d = this;
            var formIsDirty = false;
            this.form.find("input, select, textarea").each(function(_, el) {
                var isRadioOrCheckbox = d.isRadioOrCheckbox(el);
                var isFile = d.isFileInput(el);
                var $el = $(el);
                var thisIsDirty;
                if (isRadioOrCheckbox) {
                    thisIsDirty = d.isCheckboxDirty($el);
                } else if (isFile) {
                    thisIsDirty = d.isFileInputDirty($el);
                } else {
                    thisIsDirty = d.isFieldDirty($el);
                }
                $el.data(dataIsDirty, thisIsDirty);
                formIsDirty |= thisIsDirty;
            });
            if (formIsDirty) {
                d.setDirty();
            } else {
                d.setClean();
            }
        },
        setDirty: function() {
            this.isDirty = true;
            this.history[0] = this.history[1];
            this.history[1] = dirty;
            if (this.options.fireEventsOnEachChange || this.wasJustClean()) {
                this.form.trigger("dirty");
            }
        },
        setClean: function() {
            this.isDirty = false;
            this.history[0] = this.history[1];
            this.history[1] = clean;
            if (this.options.fireEventsOnEachChange || this.wasJustDirty()) {
                this.form.trigger("clean");
            }
        },
        wasJustDirty: function() {
            return this.history[0] === dirty;
        },
        wasJustClean: function() {
            return this.history[0] === clean;
        },
        setAsClean: function() {
            this.saveInitialValues();
            this.setClean();
        },
        setAsDirty: function() {
            this.saveInitialValues();
            this.setDirty();
        },
        resetForm: function() {
            var d = this;
            this.form.find("input, select, textarea").each(function(_, e) {
                var $e = $(e);
                var isRadioOrCheckbox = d.isRadioOrCheckbox(e);
                var isFile = d.isFileInput(e);
                if (isRadioOrCheckbox) {
                    var initialCheckedState = $e.data(dataInitialValue);
                    var isChecked = initialCheckedState === "checked";
                    $e.prop("checked", isChecked);
                }
                if (isFile) {
                    e.value = "";
                    $(e).data(dataInitialValue, JSON.stringify(e.files));
                } else {
                    var value = $e.data(dataInitialValue);
                    $e.val(value);
                }
            });
            this.checkValues();
        }
    };
    $.fn.dirty = function(options) {
        if (typeof options === "string") {
            var d = getSingleton($(this).attr("id"));
            if (!d) {
                return null;
            }
            if (/^(isDirty|isClean|refreshEvents|resetForm|setAsClean|setAsDirty|showDirtyFields|destroy)$/i.test(options)) {
                var optionsLowerCase = options.toLowerCase();
                switch (optionsLowerCase) {
                  case "isclean":
                    return !d.isDirty;

                  case "isdirty":
                    return d.isDirty;

                  case "refreshevents":
                    return d.refreshEvents();

                  case "resetform":
                    return d.resetForm();

                  case "setasclean":
                    return d.setAsClean();

                  case "setasdirty":
                    return d.setAsDirty();

                  case "showdirtyfields":
                    return d.showDirtyFields();

                  case "destroy":
                    return destroy(d);
                }
            } else {
                return d[options].apply(d, Array.prototype.slice.call(arguments, 1));
            }
        } else {
            return this.each(function(_, e) {
                options = $.extend({}, $.fn.dirty.defaults, options);
                var dirty = new Dirty($(e), options);
                dirty.init();
            });
        }
    };
    $.fn.dirty.singleton = getSingleton;
    $.fn.dirty.defaults = {
        preventLeaving: false,
        leavingMessage: "There are unsaved changes on this page which will be discarded if you continue.",
        onDirty: $.noop,
        onClean: $.noop,
        fireEventsOnEachChange: false
    };
    $.fn.dirty.extend = function(methods) {
        $.extend(Dirty.prototype, methods);
    };
    $.fn.dirty.constructor = Dirty;
    $.fn.dirty.prototype = Dirty.prototype;
})(jQuery);

+function($) {
    "use strict";
    var backdrop = ".dropdown-backdrop";
    var toggle = '[data-toggle="dropdown"]';
    var Dropdown = function(element) {
        $(element).on("click.bs.dropdown", this.toggle);
    };
    Dropdown.VERSION = "3.4.1";
    function getParent($this) {
        var selector = $this.attr("data-target");
        if (!selector) {
            selector = $this.attr("href");
            selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, "");
        }
        var $parent = selector !== "#" ? $(document).find(selector) : null;
        return $parent && $parent.length ? $parent : $this.parent();
    }
    function clearMenus(e) {
        if (e && e.which === 3) return;
        if (e.preventDropdownClose) return;
        $(backdrop).remove();
        $(toggle).each(function() {
            var $this = $(this);
            var $parent = getParent($this);
            var relatedTarget = {
                relatedTarget: this
            };
            if (!$parent.hasClass("open")) return;
            if (e && e.type == "click" && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return;
            $parent.trigger(e = $.Event("hide.bs.dropdown", relatedTarget));
            if (e.isDefaultPrevented()) return;
            $this.attr("aria-expanded", "false");
            $parent.removeClass("open").trigger($.Event("hidden.bs.dropdown", relatedTarget));
        });
    }
    Dropdown.prototype.toggle = function(e) {
        var $this = $(this);
        if ($this.is(".disabled, :disabled")) return;
        var $parent = getParent($this);
        var isActive = $parent.hasClass("open");
        clearMenus(e);
        if (!isActive) {
            if ("ontouchstart" in document.documentElement && !$parent.closest(".navbar-nav").length) {
                $(document.createElement("div")).addClass("dropdown-backdrop").insertAfter($(this)).on("click", clearMenus);
            }
            var relatedTarget = {
                relatedTarget: this
            };
            $parent.trigger(e = $.Event("show.bs.dropdown", relatedTarget));
            if (e.isDefaultPrevented()) return;
            $this.trigger("focus").attr("aria-expanded", "true");
            $parent.toggleClass("open").trigger($.Event("shown.bs.dropdown", relatedTarget));
        }
        return false;
    };
    Dropdown.prototype.keydown = function(e) {
        if (!/(38|40|27|32)/.test(e.which) || /input|textarea/i.test(e.target.tagName)) return;
        var $this = $(this);
        e.preventDefault();
        e.stopPropagation();
        if ($this.is(".disabled, :disabled")) return;
        var $parent = getParent($this);
        var isActive = $parent.hasClass("open");
        if (!isActive && e.which != 27 || isActive && e.which == 27) {
            if (e.which == 27) $parent.find(toggle).trigger("focus");
            return $this.trigger("click");
        }
        var desc = " li:not(.disabled):visible a";
        var $items = $parent.find(".dropdown-menu" + desc);
        if (!$items.length) return;
        var index = $items.index(e.target);
        if (e.which == 38 && index > 0) index--;
        if (e.which == 40 && index < $items.length - 1) index++;
        if (!~index) index = 0;
        $items.eq(index).trigger("focus");
    };
    function Plugin(option) {
        return this.each(function() {
            var $this = $(this);
            var data = $this.data("bs.dropdown");
            if (!data) $this.data("bs.dropdown", data = new Dropdown(this));
            if (typeof option == "string") data[option].call($this);
        });
    }
    var old = $.fn.dropdown;
    $.fn.dropdown = Plugin;
    $.fn.dropdown.Constructor = Dropdown;
    $.fn.dropdown.noConflict = function() {
        $.fn.dropdown = old;
        return this;
    };
    $(document).on("click.bs.dropdown.data-api", clearMenus).on("click.bs.dropdown.data-api", ".dropdown form", function(e) {
        e.stopPropagation();
    }).on("click.bs.dropdown.data-api", toggle, Dropdown.prototype.toggle).on("keydown.bs.dropdown.data-api", toggle, Dropdown.prototype.keydown).on("keydown.bs.dropdown.data-api", ".dropdown-menu", Dropdown.prototype.keydown);
}(jQuery);

+function($) {
    "use strict";
    var Modal = function(element, options) {
        this.options = options;
        this.$body = $(document.body);
        this.$element = $(element);
        this.$dialog = this.$element.find(".modal-dialog");
        this.$backdrop = null;
        this.isShown = null;
        this.originalBodyPad = null;
        this.scrollbarWidth = 0;
        this.ignoreBackdropClick = false;
        this.fixedContent = ".navbar-fixed-top, .navbar-fixed-bottom";
        if (this.options.remote) {
            this.$element.find(".modal-content").load(this.options.remote, $.proxy(function() {
                this.$element.trigger("loaded.bs.modal");
            }, this));
        }
    };
    Modal.VERSION = "3.4.1";
    Modal.TRANSITION_DURATION = 300;
    Modal.BACKDROP_TRANSITION_DURATION = 150;
    Modal.DEFAULTS = {
        backdrop: true,
        keyboard: true,
        show: true
    };
    Modal.prototype.toggle = function(_relatedTarget) {
        return this.isShown ? this.hide() : this.show(_relatedTarget);
    };
    Modal.prototype.show = function(_relatedTarget) {
        var that = this;
        var e = $.Event("show.bs.modal", {
            relatedTarget: _relatedTarget
        });
        this.$element.trigger(e);
        if (this.isShown || e.isDefaultPrevented()) return;
        this.isShown = true;
        this.checkScrollbar();
        this.setScrollbar();
        this.$body.addClass("modal-open");
        this.escape();
        this.resize();
        this.$element.on("click.dismiss.bs.modal", '[data-dismiss="modal"]', $.proxy(this.hide, this));
        this.$dialog.on("mousedown.dismiss.bs.modal", function() {
            that.$element.one("mouseup.dismiss.bs.modal", function(e) {
                if ($(e.target).is(that.$element)) that.ignoreBackdropClick = true;
            });
        });
        this.backdrop(function() {
            var transition = $.support.transition && that.$element.hasClass("fade");
            if (!that.$element.parent().length) {
                that.$element.appendTo(that.$body);
            }
            that.$element.show().scrollTop(0);
            that.adjustDialog();
            if (transition) {
                that.$element[0].offsetWidth;
            }
            that.$element.addClass("in");
            that.enforceFocus();
            var e = $.Event("shown.bs.modal", {
                relatedTarget: _relatedTarget
            });
            transition ? that.$dialog.one("bsTransitionEnd", function() {
                that.$element.trigger("focus").trigger(e);
            }).emulateTransitionEnd(Modal.TRANSITION_DURATION) : that.$element.trigger("focus").trigger(e);
        });
    };
    Modal.prototype.hide = function(e) {
        if (e) e.preventDefault();
        e = $.Event("hide.bs.modal");
        this.$element.trigger(e);
        if (!this.isShown || e.isDefaultPrevented()) return;
        this.isShown = false;
        this.escape();
        this.resize();
        $(document).off("focusin.bs.modal");
        this.$element.removeClass("in").off("click.dismiss.bs.modal").off("mouseup.dismiss.bs.modal");
        this.$dialog.off("mousedown.dismiss.bs.modal");
        $.support.transition && this.$element.hasClass("fade") ? this.$element.one("bsTransitionEnd", $.proxy(this.hideModal, this)).emulateTransitionEnd(Modal.TRANSITION_DURATION) : this.hideModal();
    };
    Modal.prototype.enforceFocus = function() {
        $(document).off("focusin.bs.modal").on("focusin.bs.modal", $.proxy(function(e) {
            if (document !== e.target && this.$element[0] !== e.target && !this.$element.has(e.target).length) {
                this.$element.trigger("focus");
            }
        }, this));
    };
    Modal.prototype.escape = function() {
        if (this.isShown && this.options.keyboard) {
            this.$element.on("keydown.dismiss.bs.modal", $.proxy(function(e) {
                e.which == 27 && this.hide();
            }, this));
        } else if (!this.isShown) {
            this.$element.off("keydown.dismiss.bs.modal");
        }
    };
    Modal.prototype.resize = function() {
        if (this.isShown) {
            $(window).on("resize.bs.modal", $.proxy(this.handleUpdate, this));
        } else {
            $(window).off("resize.bs.modal");
        }
    };
    Modal.prototype.hideModal = function() {
        var that = this;
        this.$element.hide();
        this.backdrop(function() {
            that.$body.removeClass("modal-open");
            that.resetAdjustments();
            that.resetScrollbar();
            that.$element.trigger("hidden.bs.modal");
        });
    };
    Modal.prototype.removeBackdrop = function() {
        this.$backdrop && this.$backdrop.remove();
        this.$backdrop = null;
    };
    Modal.prototype.backdrop = function(callback) {
        var that = this;
        var animate = this.$element.hasClass("fade") ? "fade" : "";
        if (this.isShown && this.options.backdrop) {
            var doAnimate = $.support.transition && animate;
            this.$backdrop = $(document.createElement("div")).addClass("modal-backdrop " + animate).appendTo(this.$body);
            this.$element.on("click.dismiss.bs.modal", $.proxy(function(e) {
                if (this.ignoreBackdropClick) {
                    this.ignoreBackdropClick = false;
                    return;
                }
                if (e.target !== e.currentTarget) return;
                this.options.backdrop == "static" ? this.$element[0].focus() : this.hide();
            }, this));
            this.$backdrop.on("click.dismiss.bs.modal", $.proxy(function(e) {
                this.hide.call(this);
            }, this));
            if (doAnimate) this.$backdrop[0].offsetWidth;
            this.$backdrop.addClass("in");
            if (!callback) return;
            doAnimate ? this.$backdrop.one("bsTransitionEnd", callback).emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : callback();
        } else if (!this.isShown && this.$backdrop) {
            this.$backdrop.removeClass("in");
            var callbackRemove = function() {
                that.removeBackdrop();
                callback && callback();
            };
            $.support.transition && this.$element.hasClass("fade") ? this.$backdrop.one("bsTransitionEnd", callbackRemove).emulateTransitionEnd(Modal.BACKDROP_TRANSITION_DURATION) : callbackRemove();
        } else if (callback) {
            callback();
        }
    };
    Modal.prototype.handleUpdate = function() {
        this.adjustDialog();
    };
    Modal.prototype.adjustDialog = function() {
        var modalIsOverflowing = this.$element[0].scrollHeight > document.documentElement.clientHeight;
        this.$element.css({
            paddingLeft: !this.bodyIsOverflowing && modalIsOverflowing ? this.scrollbarWidth : "",
            paddingRight: this.bodyIsOverflowing && !modalIsOverflowing ? this.scrollbarWidth : ""
        });
    };
    Modal.prototype.resetAdjustments = function() {
        this.$element.css({
            paddingLeft: "",
            paddingRight: ""
        });
    };
    Modal.prototype.checkScrollbar = function() {
        var fullWindowWidth = window.innerWidth;
        if (!fullWindowWidth) {
            var documentElementRect = document.documentElement.getBoundingClientRect();
            fullWindowWidth = documentElementRect.right - Math.abs(documentElementRect.left);
        }
        this.bodyIsOverflowing = document.body.clientWidth < fullWindowWidth;
        this.scrollbarWidth = this.measureScrollbar();
    };
    Modal.prototype.setScrollbar = function() {
        var bodyPad = parseInt(this.$body.css("padding-right") || 0, 10);
        this.originalBodyPad = document.body.style.paddingRight || "";
        var scrollbarWidth = this.scrollbarWidth;
        if (this.bodyIsOverflowing) {
            this.$body.css("padding-right", bodyPad + scrollbarWidth);
            $(this.fixedContent).each(function(index, element) {
                var actualPadding = element.style.paddingRight;
                var calculatedPadding = $(element).css("padding-right");
                $(element).data("padding-right", actualPadding).css("padding-right", parseFloat(calculatedPadding) + scrollbarWidth + "px");
            });
        }
    };
    Modal.prototype.resetScrollbar = function() {
        this.$body.css("padding-right", this.originalBodyPad);
        $(this.fixedContent).each(function(index, element) {
            var padding = $(element).data("padding-right");
            $(element).removeData("padding-right");
            element.style.paddingRight = padding ? padding : "";
        });
    };
    Modal.prototype.measureScrollbar = function() {
        var scrollDiv = document.createElement("div");
        scrollDiv.className = "modal-scrollbar-measure";
        this.$body.append(scrollDiv);
        var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
        this.$body[0].removeChild(scrollDiv);
        return scrollbarWidth;
    };
    function Plugin(option, _relatedTarget) {
        return this.each(function() {
            var $this = $(this);
            var data = $this.data("bs.modal");
            var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == "object" && option);
            if (!data) $this.data("bs.modal", data = new Modal(this, options));
            if (typeof option == "string") data[option](_relatedTarget); else if (options.show) data.show(_relatedTarget);
        });
    }
    var old = $.fn.modal;
    $.fn.modal = Plugin;
    $.fn.modal.Constructor = Modal;
    $.fn.modal.noConflict = function() {
        $.fn.modal = old;
        return this;
    };
    $(document).on("click.bs.modal.data-api", '[data-toggle="modal"]', function(e) {
        var $this = $(this);
        var href = $this.attr("href");
        var target = $this.attr("data-target") || href && href.replace(/.*(?=#[^\s]+$)/, "");
        var $target = $(document).find(target);
        var option = $target.data("bs.modal") ? "toggle" : $.extend({
            remote: !/#/.test(href) && href
        }, $target.data(), $this.data());
        if ($this.is("a")) e.preventDefault();
        $target.one("show.bs.modal", function(showEvent) {
            if (showEvent.isDefaultPrevented()) return;
            $target.one("hidden.bs.modal", function() {
                $this.is(":visible") && $this.trigger("focus");
            });
        });
        Plugin.call($target, option, this);
    });
}(jQuery);

+function($) {
    "use strict";
    var DISALLOWED_ATTRIBUTES = [ "sanitize", "whiteList", "sanitizeFn" ];
    var uriAttrs = [ "background", "cite", "href", "itemtype", "longdesc", "poster", "src", "xlink:href" ];
    var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i;
    var DefaultWhitelist = {
        "*": [ "class", "dir", "id", "lang", "role", ARIA_ATTRIBUTE_PATTERN ],
        a: [ "target", "href", "title", "rel" ],
        area: [],
        b: [],
        br: [],
        col: [],
        code: [],
        div: [],
        em: [],
        hr: [],
        h1: [],
        h2: [],
        h3: [],
        h4: [],
        h5: [],
        h6: [],
        i: [],
        img: [ "src", "alt", "title", "width", "height" ],
        li: [],
        ol: [],
        p: [],
        pre: [],
        s: [],
        small: [],
        span: [],
        sub: [],
        sup: [],
        strong: [],
        u: [],
        ul: []
    };
    var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi;
    var DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i;
    function allowedAttribute(attr, allowedAttributeList) {
        var attrName = attr.nodeName.toLowerCase();
        if ($.inArray(attrName, allowedAttributeList) !== -1) {
            if ($.inArray(attrName, uriAttrs) !== -1) {
                return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN));
            }
            return true;
        }
        var regExp = $(allowedAttributeList).filter(function(index, value) {
            return value instanceof RegExp;
        });
        for (var i = 0, l = regExp.length; i < l; i++) {
            if (attrName.match(regExp[i])) {
                return true;
            }
        }
        return false;
    }
    function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {
        if (unsafeHtml.length === 0) {
            return unsafeHtml;
        }
        if (sanitizeFn && typeof sanitizeFn === "function") {
            return sanitizeFn(unsafeHtml);
        }
        if (!document.implementation || !document.implementation.createHTMLDocument) {
            return unsafeHtml;
        }
        var createdDocument = document.implementation.createHTMLDocument("sanitization");
        createdDocument.body.innerHTML = unsafeHtml;
        var whitelistKeys = $.map(whiteList, function(el, i) {
            return i;
        });
        var elements = $(createdDocument.body).find("*");
        for (var i = 0, len = elements.length; i < len; i++) {
            var el = elements[i];
            var elName = el.nodeName.toLowerCase();
            if ($.inArray(elName, whitelistKeys) === -1) {
                el.parentNode.removeChild(el);
                continue;
            }
            var attributeList = $.map(el.attributes, function(el) {
                return el;
            });
            var whitelistedAttributes = [].concat(whiteList["*"] || [], whiteList[elName] || []);
            for (var j = 0, len2 = attributeList.length; j < len2; j++) {
                if (!allowedAttribute(attributeList[j], whitelistedAttributes)) {
                    el.removeAttribute(attributeList[j].nodeName);
                }
            }
        }
        return createdDocument.body.innerHTML;
    }
    var Tooltip = function(element, options) {
        this.type = null;
        this.options = null;
        this.enabled = null;
        this.timeout = null;
        this.hoverState = null;
        this.$element = null;
        this.inState = null;
        this.init("tooltip", element, options);
    };
    Tooltip.VERSION = "3.4.1";
    Tooltip.TRANSITION_DURATION = 150;
    Tooltip.DEFAULTS = {
        animation: true,
        placement: "top",
        selector: false,
        template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
        trigger: "hover focus",
        title: "",
        delay: 0,
        html: false,
        container: false,
        viewport: {
            selector: "body",
            padding: 0
        },
        sanitize: true,
        sanitizeFn: null,
        whiteList: DefaultWhitelist
    };
    Tooltip.prototype.init = function(type, element, options) {
        this.enabled = true;
        this.type = type;
        this.$element = $(element);
        this.options = this.getOptions(options);
        this.$viewport = this.options.viewport && $(document).find($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : this.options.viewport.selector || this.options.viewport);
        this.inState = {
            click: false,
            hover: false,
            focus: false
        };
        if (this.$element[0] instanceof document.constructor && !this.options.selector) {
            throw new Error("`selector` option must be specified when initializing " + this.type + " on the window.document object!");
        }
        var triggers = this.options.trigger.split(" ");
        for (var i = triggers.length; i--; ) {
            var trigger = triggers[i];
            if (trigger == "click") {
                this.$element.on("click." + this.type, this.options.selector, $.proxy(this.toggle, this));
            } else if (trigger != "manual") {
                var eventIn = trigger == "hover" ? "mouseenter" : "focusin";
                var eventOut = trigger == "hover" ? "mouseleave" : "focusout";
                this.$element.on(eventIn + "." + this.type, this.options.selector, $.proxy(this.enter, this));
                this.$element.on(eventOut + "." + this.type, this.options.selector, $.proxy(this.leave, this));
            }
        }
        this.options.selector ? this._options = $.extend({}, this.options, {
            trigger: "manual",
            selector: ""
        }) : this.fixTitle();
    };
    Tooltip.prototype.getDefaults = function() {
        return Tooltip.DEFAULTS;
    };
    Tooltip.prototype.getOptions = function(options) {
        var dataAttributes = this.$element.data();
        for (var dataAttr in dataAttributes) {
            if (dataAttributes.hasOwnProperty(dataAttr) && $.inArray(dataAttr, DISALLOWED_ATTRIBUTES) !== -1) {
                delete dataAttributes[dataAttr];
            }
        }
        options = $.extend({}, this.getDefaults(), dataAttributes, options);
        if (options.delay && typeof options.delay == "number") {
            options.delay = {
                show: options.delay,
                hide: options.delay
            };
        }
        if (options.sanitize) {
            options.template = sanitizeHtml(options.template, options.whiteList, options.sanitizeFn);
        }
        return options;
    };
    Tooltip.prototype.getDelegateOptions = function() {
        var options = {};
        var defaults = this.getDefaults();
        this._options && $.each(this._options, function(key, value) {
            if (defaults[key] != value) options[key] = value;
        });
        return options;
    };
    Tooltip.prototype.enter = function(obj) {
        var self = obj instanceof this.constructor ? obj : $(obj.currentTarget).data("bs." + this.type);
        if (!self) {
            self = new this.constructor(obj.currentTarget, this.getDelegateOptions());
            $(obj.currentTarget).data("bs." + this.type, self);
        }
        if (obj instanceof $.Event) {
            self.inState[obj.type == "focusin" ? "focus" : "hover"] = true;
        }
        if (self.tip().hasClass("in") || self.hoverState == "in") {
            self.hoverState = "in";
            return;
        }
        clearTimeout(self.timeout);
        self.hoverState = "in";
        if (!self.options.delay || !self.options.delay.show) return self.show();
        self.timeout = setTimeout(function() {
            if (self.hoverState == "in") self.show();
        }, self.options.delay.show);
    };
    Tooltip.prototype.isInStateTrue = function() {
        for (var key in this.inState) {
            if (this.inState[key]) return true;
        }
        return false;
    };
    Tooltip.prototype.leave = function(obj) {
        var self = obj instanceof this.constructor ? obj : $(obj.currentTarget).data("bs." + this.type);
        if (!self) {
            self = new this.constructor(obj.currentTarget, this.getDelegateOptions());
            $(obj.currentTarget).data("bs." + this.type, self);
        }
        if (obj instanceof $.Event) {
            self.inState[obj.type == "focusout" ? "focus" : "hover"] = false;
        }
        if (self.isInStateTrue()) return;
        clearTimeout(self.timeout);
        self.hoverState = "out";
        if (!self.options.delay || !self.options.delay.hide) return self.hide();
        self.timeout = setTimeout(function() {
            if (self.hoverState == "out") self.hide();
        }, self.options.delay.hide);
    };
    Tooltip.prototype.show = function() {
        var e = $.Event("show.bs." + this.type);
        if (this.hasContent() && this.enabled) {
            this.$element.trigger(e);
            var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0]);
            if (e.isDefaultPrevented() || !inDom) return;
            var that = this;
            var $tip = this.tip();
            var tipId = this.getUID(this.type);
            this.setContent();
            $tip.attr("id", tipId);
            this.$element.attr("aria-describedby", tipId);
            if (this.options.animation) $tip.addClass("fade");
            $tip.detach().css({
                top: 0,
                left: 0,
                display: "block"
            }).data("bs." + this.type, this);
            this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element);
            var placement = typeof this.options.placement == "function" ? this.options.placement.call(this, $tip[0], this.$element[0]) : this.options.placement;
            var autoToken = /\s?auto?\s?/i;
            var autoPlace = autoToken.test(placement);
            if (autoPlace) placement = placement.replace(autoToken, "") || "top";
            $tip.addClass(placement);
            this.$element.trigger("inserted.bs." + this.type);
            var pos = this.getPosition();
            var actualWidth = $tip[0].offsetWidth;
            var actualHeight = $tip[0].offsetHeight;
            if (autoPlace) {
                var orgPlacement = placement;
                var viewportDim = this.getPosition(this.$viewport);
                placement = placement == "bottom" && pos.bottom + actualHeight > viewportDim.bottom ? "top" : placement == "top" && pos.top - actualHeight < viewportDim.top ? "bottom" : placement == "right" && pos.right + actualWidth > viewportDim.width ? "left" : placement == "left" && pos.left - actualWidth < viewportDim.left ? "right" : placement;
                $tip.removeClass(orgPlacement).addClass(placement);
            }
            var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight);
            this.applyPlacement(calculatedOffset, placement);
            var complete = function() {
                var prevHoverState = that.hoverState;
                that.$element.trigger("shown.bs." + that.type);
                that.hoverState = null;
                if (prevHoverState == "out") that.leave(that);
            };
            $.support.transition && this.$tip.hasClass("fade") ? $tip.one("bsTransitionEnd", complete).emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : complete();
        }
    };
    Tooltip.prototype.applyPlacement = function(offset, placement) {
        var $tip = this.tip();
        var width = $tip[0].offsetWidth;
        var height = $tip[0].offsetHeight;
        var marginTop = parseInt($tip.css("margin-top"), 10);
        var marginLeft = parseInt($tip.css("margin-left"), 10);
        if (isNaN(marginTop)) marginTop = 0;
        if (isNaN(marginLeft)) marginLeft = 0;
        offset.top += marginTop;
        offset.left += marginLeft;
        $.offset.setOffset($tip[0], $.extend({
            using: function(props) {
                $tip.css({
                    top: Math.round(props.top),
                    left: Math.round(props.left)
                });
            }
        }, offset), 0);
        $tip.addClass("in");
        var actualWidth = $tip[0].offsetWidth;
        var actualHeight = $tip[0].offsetHeight;
        if (placement == "top" && actualHeight != height) {
            offset.top = offset.top + height - actualHeight;
        }
        var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight);
        if (delta.left) offset.left += delta.left; else offset.top += delta.top;
        var isVertical = /top|bottom/.test(placement);
        var arrowDelta = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight;
        var arrowOffsetPosition = isVertical ? "offsetWidth" : "offsetHeight";
        $tip.offset(offset);
        this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical);
    };
    Tooltip.prototype.replaceArrow = function(delta, dimension, isVertical) {
        this.arrow().css(isVertical ? "left" : "top", 50 * (1 - delta / dimension) + "%").css(isVertical ? "top" : "left", "");
    };
    Tooltip.prototype.setContent = function() {
        var $tip = this.tip();
        var title = this.getTitle();
        if (this.options.html) {
            if (this.options.sanitize) {
                title = sanitizeHtml(title, this.options.whiteList, this.options.sanitizeFn);
            }
            $tip.find(".tooltip-inner").html(title);
        } else {
            $tip.find(".tooltip-inner").text(title);
        }
        $tip.removeClass("fade in top bottom left right");
    };
    Tooltip.prototype.hide = function(callback) {
        var that = this;
        var $tip = $(this.$tip);
        var e = $.Event("hide.bs." + this.type);
        function complete() {
            if (that.hoverState != "in") $tip.detach();
            if (that.$element) {
                that.$element.removeAttr("aria-describedby").trigger("hidden.bs." + that.type);
            }
            callback && callback();
        }
        this.$element.trigger(e);
        if (e.isDefaultPrevented()) return;
        $tip.removeClass("in");
        $.support.transition && $tip.hasClass("fade") ? $tip.one("bsTransitionEnd", complete).emulateTransitionEnd(Tooltip.TRANSITION_DURATION) : complete();
        this.hoverState = null;
        return this;
    };
    Tooltip.prototype.fixTitle = function() {
        var $e = this.$element;
        if ($e.attr("title") || typeof $e.attr("data-original-title") != "string") {
            $e.attr("data-original-title", $e.attr("title") || "").attr("title", "");
        }
    };
    Tooltip.prototype.hasContent = function() {
        return this.getTitle();
    };
    Tooltip.prototype.getPosition = function($element) {
        $element = $element || this.$element;
        var el = $element[0];
        var isBody = el.tagName == "BODY";
        var elRect = el.getBoundingClientRect();
        if (elRect.width == null) {
            elRect = $.extend({}, elRect, {
                width: elRect.right - elRect.left,
                height: elRect.bottom - elRect.top
            });
        }
        var isSvg = window.SVGElement && el instanceof window.SVGElement;
        var elOffset = isBody ? {
            top: 0,
            left: 0
        } : isSvg ? null : $element.offset();
        var scroll = {
            scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop()
        };
        var outerDims = isBody ? {
            width: $(window).width(),
            height: $(window).height()
        } : null;
        return $.extend({}, elRect, scroll, outerDims, elOffset);
    };
    Tooltip.prototype.getCalculatedOffset = function(placement, pos, actualWidth, actualHeight) {
        return placement == "bottom" ? {
            top: pos.top + pos.height,
            left: pos.left + pos.width / 2 - actualWidth / 2
        } : placement == "top" ? {
            top: pos.top - actualHeight,
            left: pos.left + pos.width / 2 - actualWidth / 2
        } : placement == "left" ? {
            top: pos.top + pos.height / 2 - actualHeight / 2,
            left: pos.left - actualWidth
        } : {
            top: pos.top + pos.height / 2 - actualHeight / 2,
            left: pos.left + pos.width
        };
    };
    Tooltip.prototype.getViewportAdjustedDelta = function(placement, pos, actualWidth, actualHeight) {
        var delta = {
            top: 0,
            left: 0
        };
        if (!this.$viewport) return delta;
        var viewportPadding = this.options.viewport && this.options.viewport.padding || 0;
        var viewportDimensions = this.getPosition(this.$viewport);
        if (/right|left/.test(placement)) {
            var topEdgeOffset = pos.top - viewportPadding - viewportDimensions.scroll;
            var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight;
            if (topEdgeOffset < viewportDimensions.top) {
                delta.top = viewportDimensions.top - topEdgeOffset;
            } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) {
                delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset;
            }
        } else {
            var leftEdgeOffset = pos.left - viewportPadding;
            var rightEdgeOffset = pos.left + viewportPadding + actualWidth;
            if (leftEdgeOffset < viewportDimensions.left) {
                delta.left = viewportDimensions.left - leftEdgeOffset;
            } else if (rightEdgeOffset > viewportDimensions.right) {
                delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset;
            }
        }
        return delta;
    };
    Tooltip.prototype.getTitle = function() {
        var title;
        var $e = this.$element;
        var o = this.options;
        title = $e.attr("data-original-title") || (typeof o.title == "function" ? o.title.call($e[0]) : o.title);
        return title;
    };
    Tooltip.prototype.getUID = function(prefix) {
        do {
            prefix += ~~(Math.random() * 1e6);
        } while (document.getElementById(prefix));
        return prefix;
    };
    Tooltip.prototype.tip = function() {
        if (!this.$tip) {
            this.$tip = $(this.options.template);
            if (this.$tip.length != 1) {
                throw new Error(this.type + " `template` option must consist of exactly 1 top-level element!");
            }
        }
        return this.$tip;
    };
    Tooltip.prototype.arrow = function() {
        return this.$arrow = this.$arrow || this.tip().find(".tooltip-arrow");
    };
    Tooltip.prototype.enable = function() {
        this.enabled = true;
    };
    Tooltip.prototype.disable = function() {
        this.enabled = false;
    };
    Tooltip.prototype.toggleEnabled = function() {
        this.enabled = !this.enabled;
    };
    Tooltip.prototype.toggle = function(e) {
        var self = this;
        if (e) {
            self = $(e.currentTarget).data("bs." + this.type);
            if (!self) {
                self = new this.constructor(e.currentTarget, this.getDelegateOptions());
                $(e.currentTarget).data("bs." + this.type, self);
            }
        }
        if (e) {
            self.inState.click = !self.inState.click;
            if (self.isInStateTrue()) self.enter(self); else self.leave(self);
        } else {
            self.tip().hasClass("in") ? self.leave(self) : self.enter(self);
        }
    };
    Tooltip.prototype.destroy = function() {
        var that = this;
        clearTimeout(this.timeout);
        this.hide(function() {
            that.$element.off("." + that.type).removeData("bs." + that.type);
            if (that.$tip) {
                that.$tip.detach();
            }
            that.$tip = null;
            that.$arrow = null;
            that.$viewport = null;
            that.$element = null;
        });
    };
    Tooltip.prototype.sanitizeHtml = function(unsafeHtml) {
        return sanitizeHtml(unsafeHtml, this.options.whiteList, this.options.sanitizeFn);
    };
    function Plugin(option) {
        return this.each(function() {
            var $this = $(this);
            var data = $this.data("bs.tooltip");
            var options = typeof option == "object" && option;
            if (!data && /destroy|hide/.test(option)) return;
            if (!data) $this.data("bs.tooltip", data = new Tooltip(this, options));
            if (typeof option == "string") data[option]();
        });
    }
    var old = $.fn.bsTooltip;
    $.fn.bsTooltip = Plugin;
    $.fn.bsTooltip.Constructor = Tooltip;
    $.fn.bsTooltip.noConflict = function() {
        $.fn.bsTooltip = old;
        return this;
    };
}(jQuery);

+function($) {
    "use strict";
    var Popover = function(element, options) {
        this.init("popover", element, options);
    };
    if (!$.fn.bsTooltip) throw new Error("Popover requires bootstrap-tooltip.js");
    Popover.VERSION = "3.4.1";
    Popover.DEFAULTS = $.extend({}, $.fn.bsTooltip.Constructor.DEFAULTS, {
        placement: "right",
        trigger: "click",
        content: "",
        template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
    });
    Popover.prototype = $.extend({}, $.fn.bsTooltip.Constructor.prototype);
    Popover.prototype.constructor = Popover;
    Popover.prototype.getDefaults = function() {
        return Popover.DEFAULTS;
    };
    Popover.prototype.setContent = function() {
        var $tip = this.tip();
        var title = this.getTitle();
        var content = this.getContent();
        if (this.options.html) {
            var typeContent = typeof content;
            if (this.options.sanitize) {
                title = this.sanitizeHtml(title);
                if (typeContent === "string") {
                    content = this.sanitizeHtml(content);
                }
            }
            $tip.find(".popover-title").html(title);
            $tip.find(".popover-content").children().detach().end()[typeContent === "string" ? "html" : "append"](content);
        } else {
            $tip.find(".popover-title").text(title);
            $tip.find(".popover-content").children().detach().end().text(content);
        }
        $tip.removeClass("fade top bottom left right in");
        if (!$tip.find(".popover-title").html()) $tip.find(".popover-title").hide();
    };
    Popover.prototype.hasContent = function() {
        return this.getTitle() || this.getContent();
    };
    Popover.prototype.getContent = function() {
        var $e = this.$element;
        var o = this.options;
        return $e.attr("data-content") || (typeof o.content == "function" ? o.content.call($e[0]) : o.content);
    };
    Popover.prototype.arrow = function() {
        return this.$arrow = this.$arrow || this.tip().find(".arrow");
    };
    function Plugin(option) {
        return this.each(function() {
            var $this = $(this);
            var data = $this.data("bs.popover");
            var options = typeof option == "object" && option;
            if (!data && /destroy|hide/.test(option)) return;
            if (!data) $this.data("bs.popover", data = new Popover(this, options));
            if (typeof option == "string") data[option]();
        });
    }
    var old = $.fn.popover;
    $.fn.popover = Plugin;
    $.fn.popover.Constructor = Popover;
    $.fn.popover.noConflict = function() {
        $.fn.popover = old;
        return this;
    };
}(jQuery);

(function(root, factory) {
    if (typeof define === "function" && define.amd) {
        define([ "jquery" ], function(jq) {
            return factory(jq);
        });
    } else if (typeof exports === "object") {
        module.exports = factory(require("jquery"));
    } else if (jQuery && !jQuery.fn.colorpicker) {
        factory(jQuery);
    }
})(this, function($) {
    "use strict";
    var Color = function(val, predefinedColors, fallbackColor, fallbackFormat, hexNumberSignPrefix) {
        this.fallbackValue = fallbackColor ? typeof fallbackColor === "string" ? this.parse(fallbackColor) : fallbackColor : null;
        this.fallbackFormat = fallbackFormat ? fallbackFormat : "rgba";
        this.hexNumberSignPrefix = hexNumberSignPrefix === true;
        this.value = this.fallbackValue;
        this.origFormat = null;
        this.predefinedColors = predefinedColors ? predefinedColors : {};
        this.colors = $.extend({}, Color.webColors, this.predefinedColors);
        if (val) {
            if (typeof val.h !== "undefined") {
                this.value = val;
            } else {
                this.setColor(String(val));
            }
        }
        if (!this.value) {
            this.value = {
                h: 0,
                s: 0,
                b: 0,
                a: 1
            };
        }
    };
    Color.webColors = {
        aliceblue: "f0f8ff",
        antiquewhite: "faebd7",
        aqua: "00ffff",
        aquamarine: "7fffd4",
        azure: "f0ffff",
        beige: "f5f5dc",
        bisque: "ffe4c4",
        black: "000000",
        blanchedalmond: "ffebcd",
        blue: "0000ff",
        blueviolet: "8a2be2",
        brown: "a52a2a",
        burlywood: "deb887",
        cadetblue: "5f9ea0",
        chartreuse: "7fff00",
        chocolate: "d2691e",
        coral: "ff7f50",
        cornflowerblue: "6495ed",
        cornsilk: "fff8dc",
        crimson: "dc143c",
        cyan: "00ffff",
        darkblue: "00008b",
        darkcyan: "008b8b",
        darkgoldenrod: "b8860b",
        darkgray: "a9a9a9",
        darkgreen: "006400",
        darkkhaki: "bdb76b",
        darkmagenta: "8b008b",
        darkolivegreen: "556b2f",
        darkorange: "ff8c00",
        darkorchid: "9932cc",
        darkred: "8b0000",
        darksalmon: "e9967a",
        darkseagreen: "8fbc8f",
        darkslateblue: "483d8b",
        darkslategray: "2f4f4f",
        darkturquoise: "00ced1",
        darkviolet: "9400d3",
        deeppink: "ff1493",
        deepskyblue: "00bfff",
        dimgray: "696969",
        dodgerblue: "1e90ff",
        firebrick: "b22222",
        floralwhite: "fffaf0",
        forestgreen: "228b22",
        fuchsia: "ff00ff",
        gainsboro: "dcdcdc",
        ghostwhite: "f8f8ff",
        gold: "ffd700",
        goldenrod: "daa520",
        gray: "808080",
        green: "008000",
        greenyellow: "adff2f",
        honeydew: "f0fff0",
        hotpink: "ff69b4",
        indianred: "cd5c5c",
        indigo: "4b0082",
        ivory: "fffff0",
        khaki: "f0e68c",
        lavender: "e6e6fa",
        lavenderblush: "fff0f5",
        lawngreen: "7cfc00",
        lemonchiffon: "fffacd",
        lightblue: "add8e6",
        lightcoral: "f08080",
        lightcyan: "e0ffff",
        lightgoldenrodyellow: "fafad2",
        lightgrey: "d3d3d3",
        lightgreen: "90ee90",
        lightpink: "ffb6c1",
        lightsalmon: "ffa07a",
        lightseagreen: "20b2aa",
        lightskyblue: "87cefa",
        lightslategray: "778899",
        lightsteelblue: "b0c4de",
        lightyellow: "ffffe0",
        lime: "00ff00",
        limegreen: "32cd32",
        linen: "faf0e6",
        magenta: "ff00ff",
        maroon: "800000",
        mediumaquamarine: "66cdaa",
        mediumblue: "0000cd",
        mediumorchid: "ba55d3",
        mediumpurple: "9370d8",
        mediumseagreen: "3cb371",
        mediumslateblue: "7b68ee",
        mediumspringgreen: "00fa9a",
        mediumturquoise: "48d1cc",
        mediumvioletred: "c71585",
        midnightblue: "191970",
        mintcream: "f5fffa",
        mistyrose: "ffe4e1",
        moccasin: "ffe4b5",
        navajowhite: "ffdead",
        navy: "000080",
        oldlace: "fdf5e6",
        olive: "808000",
        olivedrab: "6b8e23",
        orange: "ffa500",
        orangered: "ff4500",
        orchid: "da70d6",
        palegoldenrod: "eee8aa",
        palegreen: "98fb98",
        paleturquoise: "afeeee",
        palevioletred: "d87093",
        papayawhip: "ffefd5",
        peachpuff: "ffdab9",
        peru: "cd853f",
        pink: "ffc0cb",
        plum: "dda0dd",
        powderblue: "b0e0e6",
        purple: "800080",
        red: "ff0000",
        rosybrown: "bc8f8f",
        royalblue: "4169e1",
        saddlebrown: "8b4513",
        salmon: "fa8072",
        sandybrown: "f4a460",
        seagreen: "2e8b57",
        seashell: "fff5ee",
        sienna: "a0522d",
        silver: "c0c0c0",
        skyblue: "87ceeb",
        slateblue: "6a5acd",
        slategray: "708090",
        snow: "fffafa",
        springgreen: "00ff7f",
        steelblue: "4682b4",
        tan: "d2b48c",
        teal: "008080",
        thistle: "d8bfd8",
        tomato: "ff6347",
        turquoise: "40e0d0",
        violet: "ee82ee",
        wheat: "f5deb3",
        white: "ffffff",
        whitesmoke: "f5f5f5",
        yellow: "ffff00",
        yellowgreen: "9acd32",
        transparent: "transparent"
    };
    Color.prototype = {
        constructor: Color,
        colors: {},
        predefinedColors: {},
        getValue: function() {
            return this.value;
        },
        setValue: function(val) {
            this.value = val;
        },
        _sanitizeNumber: function(val) {
            if (typeof val === "number") {
                return val;
            }
            if (isNaN(val) || val === null || val === "" || val === undefined) {
                return 1;
            }
            if (val === "") {
                return 0;
            }
            if (typeof val.toLowerCase !== "undefined") {
                if (val.match(/^\./)) {
                    val = "0" + val;
                }
                return Math.ceil(parseFloat(val) * 100) / 100;
            }
            return 1;
        },
        isTransparent: function(strVal) {
            if (!strVal || !(typeof strVal === "string" || strVal instanceof String)) {
                return false;
            }
            strVal = strVal.toLowerCase().trim();
            return strVal === "transparent" || strVal.match(/#?00000000/) || strVal.match(/(rgba|hsla)\(0,0,0,0?\.?0\)/);
        },
        rgbaIsTransparent: function(rgba) {
            return rgba.r === 0 && rgba.g === 0 && rgba.b === 0 && rgba.a === 0;
        },
        setColor: function(strVal) {
            strVal = strVal.toLowerCase().trim();
            if (strVal) {
                if (this.isTransparent(strVal)) {
                    this.value = {
                        h: 0,
                        s: 0,
                        b: 0,
                        a: 0
                    };
                    return true;
                } else {
                    var parsedColor = this.parse(strVal);
                    if (parsedColor) {
                        this.value = this.value = {
                            h: parsedColor.h,
                            s: parsedColor.s,
                            b: parsedColor.b,
                            a: parsedColor.a
                        };
                        if (!this.origFormat) {
                            this.origFormat = parsedColor.format;
                        }
                    } else if (this.fallbackValue) {
                        this.value = this.fallbackValue;
                    }
                }
            }
            return false;
        },
        setHue: function(h) {
            this.value.h = 1 - h;
        },
        setSaturation: function(s) {
            this.value.s = s;
        },
        setBrightness: function(b) {
            this.value.b = 1 - b;
        },
        setAlpha: function(a) {
            this.value.a = Math.round(parseInt((1 - a) * 100, 10) / 100 * 100) / 100;
        },
        toRGB: function(h, s, b, a) {
            if (arguments.length === 0) {
                h = this.value.h;
                s = this.value.s;
                b = this.value.b;
                a = this.value.a;
            }
            h *= 360;
            var R, G, B, X, C;
            h = h % 360 / 60;
            C = b * s;
            X = C * (1 - Math.abs(h % 2 - 1));
            R = G = B = b - C;
            h = ~~h;
            R += [ C, X, 0, 0, X, C ][h];
            G += [ X, C, C, X, 0, 0 ][h];
            B += [ 0, 0, X, C, C, X ][h];
            return {
                r: Math.round(R * 255),
                g: Math.round(G * 255),
                b: Math.round(B * 255),
                a: a
            };
        },
        toHex: function(ignoreFormat, h, s, b, a) {
            if (arguments.length <= 1) {
                h = this.value.h;
                s = this.value.s;
                b = this.value.b;
                a = this.value.a;
            }
            var prefix = "#";
            var rgb = this.toRGB(h, s, b, a);
            if (this.rgbaIsTransparent(rgb)) {
                return "transparent";
            }
            if (!ignoreFormat) {
                prefix = this.hexNumberSignPrefix ? "#" : "";
            }
            var hexStr = prefix + ((1 << 24) + (parseInt(rgb.r) << 16) + (parseInt(rgb.g) << 8) + parseInt(rgb.b)).toString(16).slice(1);
            return hexStr;
        },
        toHSL: function(h, s, b, a) {
            if (arguments.length === 0) {
                h = this.value.h;
                s = this.value.s;
                b = this.value.b;
                a = this.value.a;
            }
            var H = h, L = (2 - s) * b, S = s * b;
            if (L > 0 && L <= 1) {
                S /= L;
            } else {
                S /= 2 - L;
            }
            L /= 2;
            if (S > 1) {
                S = 1;
            }
            return {
                h: isNaN(H) ? 0 : H,
                s: isNaN(S) ? 0 : S,
                l: isNaN(L) ? 0 : L,
                a: isNaN(a) ? 0 : a
            };
        },
        toAlias: function(r, g, b, a) {
            var c, rgb = arguments.length === 0 ? this.toHex(true) : this.toHex(true, r, g, b, a);
            var original = this.origFormat === "alias" ? rgb : this.toString(false, this.origFormat);
            for (var alias in this.colors) {
                c = this.colors[alias].toLowerCase().trim();
                if (c === rgb || c === original) {
                    return alias;
                }
            }
            return false;
        },
        RGBtoHSB: function(r, g, b, a) {
            r /= 255;
            g /= 255;
            b /= 255;
            var H, S, V, C;
            V = Math.max(r, g, b);
            C = V - Math.min(r, g, b);
            H = C === 0 ? null : V === r ? (g - b) / C : V === g ? (b - r) / C + 2 : (r - g) / C + 4;
            H = (H + 360) % 6 * 60 / 360;
            S = C === 0 ? 0 : C / V;
            return {
                h: this._sanitizeNumber(H),
                s: S,
                b: V,
                a: this._sanitizeNumber(a)
            };
        },
        HueToRGB: function(p, q, h) {
            if (h < 0) {
                h += 1;
            } else if (h > 1) {
                h -= 1;
            }
            if (h * 6 < 1) {
                return p + (q - p) * h * 6;
            } else if (h * 2 < 1) {
                return q;
            } else if (h * 3 < 2) {
                return p + (q - p) * (2 / 3 - h) * 6;
            } else {
                return p;
            }
        },
        HSLtoRGB: function(h, s, l, a) {
            if (s < 0) {
                s = 0;
            }
            var q;
            if (l <= .5) {
                q = l * (1 + s);
            } else {
                q = l + s - l * s;
            }
            var p = 2 * l - q;
            var tr = h + 1 / 3;
            var tg = h;
            var tb = h - 1 / 3;
            var r = Math.round(this.HueToRGB(p, q, tr) * 255);
            var g = Math.round(this.HueToRGB(p, q, tg) * 255);
            var b = Math.round(this.HueToRGB(p, q, tb) * 255);
            return [ r, g, b, this._sanitizeNumber(a) ];
        },
        parse: function(strVal) {
            if (typeof strVal !== "string") {
                return this.fallbackValue;
            }
            if (arguments.length === 0) {
                return false;
            }
            var that = this, result = false, isAlias = typeof this.colors[strVal] !== "undefined", values, format;
            if (isAlias) {
                strVal = this.colors[strVal].toLowerCase().trim();
            }
            $.each(this.stringParsers, function(i, parser) {
                var match = parser.re.exec(strVal);
                values = match && parser.parse.apply(that, [ match ]);
                if (values) {
                    result = {};
                    format = isAlias ? "alias" : parser.format ? parser.format : that.getValidFallbackFormat();
                    if (format.match(/hsla?/)) {
                        result = that.RGBtoHSB.apply(that, that.HSLtoRGB.apply(that, values));
                    } else {
                        result = that.RGBtoHSB.apply(that, values);
                    }
                    if (result instanceof Object) {
                        result.format = format;
                    }
                    return false;
                }
                return true;
            });
            return result;
        },
        getValidFallbackFormat: function() {
            var formats = [ "rgba", "rgb", "hex", "hsla", "hsl" ];
            if (this.origFormat && formats.indexOf(this.origFormat) !== -1) {
                return this.origFormat;
            }
            if (this.fallbackFormat && formats.indexOf(this.fallbackFormat) !== -1) {
                return this.fallbackFormat;
            }
            return "rgba";
        },
        toString: function(forceRawValue, format, translateAlias) {
            format = format || this.origFormat || this.fallbackFormat;
            translateAlias = translateAlias || false;
            var c = false;
            switch (format) {
              case "rgb":
                {
                    c = this.toRGB();
                    if (this.rgbaIsTransparent(c)) {
                        return "transparent";
                    }
                    return "rgb(" + c.r + "," + c.g + "," + c.b + ")";
                }
                break;

              case "rgba":
                {
                    c = this.toRGB();
                    return "rgba(" + c.r + "," + c.g + "," + c.b + "," + c.a + ")";
                }
                break;

              case "hsl":
                {
                    c = this.toHSL();
                    return "hsl(" + Math.round(c.h * 360) + "," + Math.round(c.s * 100) + "%," + Math.round(c.l * 100) + "%)";
                }
                break;

              case "hsla":
                {
                    c = this.toHSL();
                    return "hsla(" + Math.round(c.h * 360) + "," + Math.round(c.s * 100) + "%," + Math.round(c.l * 100) + "%," + c.a + ")";
                }
                break;

              case "hex":
                {
                    return this.toHex(forceRawValue);
                }
                break;

              case "alias":
                {
                    c = this.toAlias();
                    if (c === false) {
                        return this.toString(forceRawValue, this.getValidFallbackFormat());
                    }
                    if (translateAlias && !(c in Color.webColors) && c in this.predefinedColors) {
                        return this.predefinedColors[c];
                    }
                    return c;
                }

              default:
                {
                    return c;
                }
                break;
            }
        },
        stringParsers: [ {
            re: /rgb\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*?\)/,
            format: "rgb",
            parse: function(execResult) {
                return [ execResult[1], execResult[2], execResult[3], 1 ];
            }
        }, {
            re: /rgb\(\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*?\)/,
            format: "rgb",
            parse: function(execResult) {
                return [ 2.55 * execResult[1], 2.55 * execResult[2], 2.55 * execResult[3], 1 ];
            }
        }, {
            re: /rgba\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d*(?:\.\d+)?)\s*)?\)/,
            format: "rgba",
            parse: function(execResult) {
                return [ execResult[1], execResult[2], execResult[3], execResult[4] ];
            }
        }, {
            re: /rgba\(\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*(?:,\s*(\d*(?:\.\d+)?)\s*)?\)/,
            format: "rgba",
            parse: function(execResult) {
                return [ 2.55 * execResult[1], 2.55 * execResult[2], 2.55 * execResult[3], execResult[4] ];
            }
        }, {
            re: /hsl\(\s*(\d*(?:\.\d+)?)\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*?\)/,
            format: "hsl",
            parse: function(execResult) {
                return [ execResult[1] / 360, execResult[2] / 100, execResult[3] / 100, execResult[4] ];
            }
        }, {
            re: /hsla\(\s*(\d*(?:\.\d+)?)\s*,\s*(\d*(?:\.\d+)?)\%\s*,\s*(\d*(?:\.\d+)?)\%\s*(?:,\s*(\d*(?:\.\d+)?)\s*)?\)/,
            format: "hsla",
            parse: function(execResult) {
                return [ execResult[1] / 360, execResult[2] / 100, execResult[3] / 100, execResult[4] ];
            }
        }, {
            re: /#?([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/,
            format: "hex",
            parse: function(execResult) {
                return [ parseInt(execResult[1], 16), parseInt(execResult[2], 16), parseInt(execResult[3], 16), 1 ];
            }
        }, {
            re: /#?([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/,
            format: "hex",
            parse: function(execResult) {
                return [ parseInt(execResult[1] + execResult[1], 16), parseInt(execResult[2] + execResult[2], 16), parseInt(execResult[3] + execResult[3], 16), 1 ];
            }
        } ],
        colorNameToHex: function(name) {
            if (typeof this.colors[name.toLowerCase()] !== "undefined") {
                return this.colors[name.toLowerCase()];
            }
            return false;
        }
    };
    var defaults = {
        horizontal: false,
        inline: false,
        color: false,
        format: false,
        input: "input",
        container: false,
        component: ".add-on, .input-group-addon",
        fallbackColor: false,
        fallbackFormat: "hex",
        hexNumberSignPrefix: true,
        sliders: {
            saturation: {
                maxLeft: 100,
                maxTop: 100,
                callLeft: "setSaturation",
                callTop: "setBrightness"
            },
            hue: {
                maxLeft: 0,
                maxTop: 100,
                callLeft: false,
                callTop: "setHue"
            },
            alpha: {
                maxLeft: 0,
                maxTop: 100,
                callLeft: false,
                callTop: "setAlpha"
            }
        },
        slidersHorz: {
            saturation: {
                maxLeft: 100,
                maxTop: 100,
                callLeft: "setSaturation",
                callTop: "setBrightness"
            },
            hue: {
                maxLeft: 100,
                maxTop: 0,
                callLeft: "setHue",
                callTop: false
            },
            alpha: {
                maxLeft: 100,
                maxTop: 0,
                callLeft: "setAlpha",
                callTop: false
            }
        },
        template: '<div class="colorpicker dropdown-menu">' + '<div class="colorpicker-saturation"><i><b></b></i></div>' + '<div class="colorpicker-hue"><i></i></div>' + '<div class="colorpicker-alpha"><i></i></div>' + '<div class="colorpicker-color"><div /></div>' + '<div class="colorpicker-selectors"></div>' + "</div>",
        align: "right",
        customClass: null,
        colorSelectors: null
    };
    var Colorpicker = function(element, options) {
        this.element = $(element).addClass("colorpicker-element");
        this.options = $.extend(true, {}, defaults, this.element.data(), options);
        this.component = this.options.component;
        this.component = this.component !== false ? this.element.find(this.component) : false;
        if (this.component && this.component.length === 0) {
            this.component = false;
        }
        this.container = this.options.container === true ? this.element : this.options.container;
        this.container = this.container !== false ? $(this.container) : false;
        this.input = this.element.is("input") ? this.element : this.options.input ? this.element.find(this.options.input) : false;
        if (this.input && this.input.length === 0) {
            this.input = false;
        }
        this.color = this.createColor(this.options.color !== false ? this.options.color : this.getValue());
        this.format = this.options.format !== false ? this.options.format : this.color.origFormat;
        if (this.options.color !== false) {
            this.updateInput(this.color);
            this.updateData(this.color);
        }
        this.disabled = false;
        var $picker = this.picker = $(this.options.template);
        if (this.options.customClass) {
            $picker.addClass(this.options.customClass);
        }
        if (this.options.inline) {
            $picker.addClass("colorpicker-inline colorpicker-visible");
        } else {
            $picker.addClass("colorpicker-hidden");
        }
        if (this.options.horizontal) {
            $picker.addClass("colorpicker-horizontal");
        }
        if ([ "rgba", "hsla", "alias" ].indexOf(this.format) !== -1 || this.options.format === false || this.getValue() === "transparent") {
            $picker.addClass("colorpicker-with-alpha");
        }
        if (this.options.align === "right") {
            $picker.addClass("colorpicker-right");
        }
        if (this.options.inline === true) {
            $picker.addClass("colorpicker-no-arrow");
        }
        if (this.options.colorSelectors) {
            var colorpicker = this, selectorsContainer = colorpicker.picker.find(".colorpicker-selectors");
            if (selectorsContainer.length > 0) {
                $.each(this.options.colorSelectors, function(name, color) {
                    var $btn = $("<i />").addClass("colorpicker-selectors-color").css("background-color", color).data("class", name).data("alias", name);
                    $btn.on("mousedown.colorpicker touchstart.colorpicker", function(event) {
                        event.preventDefault();
                        colorpicker.setValue(colorpicker.format === "alias" ? $(this).data("alias") : $(this).css("background-color"));
                    });
                    selectorsContainer.append($btn);
                });
                selectorsContainer.show().addClass("colorpicker-visible");
            }
        }
        $picker.on("mousedown.colorpicker touchstart.colorpicker", $.proxy(function(e) {
            if (e.target === e.currentTarget) {
                e.preventDefault();
            }
        }, this));
        $picker.find(".colorpicker-saturation, .colorpicker-hue, .colorpicker-alpha").on("mousedown.colorpicker touchstart.colorpicker", $.proxy(this.mousedown, this));
        $picker.appendTo(this.container ? this.container : $("body"));
        if (this.input !== false) {
            this.input.on({
                "keyup.colorpicker": $.proxy(this.keyup, this)
            });
            this.input.on({
                "input.colorpicker": $.proxy(this.change, this)
            });
            if (this.component === false) {
                this.element.on({
                    "focus.colorpicker": $.proxy(this.show, this)
                });
            }
            if (this.options.inline === false) {
                this.element.on({
                    "focusout.colorpicker": $.proxy(this.hide, this)
                });
            }
        }
        if (this.component !== false) {
            this.component.on({
                "click.colorpicker": $.proxy(this.show, this)
            });
        }
        if (this.input === false && this.component === false) {
            this.element.on({
                "click.colorpicker": $.proxy(this.show, this)
            });
        }
        if (this.input !== false && this.component !== false && this.input.attr("type") === "color") {
            this.input.on({
                "click.colorpicker": $.proxy(this.show, this),
                "focus.colorpicker": $.proxy(this.show, this)
            });
        }
        this.update();
        $($.proxy(function() {
            this.element.trigger("create");
        }, this));
    };
    Colorpicker.Color = Color;
    Colorpicker.prototype = {
        constructor: Colorpicker,
        destroy: function() {
            this.picker.remove();
            this.element.removeData("colorpicker", "color").off(".colorpicker");
            if (this.input !== false) {
                this.input.off(".colorpicker");
            }
            if (this.component !== false) {
                this.component.off(".colorpicker");
            }
            this.element.removeClass("colorpicker-element");
            this.element.trigger({
                type: "destroy"
            });
        },
        reposition: function() {
            if (this.options.inline !== false || this.options.container) {
                return false;
            }
            var type = this.container && this.container[0] !== window.document.body ? "position" : "offset";
            var element = this.component || this.element;
            var offset = element[type]();
            if (this.options.align === "right") {
                offset.left -= this.picker.outerWidth() - element.outerWidth();
            }
            this.picker.css({
                top: offset.top + element.outerHeight(),
                left: offset.left
            });
        },
        show: function(e) {
            if (this.isDisabled()) {
                return;
            }
            this.picker.addClass("colorpicker-visible").removeClass("colorpicker-hidden");
            this.reposition();
            $(window).on("resize.colorpicker", $.proxy(this.reposition, this));
            if (e && (!this.hasInput() || this.input.attr("type") === "color")) {
                if (e.stopPropagation && e.preventDefault) {
                    e.stopPropagation();
                    e.preventDefault();
                }
            }
            if ((this.component || !this.input) && this.options.inline === false) {
                $(window.document).on({
                    "mousedown.colorpicker": $.proxy(this.hide, this)
                });
            }
            this.element.trigger({
                type: "showPicker",
                color: this.color
            });
        },
        hide: function(e) {
            if (typeof e !== "undefined" && e.target) {
                if ($(e.currentTarget).parents(".colorpicker").length > 0 || $(e.target).parents(".colorpicker").length > 0) {
                    return false;
                }
            }
            this.picker.addClass("colorpicker-hidden").removeClass("colorpicker-visible");
            $(window).off("resize.colorpicker", this.reposition);
            $(window.document).off({
                "mousedown.colorpicker": this.hide
            });
            this.update();
            this.element.trigger({
                type: "hidePicker",
                color: this.color
            });
        },
        updateData: function(val) {
            val = val || this.color.toString(false, this.format);
            this.element.data("color", val);
            return val;
        },
        updateInput: function(val) {
            val = val || this.color.toString(false, this.format);
            if (this.input !== false) {
                this.input.prop("value", val);
                this.input.trigger("change");
            }
            return val;
        },
        updatePicker: function(val) {
            if (typeof val !== "undefined") {
                this.color = this.createColor(val);
            }
            var sl = this.options.horizontal === false ? this.options.sliders : this.options.slidersHorz;
            var icns = this.picker.find("i");
            if (icns.length === 0) {
                return;
            }
            if (this.options.horizontal === false) {
                sl = this.options.sliders;
                icns.eq(1).css("top", sl.hue.maxTop * (1 - this.color.value.h)).end().eq(2).css("top", sl.alpha.maxTop * (1 - this.color.value.a));
            } else {
                sl = this.options.slidersHorz;
                icns.eq(1).css("left", sl.hue.maxLeft * (1 - this.color.value.h)).end().eq(2).css("left", sl.alpha.maxLeft * (1 - this.color.value.a));
            }
            icns.eq(0).css({
                top: sl.saturation.maxTop - this.color.value.b * sl.saturation.maxTop,
                left: this.color.value.s * sl.saturation.maxLeft
            });
            this.picker.find(".colorpicker-saturation").css("backgroundColor", this.color.toHex(true, this.color.value.h, 1, 1, 1));
            this.picker.find(".colorpicker-alpha").css("backgroundColor", this.color.toHex(true));
            this.picker.find(".colorpicker-color, .colorpicker-color div").css("backgroundColor", this.color.toString(true, this.format));
            return val;
        },
        updateComponent: function(val) {
            var color;
            if (typeof val !== "undefined") {
                color = this.createColor(val);
            } else {
                color = this.color;
            }
            if (this.component !== false) {
                var icn = this.component.find("i").eq(0);
                if (icn.length > 0) {
                    icn.css({
                        backgroundColor: color.toString(true, this.format)
                    });
                } else {
                    this.component.css({
                        backgroundColor: color.toString(true, this.format)
                    });
                }
            }
            return color.toString(false, this.format);
        },
        update: function(force) {
            var val;
            if (this.getValue(false) !== false || force === true) {
                val = this.updateComponent();
                this.updateInput(val);
                this.updateData(val);
                this.updatePicker();
            }
            return val;
        },
        setValue: function(val) {
            this.color = this.createColor(val);
            this.update(true);
            this.element.trigger({
                type: "changeColor",
                color: this.color,
                value: val
            });
        },
        createColor: function(val) {
            return new Color(val ? val : null, this.options.colorSelectors, this.options.fallbackColor ? this.options.fallbackColor : this.color, this.options.fallbackFormat, this.options.hexNumberSignPrefix);
        },
        getValue: function(defaultValue) {
            defaultValue = typeof defaultValue === "undefined" ? this.options.fallbackColor : defaultValue;
            var val;
            if (this.hasInput()) {
                val = this.input.val();
            } else {
                val = this.element.data("color");
            }
            if (val === undefined || val === "" || val === null) {
                val = defaultValue;
            }
            return val;
        },
        hasInput: function() {
            return this.input !== false;
        },
        isDisabled: function() {
            return this.disabled;
        },
        disable: function() {
            if (this.hasInput()) {
                this.input.prop("disabled", true);
            }
            this.disabled = true;
            this.element.trigger({
                type: "disable",
                color: this.color,
                value: this.getValue()
            });
            return true;
        },
        enable: function() {
            if (this.hasInput()) {
                this.input.prop("disabled", false);
            }
            this.disabled = false;
            this.element.trigger({
                type: "enable",
                color: this.color,
                value: this.getValue()
            });
            return true;
        },
        currentSlider: null,
        mousePointer: {
            left: 0,
            top: 0
        },
        mousedown: function(e) {
            if (!e.pageX && !e.pageY && e.originalEvent && e.originalEvent.touches) {
                e.pageX = e.originalEvent.touches[0].pageX;
                e.pageY = e.originalEvent.touches[0].pageY;
            }
            e.stopPropagation();
            e.preventDefault();
            var target = $(e.target);
            var zone = target.closest("div");
            var sl = this.options.horizontal ? this.options.slidersHorz : this.options.sliders;
            if (!zone.is(".colorpicker")) {
                if (zone.is(".colorpicker-saturation")) {
                    this.currentSlider = $.extend({}, sl.saturation);
                } else if (zone.is(".colorpicker-hue")) {
                    this.currentSlider = $.extend({}, sl.hue);
                } else if (zone.is(".colorpicker-alpha")) {
                    this.currentSlider = $.extend({}, sl.alpha);
                } else {
                    return false;
                }
                var offset = zone.offset();
                this.currentSlider.guide = zone.find("i")[0].style;
                this.currentSlider.left = e.pageX - offset.left;
                this.currentSlider.top = e.pageY - offset.top;
                this.mousePointer = {
                    left: e.pageX,
                    top: e.pageY
                };
                $(window.document).on({
                    "mousemove.colorpicker": $.proxy(this.mousemove, this),
                    "touchmove.colorpicker": $.proxy(this.mousemove, this),
                    "mouseup.colorpicker": $.proxy(this.mouseup, this),
                    "touchend.colorpicker": $.proxy(this.mouseup, this)
                }).trigger("mousemove");
            }
            return false;
        },
        mousemove: function(e) {
            if (!e.pageX && !e.pageY && e.originalEvent && e.originalEvent.touches) {
                e.pageX = e.originalEvent.touches[0].pageX;
                e.pageY = e.originalEvent.touches[0].pageY;
            }
            e.stopPropagation();
            e.preventDefault();
            var left = Math.max(0, Math.min(this.currentSlider.maxLeft, this.currentSlider.left + ((e.pageX || this.mousePointer.left) - this.mousePointer.left)));
            var top = Math.max(0, Math.min(this.currentSlider.maxTop, this.currentSlider.top + ((e.pageY || this.mousePointer.top) - this.mousePointer.top)));
            this.currentSlider.guide.left = left + "px";
            this.currentSlider.guide.top = top + "px";
            if (this.currentSlider.callLeft) {
                this.color[this.currentSlider.callLeft].call(this.color, left / this.currentSlider.maxLeft);
            }
            if (this.currentSlider.callTop) {
                this.color[this.currentSlider.callTop].call(this.color, top / this.currentSlider.maxTop);
            }
            if (this.options.format === false && (this.currentSlider.callTop === "setAlpha" || this.currentSlider.callLeft === "setAlpha")) {
                if (this.color.value.a !== 1) {
                    this.format = "rgba";
                    this.color.origFormat = "rgba";
                } else {
                    this.format = "hex";
                    this.color.origFormat = "hex";
                }
            }
            this.update(true);
            this.element.trigger({
                type: "changeColor",
                color: this.color
            });
            return false;
        },
        mouseup: function(e) {
            e.stopPropagation();
            e.preventDefault();
            $(window.document).off({
                "mousemove.colorpicker": this.mousemove,
                "touchmove.colorpicker": this.mousemove,
                "mouseup.colorpicker": this.mouseup,
                "touchend.colorpicker": this.mouseup
            });
            return false;
        },
        change: function(e) {
            this.color = this.createColor(this.input.val());
            if (this.color.origFormat && this.options.format === false) {
                this.format = this.color.origFormat;
            }
            if (this.getValue(false) !== false) {
                this.updateData();
                this.updateComponent();
                this.updatePicker();
            }
            this.element.trigger({
                type: "changeColor",
                color: this.color,
                value: this.input.val()
            });
        },
        keyup: function(e) {
            if (e.keyCode === 38) {
                if (this.color.value.a < 1) {
                    this.color.value.a = Math.round((this.color.value.a + .01) * 100) / 100;
                }
                this.update(true);
            } else if (e.keyCode === 40) {
                if (this.color.value.a > 0) {
                    this.color.value.a = Math.round((this.color.value.a - .01) * 100) / 100;
                }
                this.update(true);
            }
            this.element.trigger({
                type: "changeColor",
                color: this.color,
                value: this.input.val()
            });
        }
    };
    $.colorpicker = Colorpicker;
    $.fn.colorpicker = function(option) {
        var apiArgs = Array.prototype.slice.call(arguments, 1), isSingleElement = this.length === 1, returnValue = null;
        var $jq = this.each(function() {
            var $this = $(this), inst = $this.data("colorpicker"), options = typeof option === "object" ? option : {};
            if (!inst) {
                inst = new Colorpicker(this, options);
                $this.data("colorpicker", inst);
            }
            if (typeof option === "string") {
                if ($.isFunction(inst[option])) {
                    returnValue = inst[option].apply(inst, apiArgs);
                } else {
                    if (apiArgs.length) {
                        inst[option] = apiArgs[0];
                    }
                    returnValue = inst[option];
                }
            } else {
                returnValue = $this;
            }
        });
        return isSingleElement ? returnValue : $jq;
    };
    $.fn.colorpicker.constructor = Colorpicker;
});

!function() {
    var d3 = {
        version: "3.5.5"
    };
    var d3_arraySlice = [].slice, d3_array = function(list) {
        return d3_arraySlice.call(list);
    };
    var d3_document = this.document;
    function d3_documentElement(node) {
        return node && (node.ownerDocument || node.document || node).documentElement;
    }
    function d3_window(node) {
        return node && (node.ownerDocument && node.ownerDocument.defaultView || node.document && node || node.defaultView);
    }
    if (d3_document) {
        try {
            d3_array(d3_document.documentElement.childNodes)[0].nodeType;
        } catch (e) {
            d3_array = function(list) {
                var i = list.length, array = new Array(i);
                while (i--) array[i] = list[i];
                return array;
            };
        }
    }
    if (!Date.now) Date.now = function() {
        return +new Date();
    };
    if (d3_document) {
        try {
            d3_document.createElement("DIV").style.setProperty("opacity", 0, "");
        } catch (error) {
            var d3_element_prototype = this.Element.prototype, d3_element_setAttribute = d3_element_prototype.setAttribute, d3_element_setAttributeNS = d3_element_prototype.setAttributeNS, d3_style_prototype = this.CSSStyleDeclaration.prototype, d3_style_setProperty = d3_style_prototype.setProperty;
            d3_element_prototype.setAttribute = function(name, value) {
                d3_element_setAttribute.call(this, name, value + "");
            };
            d3_element_prototype.setAttributeNS = function(space, local, value) {
                d3_element_setAttributeNS.call(this, space, local, value + "");
            };
            d3_style_prototype.setProperty = function(name, value, priority) {
                d3_style_setProperty.call(this, name, value + "", priority);
            };
        }
    }
    d3.ascending = d3_ascending;
    function d3_ascending(a, b) {
        return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
    }
    d3.descending = function(a, b) {
        return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
    };
    d3.min = function(array, f) {
        var i = -1, n = array.length, a, b;
        if (arguments.length === 1) {
            while (++i < n) if ((b = array[i]) != null && b >= b) {
                a = b;
                break;
            }
            while (++i < n) if ((b = array[i]) != null && a > b) a = b;
        } else {
            while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) {
                a = b;
                break;
            }
            while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b;
        }
        return a;
    };
    d3.max = function(array, f) {
        var i = -1, n = array.length, a, b;
        if (arguments.length === 1) {
            while (++i < n) if ((b = array[i]) != null && b >= b) {
                a = b;
                break;
            }
            while (++i < n) if ((b = array[i]) != null && b > a) a = b;
        } else {
            while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) {
                a = b;
                break;
            }
            while (++i < n) if ((b = f.call(array, array[i], i)) != null && b > a) a = b;
        }
        return a;
    };
    d3.extent = function(array, f) {
        var i = -1, n = array.length, a, b, c;
        if (arguments.length === 1) {
            while (++i < n) if ((b = array[i]) != null && b >= b) {
                a = c = b;
                break;
            }
            while (++i < n) if ((b = array[i]) != null) {
                if (a > b) a = b;
                if (c < b) c = b;
            }
        } else {
            while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) {
                a = c = b;
                break;
            }
            while (++i < n) if ((b = f.call(array, array[i], i)) != null) {
                if (a > b) a = b;
                if (c < b) c = b;
            }
        }
        return [ a, c ];
    };
    function d3_number(x) {
        return x === null ? NaN : +x;
    }
    function d3_numeric(x) {
        return !isNaN(x);
    }
    d3.sum = function(array, f) {
        var s = 0, n = array.length, a, i = -1;
        if (arguments.length === 1) {
            while (++i < n) if (d3_numeric(a = +array[i])) s += a;
        } else {
            while (++i < n) if (d3_numeric(a = +f.call(array, array[i], i))) s += a;
        }
        return s;
    };
    d3.mean = function(array, f) {
        var s = 0, n = array.length, a, i = -1, j = n;
        if (arguments.length === 1) {
            while (++i < n) if (d3_numeric(a = d3_number(array[i]))) s += a; else --j;
        } else {
            while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) s += a; else --j;
        }
        if (j) return s / j;
    };
    d3.quantile = function(values, p) {
        var H = (values.length - 1) * p + 1, h = Math.floor(H), v = +values[h - 1], e = H - h;
        return e ? v + e * (values[h] - v) : v;
    };
    d3.median = function(array, f) {
        var numbers = [], n = array.length, a, i = -1;
        if (arguments.length === 1) {
            while (++i < n) if (d3_numeric(a = d3_number(array[i]))) numbers.push(a);
        } else {
            while (++i < n) if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) numbers.push(a);
        }
        if (numbers.length) return d3.quantile(numbers.sort(d3_ascending), .5);
    };
    d3.variance = function(array, f) {
        var n = array.length, m = 0, a, d, s = 0, i = -1, j = 0;
        if (arguments.length === 1) {
            while (++i < n) {
                if (d3_numeric(a = d3_number(array[i]))) {
                    d = a - m;
                    m += d / ++j;
                    s += d * (a - m);
                }
            }
        } else {
            while (++i < n) {
                if (d3_numeric(a = d3_number(f.call(array, array[i], i)))) {
                    d = a - m;
                    m += d / ++j;
                    s += d * (a - m);
                }
            }
        }
        if (j > 1) return s / (j - 1);
    };
    d3.deviation = function() {
        var v = d3.variance.apply(this, arguments);
        return v ? Math.sqrt(v) : v;
    };
    function d3_bisector(compare) {
        return {
            left: function(a, x, lo, hi) {
                if (arguments.length < 3) lo = 0;
                if (arguments.length < 4) hi = a.length;
                while (lo < hi) {
                    var mid = lo + hi >>> 1;
                    if (compare(a[mid], x) < 0) lo = mid + 1; else hi = mid;
                }
                return lo;
            },
            right: function(a, x, lo, hi) {
                if (arguments.length < 3) lo = 0;
                if (arguments.length < 4) hi = a.length;
                while (lo < hi) {
                    var mid = lo + hi >>> 1;
                    if (compare(a[mid], x) > 0) hi = mid; else lo = mid + 1;
                }
                return lo;
            }
        };
    }
    var d3_bisect = d3_bisector(d3_ascending);
    d3.bisectLeft = d3_bisect.left;
    d3.bisect = d3.bisectRight = d3_bisect.right;
    d3.bisector = function(f) {
        return d3_bisector(f.length === 1 ? function(d, x) {
            return d3_ascending(f(d), x);
        } : f);
    };
    d3.shuffle = function(array, i0, i1) {
        if ((m = arguments.length) < 3) {
            i1 = array.length;
            if (m < 2) i0 = 0;
        }
        var m = i1 - i0, t, i;
        while (m) {
            i = Math.random() * m-- | 0;
            t = array[m + i0], array[m + i0] = array[i + i0], array[i + i0] = t;
        }
        return array;
    };
    d3.permute = function(array, indexes) {
        var i = indexes.length, permutes = new Array(i);
        while (i--) permutes[i] = array[indexes[i]];
        return permutes;
    };
    d3.pairs = function(array) {
        var i = 0, n = array.length - 1, p0, p1 = array[0], pairs = new Array(n < 0 ? 0 : n);
        while (i < n) pairs[i] = [ p0 = p1, p1 = array[++i] ];
        return pairs;
    };
    d3.zip = function() {
        if (!(n = arguments.length)) return [];
        for (var i = -1, m = d3.min(arguments, d3_zipLength), zips = new Array(m); ++i < m; ) {
            for (var j = -1, n, zip = zips[i] = new Array(n); ++j < n; ) {
                zip[j] = arguments[j][i];
            }
        }
        return zips;
    };
    function d3_zipLength(d) {
        return d.length;
    }
    d3.transpose = function(matrix) {
        return d3.zip.apply(d3, matrix);
    };
    d3.keys = function(map) {
        var keys = [];
        for (var key in map) keys.push(key);
        return keys;
    };
    d3.values = function(map) {
        var values = [];
        for (var key in map) values.push(map[key]);
        return values;
    };
    d3.entries = function(map) {
        var entries = [];
        for (var key in map) entries.push({
            key: key,
            value: map[key]
        });
        return entries;
    };
    d3.merge = function(arrays) {
        var n = arrays.length, m, i = -1, j = 0, merged, array;
        while (++i < n) j += arrays[i].length;
        merged = new Array(j);
        while (--n >= 0) {
            array = arrays[n];
            m = array.length;
            while (--m >= 0) {
                merged[--j] = array[m];
            }
        }
        return merged;
    };
    var abs = Math.abs;
    d3.range = function(start, stop, step) {
        if (arguments.length < 3) {
            step = 1;
            if (arguments.length < 2) {
                stop = start;
                start = 0;
            }
        }
        if ((stop - start) / step === Infinity) throw new Error("infinite range");
        var range = [], k = d3_range_integerScale(abs(step)), i = -1, j;
        start *= k, stop *= k, step *= k;
        if (step < 0) while ((j = start + step * ++i) > stop) range.push(j / k); else while ((j = start + step * ++i) < stop) range.push(j / k);
        return range;
    };
    function d3_range_integerScale(x) {
        var k = 1;
        while (x * k % 1) k *= 10;
        return k;
    }
    function d3_class(ctor, properties) {
        for (var key in properties) {
            Object.defineProperty(ctor.prototype, key, {
                value: properties[key],
                enumerable: false
            });
        }
    }
    d3.map = function(object, f) {
        var map = new d3_Map();
        if (object instanceof d3_Map) {
            object.forEach(function(key, value) {
                map.set(key, value);
            });
        } else if (Array.isArray(object)) {
            var i = -1, n = object.length, o;
            if (arguments.length === 1) while (++i < n) map.set(i, object[i]); else while (++i < n) map.set(f.call(object, o = object[i], i), o);
        } else {
            for (var key in object) map.set(key, object[key]);
        }
        return map;
    };
    function d3_Map() {
        this._ = Object.create(null);
    }
    var d3_map_proto = "__proto__", d3_map_zero = "\0";
    d3_class(d3_Map, {
        has: d3_map_has,
        get: function(key) {
            return this._[d3_map_escape(key)];
        },
        set: function(key, value) {
            return this._[d3_map_escape(key)] = value;
        },
        remove: d3_map_remove,
        keys: d3_map_keys,
        values: function() {
            var values = [];
            for (var key in this._) values.push(this._[key]);
            return values;
        },
        entries: function() {
            var entries = [];
            for (var key in this._) entries.push({
                key: d3_map_unescape(key),
                value: this._[key]
            });
            return entries;
        },
        size: d3_map_size,
        empty: d3_map_empty,
        forEach: function(f) {
            for (var key in this._) f.call(this, d3_map_unescape(key), this._[key]);
        }
    });
    function d3_map_escape(key) {
        return (key += "") === d3_map_proto || key[0] === d3_map_zero ? d3_map_zero + key : key;
    }
    function d3_map_unescape(key) {
        return (key += "")[0] === d3_map_zero ? key.slice(1) : key;
    }
    function d3_map_has(key) {
        return d3_map_escape(key) in this._;
    }
    function d3_map_remove(key) {
        return (key = d3_map_escape(key)) in this._ && delete this._[key];
    }
    function d3_map_keys() {
        var keys = [];
        for (var key in this._) keys.push(d3_map_unescape(key));
        return keys;
    }
    function d3_map_size() {
        var size = 0;
        for (var key in this._) ++size;
        return size;
    }
    function d3_map_empty() {
        for (var key in this._) return false;
        return true;
    }
    d3.nest = function() {
        var nest = {}, keys = [], sortKeys = [], sortValues, rollup;
        function map(mapType, array, depth) {
            if (depth >= keys.length) return rollup ? rollup.call(nest, array) : sortValues ? array.sort(sortValues) : array;
            var i = -1, n = array.length, key = keys[depth++], keyValue, object, setter, valuesByKey = new d3_Map(), values;
            while (++i < n) {
                if (values = valuesByKey.get(keyValue = key(object = array[i]))) {
                    values.push(object);
                } else {
                    valuesByKey.set(keyValue, [ object ]);
                }
            }
            if (mapType) {
                object = mapType();
                setter = function(keyValue, values) {
                    object.set(keyValue, map(mapType, values, depth));
                };
            } else {
                object = {};
                setter = function(keyValue, values) {
                    object[keyValue] = map(mapType, values, depth);
                };
            }
            valuesByKey.forEach(setter);
            return object;
        }
        function entries(map, depth) {
            if (depth >= keys.length) return map;
            var array = [], sortKey = sortKeys[depth++];
            map.forEach(function(key, keyMap) {
                array.push({
                    key: key,
                    values: entries(keyMap, depth)
                });
            });
            return sortKey ? array.sort(function(a, b) {
                return sortKey(a.key, b.key);
            }) : array;
        }
        nest.map = function(array, mapType) {
            return map(mapType, array, 0);
        };
        nest.entries = function(array) {
            return entries(map(d3.map, array, 0), 0);
        };
        nest.key = function(d) {
            keys.push(d);
            return nest;
        };
        nest.sortKeys = function(order) {
            sortKeys[keys.length - 1] = order;
            return nest;
        };
        nest.sortValues = function(order) {
            sortValues = order;
            return nest;
        };
        nest.rollup = function(f) {
            rollup = f;
            return nest;
        };
        return nest;
    };
    d3.set = function(array) {
        var set = new d3_Set();
        if (array) for (var i = 0, n = array.length; i < n; ++i) set.add(array[i]);
        return set;
    };
    function d3_Set() {
        this._ = Object.create(null);
    }
    d3_class(d3_Set, {
        has: d3_map_has,
        add: function(key) {
            this._[d3_map_escape(key += "")] = true;
            return key;
        },
        remove: d3_map_remove,
        values: d3_map_keys,
        size: d3_map_size,
        empty: d3_map_empty,
        forEach: function(f) {
            for (var key in this._) f.call(this, d3_map_unescape(key));
        }
    });
    d3.behavior = {};
    function d3_identity(d) {
        return d;
    }
    d3.rebind = function(target, source) {
        var i = 1, n = arguments.length, method;
        while (++i < n) target[method = arguments[i]] = d3_rebind(target, source, source[method]);
        return target;
    };
    function d3_rebind(target, source, method) {
        return function() {
            var value = method.apply(source, arguments);
            return value === source ? target : value;
        };
    }
    function d3_vendorSymbol(object, name) {
        if (name in object) return name;
        name = name.charAt(0).toUpperCase() + name.slice(1);
        for (var i = 0, n = d3_vendorPrefixes.length; i < n; ++i) {
            var prefixName = d3_vendorPrefixes[i] + name;
            if (prefixName in object) return prefixName;
        }
    }
    var d3_vendorPrefixes = [ "webkit", "ms", "moz", "Moz", "o", "O" ];
    function d3_noop() {}
    d3.dispatch = function() {
        var dispatch = new d3_dispatch(), i = -1, n = arguments.length;
        while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
        return dispatch;
    };
    function d3_dispatch() {}
    d3_dispatch.prototype.on = function(type, listener) {
        var i = type.indexOf("."), name = "";
        if (i >= 0) {
            name = type.slice(i + 1);
            type = type.slice(0, i);
        }
        if (type) return arguments.length < 2 ? this[type].on(name) : this[type].on(name, listener);
        if (arguments.length === 2) {
            if (listener == null) for (type in this) {
                if (this.hasOwnProperty(type)) this[type].on(name, null);
            }
            return this;
        }
    };
    function d3_dispatch_event(dispatch) {
        var listeners = [], listenerByName = new d3_Map();
        function event() {
            var z = listeners, i = -1, n = z.length, l;
            while (++i < n) if (l = z[i].on) l.apply(this, arguments);
            return dispatch;
        }
        event.on = function(name, listener) {
            var l = listenerByName.get(name), i;
            if (arguments.length < 2) return l && l.on;
            if (l) {
                l.on = null;
                listeners = listeners.slice(0, i = listeners.indexOf(l)).concat(listeners.slice(i + 1));
                listenerByName.remove(name);
            }
            if (listener) listeners.push(listenerByName.set(name, {
                on: listener
            }));
            return dispatch;
        };
        return event;
    }
    d3.event = null;
    function d3_eventPreventDefault() {
        d3.event.preventDefault();
    }
    function d3_eventSource() {
        var e = d3.event, s;
        while (s = e.sourceEvent) e = s;
        return e;
    }
    function d3_eventDispatch(target) {
        var dispatch = new d3_dispatch(), i = 0, n = arguments.length;
        while (++i < n) dispatch[arguments[i]] = d3_dispatch_event(dispatch);
        dispatch.of = function(thiz, argumentz) {
            return function(e1) {
                try {
                    var e0 = e1.sourceEvent = d3.event;
                    e1.target = target;
                    d3.event = e1;
                    dispatch[e1.type].apply(thiz, argumentz);
                } finally {
                    d3.event = e0;
                }
            };
        };
        return dispatch;
    }
    d3.requote = function(s) {
        return s.replace(d3_requote_re, "\\$&");
    };
    var d3_requote_re = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
    var d3_subclass = {}.__proto__ ? function(object, prototype) {
        object.__proto__ = prototype;
    } : function(object, prototype) {
        for (var property in prototype) object[property] = prototype[property];
    };
    function d3_selection(groups) {
        d3_subclass(groups, d3_selectionPrototype);
        return groups;
    }
    var d3_select = function(s, n) {
        return n.querySelector(s);
    }, d3_selectAll = function(s, n) {
        return n.querySelectorAll(s);
    }, d3_selectMatches = function(n, s) {
        var d3_selectMatcher = n.matches || n[d3_vendorSymbol(n, "matchesSelector")];
        d3_selectMatches = function(n, s) {
            return d3_selectMatcher.call(n, s);
        };
        return d3_selectMatches(n, s);
    };
    if (typeof Sizzle === "function") {
        d3_select = function(s, n) {
            return Sizzle(s, n)[0] || null;
        };
        d3_selectAll = Sizzle;
        d3_selectMatches = Sizzle.matchesSelector;
    }
    d3.selection = function() {
        return d3.select(d3_document.documentElement);
    };
    var d3_selectionPrototype = d3.selection.prototype = [];
    d3_selectionPrototype.select = function(selector) {
        var subgroups = [], subgroup, subnode, group, node;
        selector = d3_selection_selector(selector);
        for (var j = -1, m = this.length; ++j < m; ) {
            subgroups.push(subgroup = []);
            subgroup.parentNode = (group = this[j]).parentNode;
            for (var i = -1, n = group.length; ++i < n; ) {
                if (node = group[i]) {
                    subgroup.push(subnode = selector.call(node, node.__data__, i, j));
                    if (subnode && "__data__" in node) subnode.__data__ = node.__data__;
                } else {
                    subgroup.push(null);
                }
            }
        }
        return d3_selection(subgroups);
    };
    function d3_selection_selector(selector) {
        return typeof selector === "function" ? selector : function() {
            return d3_select(selector, this);
        };
    }
    d3_selectionPrototype.selectAll = function(selector) {
        var subgroups = [], subgroup, node;
        selector = d3_selection_selectorAll(selector);
        for (var j = -1, m = this.length; ++j < m; ) {
            for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
                if (node = group[i]) {
                    subgroups.push(subgroup = d3_array(selector.call(node, node.__data__, i, j)));
                    subgroup.parentNode = node;
                }
            }
        }
        return d3_selection(subgroups);
    };
    function d3_selection_selectorAll(selector) {
        return typeof selector === "function" ? selector : function() {
            return d3_selectAll(selector, this);
        };
    }
    var d3_nsPrefix = {
        svg: "http://www.w3.org/2000/svg",
        xhtml: "http://www.w3.org/1999/xhtml",
        xlink: "http://www.w3.org/1999/xlink",
        xml: "http://www.w3.org/XML/1998/namespace",
        xmlns: "http://www.w3.org/2000/xmlns/"
    };
    d3.ns = {
        prefix: d3_nsPrefix,
        qualify: function(name) {
            var i = name.indexOf(":"), prefix = name;
            if (i >= 0) {
                prefix = name.slice(0, i);
                name = name.slice(i + 1);
            }
            return d3_nsPrefix.hasOwnProperty(prefix) ? {
                space: d3_nsPrefix[prefix],
                local: name
            } : name;
        }
    };
    d3_selectionPrototype.attr = function(name, value) {
        if (arguments.length < 2) {
            if (typeof name === "string") {
                var node = this.node();
                name = d3.ns.qualify(name);
                return name.local ? node.getAttributeNS(name.space, name.local) : node.getAttribute(name);
            }
            for (value in name) this.each(d3_selection_attr(value, name[value]));
            return this;
        }
        return this.each(d3_selection_attr(name, value));
    };
    function d3_selection_attr(name, value) {
        name = d3.ns.qualify(name);
        function attrNull() {
            this.removeAttribute(name);
        }
        function attrNullNS() {
            this.removeAttributeNS(name.space, name.local);
        }
        function attrConstant() {
            this.setAttribute(name, value);
        }
        function attrConstantNS() {
            this.setAttributeNS(name.space, name.local, value);
        }
        function attrFunction() {
            var x = value.apply(this, arguments);
            if (x == null) this.removeAttribute(name); else this.setAttribute(name, x);
        }
        function attrFunctionNS() {
            var x = value.apply(this, arguments);
            if (x == null) this.removeAttributeNS(name.space, name.local); else this.setAttributeNS(name.space, name.local, x);
        }
        return value == null ? name.local ? attrNullNS : attrNull : typeof value === "function" ? name.local ? attrFunctionNS : attrFunction : name.local ? attrConstantNS : attrConstant;
    }
    function d3_collapse(s) {
        return s.trim().replace(/\s+/g, " ");
    }
    d3_selectionPrototype.classed = function(name, value) {
        if (arguments.length < 2) {
            if (typeof name === "string") {
                var node = this.node(), n = (name = d3_selection_classes(name)).length, i = -1;
                if (value = node.classList) {
                    while (++i < n) if (!value.contains(name[i])) return false;
                } else {
                    value = node.getAttribute("class");
                    while (++i < n) if (!d3_selection_classedRe(name[i]).test(value)) return false;
                }
                return true;
            }
            for (value in name) this.each(d3_selection_classed(value, name[value]));
            return this;
        }
        return this.each(d3_selection_classed(name, value));
    };
    function d3_selection_classedRe(name) {
        return new RegExp("(?:^|\\s+)" + d3.requote(name) + "(?:\\s+|$)", "g");
    }
    function d3_selection_classes(name) {
        return (name + "").trim().split(/^|\s+/);
    }
    function d3_selection_classed(name, value) {
        name = d3_selection_classes(name).map(d3_selection_classedName);
        var n = name.length;
        function classedConstant() {
            var i = -1;
            while (++i < n) name[i](this, value);
        }
        function classedFunction() {
            var i = -1, x = value.apply(this, arguments);
            while (++i < n) name[i](this, x);
        }
        return typeof value === "function" ? classedFunction : classedConstant;
    }
    function d3_selection_classedName(name) {
        var re = d3_selection_classedRe(name);
        return function(node, value) {
            if (c = node.classList) return value ? c.add(name) : c.remove(name);
            var c = node.getAttribute("class") || "";
            if (value) {
                re.lastIndex = 0;
                if (!re.test(c)) node.setAttribute("class", d3_collapse(c + " " + name));
            } else {
                node.setAttribute("class", d3_collapse(c.replace(re, " ")));
            }
        };
    }
    d3_selectionPrototype.style = function(name, value, priority) {
        var n = arguments.length;
        if (n < 3) {
            if (typeof name !== "string") {
                if (n < 2) value = "";
                for (priority in name) this.each(d3_selection_style(priority, name[priority], value));
                return this;
            }
            if (n < 2) {
                var node = this.node();
                return d3_window(node).getComputedStyle(node, null).getPropertyValue(name);
            }
            priority = "";
        }
        return this.each(d3_selection_style(name, value, priority));
    };
    function d3_selection_style(name, value, priority) {
        function styleNull() {
            this.style.removeProperty(name);
        }
        function styleConstant() {
            this.style.setProperty(name, value, priority);
        }
        function styleFunction() {
            var x = value.apply(this, arguments);
            if (x == null) this.style.removeProperty(name); else this.style.setProperty(name, x, priority);
        }
        return value == null ? styleNull : typeof value === "function" ? styleFunction : styleConstant;
    }
    d3_selectionPrototype.property = function(name, value) {
        if (arguments.length < 2) {
            if (typeof name === "string") return this.node()[name];
            for (value in name) this.each(d3_selection_property(value, name[value]));
            return this;
        }
        return this.each(d3_selection_property(name, value));
    };
    function d3_selection_property(name, value) {
        function propertyNull() {
            delete this[name];
        }
        function propertyConstant() {
            this[name] = value;
        }
        function propertyFunction() {
            var x = value.apply(this, arguments);
            if (x == null) delete this[name]; else this[name] = x;
        }
        return value == null ? propertyNull : typeof value === "function" ? propertyFunction : propertyConstant;
    }
    d3_selectionPrototype.text = function(value) {
        return arguments.length ? this.each(typeof value === "function" ? function() {
            var v = value.apply(this, arguments);
            this.textContent = v == null ? "" : v;
        } : value == null ? function() {
            this.textContent = "";
        } : function() {
            this.textContent = value;
        }) : this.node().textContent;
    };
    d3_selectionPrototype.html = function(value) {
        return arguments.length ? this.each(typeof value === "function" ? function() {
            var v = value.apply(this, arguments);
            this.innerHTML = v == null ? "" : v;
        } : value == null ? function() {
            this.innerHTML = "";
        } : function() {
            this.innerHTML = value;
        }) : this.node().innerHTML;
    };
    d3_selectionPrototype.append = function(name) {
        name = d3_selection_creator(name);
        return this.select(function() {
            return this.appendChild(name.apply(this, arguments));
        });
    };
    function d3_selection_creator(name) {
        function create() {
            var document = this.ownerDocument, namespace = this.namespaceURI;
            return namespace ? document.createElementNS(namespace, name) : document.createElement(name);
        }
        function createNS() {
            return this.ownerDocument.createElementNS(name.space, name.local);
        }
        return typeof name === "function" ? name : (name = d3.ns.qualify(name)).local ? createNS : create;
    }
    d3_selectionPrototype.insert = function(name, before) {
        name = d3_selection_creator(name);
        before = d3_selection_selector(before);
        return this.select(function() {
            return this.insertBefore(name.apply(this, arguments), before.apply(this, arguments) || null);
        });
    };
    d3_selectionPrototype.remove = function() {
        return this.each(d3_selectionRemove);
    };
    function d3_selectionRemove() {
        var parent = this.parentNode;
        if (parent) parent.removeChild(this);
    }
    d3_selectionPrototype.data = function(value, key) {
        var i = -1, n = this.length, group, node;
        if (!arguments.length) {
            value = new Array(n = (group = this[0]).length);
            while (++i < n) {
                if (node = group[i]) {
                    value[i] = node.__data__;
                }
            }
            return value;
        }
        function bind(group, groupData) {
            var i, n = group.length, m = groupData.length, n0 = Math.min(n, m), updateNodes = new Array(m), enterNodes = new Array(m), exitNodes = new Array(n), node, nodeData;
            if (key) {
                var nodeByKeyValue = new d3_Map(), keyValues = new Array(n), keyValue;
                for (i = -1; ++i < n; ) {
                    if (nodeByKeyValue.has(keyValue = key.call(node = group[i], node.__data__, i))) {
                        exitNodes[i] = node;
                    } else {
                        nodeByKeyValue.set(keyValue, node);
                    }
                    keyValues[i] = keyValue;
                }
                for (i = -1; ++i < m; ) {
                    if (!(node = nodeByKeyValue.get(keyValue = key.call(groupData, nodeData = groupData[i], i)))) {
                        enterNodes[i] = d3_selection_dataNode(nodeData);
                    } else if (node !== true) {
                        updateNodes[i] = node;
                        node.__data__ = nodeData;
                    }
                    nodeByKeyValue.set(keyValue, true);
                }
                for (i = -1; ++i < n; ) {
                    if (nodeByKeyValue.get(keyValues[i]) !== true) {
                        exitNodes[i] = group[i];
                    }
                }
            } else {
                for (i = -1; ++i < n0; ) {
                    node = group[i];
                    nodeData = groupData[i];
                    if (node) {
                        node.__data__ = nodeData;
                        updateNodes[i] = node;
                    } else {
                        enterNodes[i] = d3_selection_dataNode(nodeData);
                    }
                }
                for (;i < m; ++i) {
                    enterNodes[i] = d3_selection_dataNode(groupData[i]);
                }
                for (;i < n; ++i) {
                    exitNodes[i] = group[i];
                }
            }
            enterNodes.update = updateNodes;
            enterNodes.parentNode = updateNodes.parentNode = exitNodes.parentNode = group.parentNode;
            enter.push(enterNodes);
            update.push(updateNodes);
            exit.push(exitNodes);
        }
        var enter = d3_selection_enter([]), update = d3_selection([]), exit = d3_selection([]);
        if (typeof value === "function") {
            while (++i < n) {
                bind(group = this[i], value.call(group, group.parentNode.__data__, i));
            }
        } else {
            while (++i < n) {
                bind(group = this[i], value);
            }
        }
        update.enter = function() {
            return enter;
        };
        update.exit = function() {
            return exit;
        };
        return update;
    };
    function d3_selection_dataNode(data) {
        return {
            __data__: data
        };
    }
    d3_selectionPrototype.datum = function(value) {
        return arguments.length ? this.property("__data__", value) : this.property("__data__");
    };
    d3_selectionPrototype.filter = function(filter) {
        var subgroups = [], subgroup, group, node;
        if (typeof filter !== "function") filter = d3_selection_filter(filter);
        for (var j = 0, m = this.length; j < m; j++) {
            subgroups.push(subgroup = []);
            subgroup.parentNode = (group = this[j]).parentNode;
            for (var i = 0, n = group.length; i < n; i++) {
                if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {
                    subgroup.push(node);
                }
            }
        }
        return d3_selection(subgroups);
    };
    function d3_selection_filter(selector) {
        return function() {
            return d3_selectMatches(this, selector);
        };
    }
    d3_selectionPrototype.order = function() {
        for (var j = -1, m = this.length; ++j < m; ) {
            for (var group = this[j], i = group.length - 1, next = group[i], node; --i >= 0; ) {
                if (node = group[i]) {
                    if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);
                    next = node;
                }
            }
        }
        return this;
    };
    d3_selectionPrototype.sort = function(comparator) {
        comparator = d3_selection_sortComparator.apply(this, arguments);
        for (var j = -1, m = this.length; ++j < m; ) this[j].sort(comparator);
        return this.order();
    };
    function d3_selection_sortComparator(comparator) {
        if (!arguments.length) comparator = d3_ascending;
        return function(a, b) {
            return a && b ? comparator(a.__data__, b.__data__) : !a - !b;
        };
    }
    d3_selectionPrototype.each = function(callback) {
        return d3_selection_each(this, function(node, i, j) {
            callback.call(node, node.__data__, i, j);
        });
    };
    function d3_selection_each(groups, callback) {
        for (var j = 0, m = groups.length; j < m; j++) {
            for (var group = groups[j], i = 0, n = group.length, node; i < n; i++) {
                if (node = group[i]) callback(node, i, j);
            }
        }
        return groups;
    }
    d3_selectionPrototype.call = function(callback) {
        var args = d3_array(arguments);
        callback.apply(args[0] = this, args);
        return this;
    };
    d3_selectionPrototype.empty = function() {
        return !this.node();
    };
    d3_selectionPrototype.node = function() {
        for (var j = 0, m = this.length; j < m; j++) {
            for (var group = this[j], i = 0, n = group.length; i < n; i++) {
                var node = group[i];
                if (node) return node;
            }
        }
        return null;
    };
    d3_selectionPrototype.size = function() {
        var n = 0;
        d3_selection_each(this, function() {
            ++n;
        });
        return n;
    };
    function d3_selection_enter(selection) {
        d3_subclass(selection, d3_selection_enterPrototype);
        return selection;
    }
    var d3_selection_enterPrototype = [];
    d3.selection.enter = d3_selection_enter;
    d3.selection.enter.prototype = d3_selection_enterPrototype;
    d3_selection_enterPrototype.append = d3_selectionPrototype.append;
    d3_selection_enterPrototype.empty = d3_selectionPrototype.empty;
    d3_selection_enterPrototype.node = d3_selectionPrototype.node;
    d3_selection_enterPrototype.call = d3_selectionPrototype.call;
    d3_selection_enterPrototype.size = d3_selectionPrototype.size;
    d3_selection_enterPrototype.select = function(selector) {
        var subgroups = [], subgroup, subnode, upgroup, group, node;
        for (var j = -1, m = this.length; ++j < m; ) {
            upgroup = (group = this[j]).update;
            subgroups.push(subgroup = []);
            subgroup.parentNode = group.parentNode;
            for (var i = -1, n = group.length; ++i < n; ) {
                if (node = group[i]) {
                    subgroup.push(upgroup[i] = subnode = selector.call(group.parentNode, node.__data__, i, j));
                    subnode.__data__ = node.__data__;
                } else {
                    subgroup.push(null);
                }
            }
        }
        return d3_selection(subgroups);
    };
    d3_selection_enterPrototype.insert = function(name, before) {
        if (arguments.length < 2) before = d3_selection_enterInsertBefore(this);
        return d3_selectionPrototype.insert.call(this, name, before);
    };
    function d3_selection_enterInsertBefore(enter) {
        var i0, j0;
        return function(d, i, j) {
            var group = enter[j].update, n = group.length, node;
            if (j != j0) j0 = j, i0 = 0;
            if (i >= i0) i0 = i + 1;
            while (!(node = group[i0]) && ++i0 < n);
            return node;
        };
    }
    d3.select = function(node) {
        var group;
        if (typeof node === "string") {
            group = [ d3_select(node, d3_document) ];
            group.parentNode = d3_document.documentElement;
        } else {
            group = [ node ];
            group.parentNode = d3_documentElement(node);
        }
        return d3_selection([ group ]);
    };
    d3.selectAll = function(nodes) {
        var group;
        if (typeof nodes === "string") {
            group = d3_array(d3_selectAll(nodes, d3_document));
            group.parentNode = d3_document.documentElement;
        } else {
            group = nodes;
            group.parentNode = null;
        }
        return d3_selection([ group ]);
    };
    d3_selectionPrototype.on = function(type, listener, capture) {
        var n = arguments.length;
        if (n < 3) {
            if (typeof type !== "string") {
                if (n < 2) listener = false;
                for (capture in type) this.each(d3_selection_on(capture, type[capture], listener));
                return this;
            }
            if (n < 2) return (n = this.node()["__on" + type]) && n._;
            capture = false;
        }
        return this.each(d3_selection_on(type, listener, capture));
    };
    function d3_selection_on(type, listener, capture) {
        var name = "__on" + type, i = type.indexOf("."), wrap = d3_selection_onListener;
        if (i > 0) type = type.slice(0, i);
        var filter = d3_selection_onFilters.get(type);
        if (filter) type = filter, wrap = d3_selection_onFilter;
        function onRemove() {
            var l = this[name];
            if (l) {
                this.removeEventListener(type, l, l.$);
                delete this[name];
            }
        }
        function onAdd() {
            var l = wrap(listener, d3_array(arguments));
            onRemove.call(this);
            this.addEventListener(type, this[name] = l, l.$ = capture);
            l._ = listener;
        }
        function removeAll() {
            var re = new RegExp("^__on([^.]+)" + d3.requote(type) + "$"), match;
            for (var name in this) {
                if (match = name.match(re)) {
                    var l = this[name];
                    this.removeEventListener(match[1], l, l.$);
                    delete this[name];
                }
            }
        }
        return i ? listener ? onAdd : onRemove : listener ? d3_noop : removeAll;
    }
    var d3_selection_onFilters = d3.map({
        mouseenter: "mouseover",
        mouseleave: "mouseout"
    });
    if (d3_document) {
        d3_selection_onFilters.forEach(function(k) {
            if ("on" + k in d3_document) d3_selection_onFilters.remove(k);
        });
    }
    function d3_selection_onListener(listener, argumentz) {
        return function(e) {
            var o = d3.event;
            d3.event = e;
            argumentz[0] = this.__data__;
            try {
                listener.apply(this, argumentz);
            } finally {
                d3.event = o;
            }
        };
    }
    function d3_selection_onFilter(listener, argumentz) {
        var l = d3_selection_onListener(listener, argumentz);
        return function(e) {
            var target = this, related = e.relatedTarget;
            if (!related || related !== target && !(related.compareDocumentPosition(target) & 8)) {
                l.call(target, e);
            }
        };
    }
    var d3_event_dragSelect, d3_event_dragId = 0;
    function d3_event_dragSuppress(node) {
        var name = ".dragsuppress-" + ++d3_event_dragId, click = "click" + name, w = d3.select(d3_window(node)).on("touchmove" + name, d3_eventPreventDefault).on("dragstart" + name, d3_eventPreventDefault).on("selectstart" + name, d3_eventPreventDefault);
        if (d3_event_dragSelect == null) {
            d3_event_dragSelect = "onselectstart" in node ? false : d3_vendorSymbol(node.style, "userSelect");
        }
        if (d3_event_dragSelect) {
            var style = d3_documentElement(node).style, select = style[d3_event_dragSelect];
            style[d3_event_dragSelect] = "none";
        }
        return function(suppressClick) {
            w.on(name, null);
            if (d3_event_dragSelect) style[d3_event_dragSelect] = select;
            if (suppressClick) {
                var off = function() {
                    w.on(click, null);
                };
                w.on(click, function() {
                    d3_eventPreventDefault();
                    off();
                }, true);
                setTimeout(off, 0);
            }
        };
    }
    d3.mouse = function(container) {
        return d3_mousePoint(container, d3_eventSource());
    };
    var d3_mouse_bug44083 = this.navigator && /WebKit/.test(this.navigator.userAgent) ? -1 : 0;
    function d3_mousePoint(container, e) {
        if (e.changedTouches) e = e.changedTouches[0];
        var svg = container.ownerSVGElement || container;
        if (svg.createSVGPoint) {
            var point = svg.createSVGPoint();
            if (d3_mouse_bug44083 < 0) {
                var window = d3_window(container);
                if (window.scrollX || window.scrollY) {
                    svg = d3.select("body").append("svg").style({
                        position: "absolute",
                        top: 0,
                        left: 0,
                        margin: 0,
                        padding: 0,
                        border: "none"
                    }, "important");
                    var ctm = svg[0][0].getScreenCTM();
                    d3_mouse_bug44083 = !(ctm.f || ctm.e);
                    svg.remove();
                }
            }
            if (d3_mouse_bug44083) point.x = e.pageX, point.y = e.pageY; else point.x = e.clientX, 
            point.y = e.clientY;
            point = point.matrixTransform(container.getScreenCTM().inverse());
            return [ point.x, point.y ];
        }
        var rect = container.getBoundingClientRect();
        return [ e.clientX - rect.left - container.clientLeft, e.clientY - rect.top - container.clientTop ];
    }
    d3.touch = function(container, touches, identifier) {
        if (arguments.length < 3) identifier = touches, touches = d3_eventSource().changedTouches;
        if (touches) for (var i = 0, n = touches.length, touch; i < n; ++i) {
            if ((touch = touches[i]).identifier === identifier) {
                return d3_mousePoint(container, touch);
            }
        }
    };
    d3.behavior.drag = function() {
        var event = d3_eventDispatch(drag, "drag", "dragstart", "dragend"), origin = null, mousedown = dragstart(d3_noop, d3.mouse, d3_window, "mousemove", "mouseup"), touchstart = dragstart(d3_behavior_dragTouchId, d3.touch, d3_identity, "touchmove", "touchend");
        function drag() {
            this.on("mousedown.drag", mousedown).on("touchstart.drag", touchstart);
        }
        function dragstart(id, position, subject, move, end) {
            return function() {
                var that = this, target = d3.event.target, parent = that.parentNode, dispatch = event.of(that, arguments), dragged = 0, dragId = id(), dragName = ".drag" + (dragId == null ? "" : "-" + dragId), dragOffset, dragSubject = d3.select(subject(target)).on(move + dragName, moved).on(end + dragName, ended), dragRestore = d3_event_dragSuppress(target), position0 = position(parent, dragId);
                if (origin) {
                    dragOffset = origin.apply(that, arguments);
                    dragOffset = [ dragOffset.x - position0[0], dragOffset.y - position0[1] ];
                } else {
                    dragOffset = [ 0, 0 ];
                }
                dispatch({
                    type: "dragstart"
                });
                function moved() {
                    var position1 = position(parent, dragId), dx, dy;
                    if (!position1) return;
                    dx = position1[0] - position0[0];
                    dy = position1[1] - position0[1];
                    dragged |= dx | dy;
                    position0 = position1;
                    dispatch({
                        type: "drag",
                        x: position1[0] + dragOffset[0],
                        y: position1[1] + dragOffset[1],
                        dx: dx,
                        dy: dy
                    });
                }
                function ended() {
                    if (!position(parent, dragId)) return;
                    dragSubject.on(move + dragName, null).on(end + dragName, null);
                    dragRestore(dragged && d3.event.target === target);
                    dispatch({
                        type: "dragend"
                    });
                }
            };
        }
        drag.origin = function(x) {
            if (!arguments.length) return origin;
            origin = x;
            return drag;
        };
        return d3.rebind(drag, event, "on");
    };
    function d3_behavior_dragTouchId() {
        return d3.event.changedTouches[0].identifier;
    }
    d3.touches = function(container, touches) {
        if (arguments.length < 2) touches = d3_eventSource().touches;
        return touches ? d3_array(touches).map(function(touch) {
            var point = d3_mousePoint(container, touch);
            point.identifier = touch.identifier;
            return point;
        }) : [];
    };
    var ε = 1e-6, ε2 = ε * ε, π = Math.PI, τ = 2 * π, τε = τ - ε, halfπ = π / 2, d3_radians = π / 180, d3_degrees = 180 / π;
    function d3_sgn(x) {
        return x > 0 ? 1 : x < 0 ? -1 : 0;
    }
    function d3_cross2d(a, b, c) {
        return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
    }
    function d3_acos(x) {
        return x > 1 ? 0 : x < -1 ? π : Math.acos(x);
    }
    function d3_asin(x) {
        return x > 1 ? halfπ : x < -1 ? -halfπ : Math.asin(x);
    }
    function d3_sinh(x) {
        return ((x = Math.exp(x)) - 1 / x) / 2;
    }
    function d3_cosh(x) {
        return ((x = Math.exp(x)) + 1 / x) / 2;
    }
    function d3_tanh(x) {
        return ((x = Math.exp(2 * x)) - 1) / (x + 1);
    }
    function d3_haversin(x) {
        return (x = Math.sin(x / 2)) * x;
    }
    var ρ = Math.SQRT2, ρ2 = 2, ρ4 = 4;
    d3.interpolateZoom = function(p0, p1) {
        var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], ux1 = p1[0], uy1 = p1[1], w1 = p1[2];
        var dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, d1 = Math.sqrt(d2), b0 = (w1 * w1 - w0 * w0 + ρ4 * d2) / (2 * w0 * ρ2 * d1), b1 = (w1 * w1 - w0 * w0 - ρ4 * d2) / (2 * w1 * ρ2 * d1), r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1), dr = r1 - r0, S = (dr || Math.log(w1 / w0)) / ρ;
        function interpolate(t) {
            var s = t * S;
            if (dr) {
                var coshr0 = d3_cosh(r0), u = w0 / (ρ2 * d1) * (coshr0 * d3_tanh(ρ * s + r0) - d3_sinh(r0));
                return [ ux0 + u * dx, uy0 + u * dy, w0 * coshr0 / d3_cosh(ρ * s + r0) ];
            }
            return [ ux0 + t * dx, uy0 + t * dy, w0 * Math.exp(ρ * s) ];
        }
        interpolate.duration = S * 1e3;
        return interpolate;
    };
    d3.behavior.zoom = function() {
        var view = {
            x: 0,
            y: 0,
            k: 1
        }, translate0, center0, center, size = [ 960, 500 ], scaleExtent = d3_behavior_zoomInfinity, duration = 250, zooming = 0, mousedown = "mousedown.zoom", mousemove = "mousemove.zoom", mouseup = "mouseup.zoom", mousewheelTimer, touchstart = "touchstart.zoom", touchtime, event = d3_eventDispatch(zoom, "zoomstart", "zoom", "zoomend"), x0, x1, y0, y1;
        if (!d3_behavior_zoomWheel) {
            d3_behavior_zoomWheel = "onwheel" in d3_document ? (d3_behavior_zoomDelta = function() {
                return -d3.event.deltaY * (d3.event.deltaMode ? 120 : 1);
            }, "wheel") : "onmousewheel" in d3_document ? (d3_behavior_zoomDelta = function() {
                return d3.event.wheelDelta;
            }, "mousewheel") : (d3_behavior_zoomDelta = function() {
                return -d3.event.detail;
            }, "MozMousePixelScroll");
        }
        function zoom(g) {
            g.on(mousedown, mousedowned).on(d3_behavior_zoomWheel + ".zoom", mousewheeled).on("dblclick.zoom", dblclicked).on(touchstart, touchstarted);
        }
        zoom.event = function(g) {
            g.each(function() {
                var dispatch = event.of(this, arguments), view1 = view;
                if (d3_transitionInheritId) {
                    d3.select(this).transition().each("start.zoom", function() {
                        view = this.__chart__ || {
                            x: 0,
                            y: 0,
                            k: 1
                        };
                        zoomstarted(dispatch);
                    }).tween("zoom:zoom", function() {
                        var dx = size[0], dy = size[1], cx = center0 ? center0[0] : dx / 2, cy = center0 ? center0[1] : dy / 2, i = d3.interpolateZoom([ (cx - view.x) / view.k, (cy - view.y) / view.k, dx / view.k ], [ (cx - view1.x) / view1.k, (cy - view1.y) / view1.k, dx / view1.k ]);
                        return function(t) {
                            var l = i(t), k = dx / l[2];
                            this.__chart__ = view = {
                                x: cx - l[0] * k,
                                y: cy - l[1] * k,
                                k: k
                            };
                            zoomed(dispatch);
                        };
                    }).each("interrupt.zoom", function() {
                        zoomended(dispatch);
                    }).each("end.zoom", function() {
                        zoomended(dispatch);
                    });
                } else {
                    this.__chart__ = view;
                    zoomstarted(dispatch);
                    zoomed(dispatch);
                    zoomended(dispatch);
                }
            });
        };
        zoom.translate = function(_) {
            if (!arguments.length) return [ view.x, view.y ];
            view = {
                x: +_[0],
                y: +_[1],
                k: view.k
            };
            rescale();
            return zoom;
        };
        zoom.scale = function(_) {
            if (!arguments.length) return view.k;
            view = {
                x: view.x,
                y: view.y,
                k: +_
            };
            rescale();
            return zoom;
        };
        zoom.scaleExtent = function(_) {
            if (!arguments.length) return scaleExtent;
            scaleExtent = _ == null ? d3_behavior_zoomInfinity : [ +_[0], +_[1] ];
            return zoom;
        };
        zoom.center = function(_) {
            if (!arguments.length) return center;
            center = _ && [ +_[0], +_[1] ];
            return zoom;
        };
        zoom.size = function(_) {
            if (!arguments.length) return size;
            size = _ && [ +_[0], +_[1] ];
            return zoom;
        };
        zoom.duration = function(_) {
            if (!arguments.length) return duration;
            duration = +_;
            return zoom;
        };
        zoom.x = function(z) {
            if (!arguments.length) return x1;
            x1 = z;
            x0 = z.copy();
            view = {
                x: 0,
                y: 0,
                k: 1
            };
            return zoom;
        };
        zoom.y = function(z) {
            if (!arguments.length) return y1;
            y1 = z;
            y0 = z.copy();
            view = {
                x: 0,
                y: 0,
                k: 1
            };
            return zoom;
        };
        function location(p) {
            return [ (p[0] - view.x) / view.k, (p[1] - view.y) / view.k ];
        }
        function point(l) {
            return [ l[0] * view.k + view.x, l[1] * view.k + view.y ];
        }
        function scaleTo(s) {
            view.k = Math.max(scaleExtent[0], Math.min(scaleExtent[1], s));
        }
        function translateTo(p, l) {
            l = point(l);
            view.x += p[0] - l[0];
            view.y += p[1] - l[1];
        }
        function zoomTo(that, p, l, k) {
            that.__chart__ = {
                x: view.x,
                y: view.y,
                k: view.k
            };
            scaleTo(Math.pow(2, k));
            translateTo(center0 = p, l);
            that = d3.select(that);
            if (duration > 0) that = that.transition().duration(duration);
            that.call(zoom.event);
        }
        function rescale() {
            if (x1) x1.domain(x0.range().map(function(x) {
                return (x - view.x) / view.k;
            }).map(x0.invert));
            if (y1) y1.domain(y0.range().map(function(y) {
                return (y - view.y) / view.k;
            }).map(y0.invert));
        }
        function zoomstarted(dispatch) {
            if (!zooming++) dispatch({
                type: "zoomstart"
            });
        }
        function zoomed(dispatch) {
            rescale();
            dispatch({
                type: "zoom",
                scale: view.k,
                translate: [ view.x, view.y ]
            });
        }
        function zoomended(dispatch) {
            if (!--zooming) dispatch({
                type: "zoomend"
            });
            center0 = null;
        }
        function mousedowned() {
            var that = this, target = d3.event.target, dispatch = event.of(that, arguments), dragged = 0, subject = d3.select(d3_window(that)).on(mousemove, moved).on(mouseup, ended), location0 = location(d3.mouse(that)), dragRestore = d3_event_dragSuppress(that);
            d3_selection_interrupt.call(that);
            zoomstarted(dispatch);
            function moved() {
                dragged = 1;
                translateTo(d3.mouse(that), location0);
                zoomed(dispatch);
            }
            function ended() {
                subject.on(mousemove, null).on(mouseup, null);
                dragRestore(dragged && d3.event.target === target);
                zoomended(dispatch);
            }
        }
        function touchstarted() {
            var that = this, dispatch = event.of(that, arguments), locations0 = {}, distance0 = 0, scale0, zoomName = ".zoom-" + d3.event.changedTouches[0].identifier, touchmove = "touchmove" + zoomName, touchend = "touchend" + zoomName, targets = [], subject = d3.select(that), dragRestore = d3_event_dragSuppress(that);
            started();
            zoomstarted(dispatch);
            subject.on(mousedown, null).on(touchstart, started);
            function relocate() {
                var touches = d3.touches(that);
                scale0 = view.k;
                touches.forEach(function(t) {
                    if (t.identifier in locations0) locations0[t.identifier] = location(t);
                });
                return touches;
            }
            function started() {
                var target = d3.event.target;
                d3.select(target).on(touchmove, moved).on(touchend, ended);
                targets.push(target);
                var changed = d3.event.changedTouches;
                for (var i = 0, n = changed.length; i < n; ++i) {
                    locations0[changed[i].identifier] = null;
                }
                var touches = relocate(), now = Date.now();
                if (touches.length === 1) {
                    if (now - touchtime < 500) {
                        var p = touches[0];
                        zoomTo(that, p, locations0[p.identifier], Math.floor(Math.log(view.k) / Math.LN2) + 1);
                        d3_eventPreventDefault();
                    }
                    touchtime = now;
                } else if (touches.length > 1) {
                    var p = touches[0], q = touches[1], dx = p[0] - q[0], dy = p[1] - q[1];
                    distance0 = dx * dx + dy * dy;
                }
            }
            function moved() {
                var touches = d3.touches(that), p0, l0, p1, l1;
                d3_selection_interrupt.call(that);
                for (var i = 0, n = touches.length; i < n; ++i, l1 = null) {
                    p1 = touches[i];
                    if (l1 = locations0[p1.identifier]) {
                        if (l0) break;
                        p0 = p1, l0 = l1;
                    }
                }
                if (l1) {
                    var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1, scale1 = distance0 && Math.sqrt(distance1 / distance0);
                    p0 = [ (p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2 ];
                    l0 = [ (l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2 ];
                    scaleTo(scale1 * scale0);
                }
                touchtime = null;
                translateTo(p0, l0);
                zoomed(dispatch);
            }
            function ended() {
                if (d3.event.touches.length) {
                    var changed = d3.event.changedTouches;
                    for (var i = 0, n = changed.length; i < n; ++i) {
                        delete locations0[changed[i].identifier];
                    }
                    for (var identifier in locations0) {
                        return void relocate();
                    }
                }
                d3.selectAll(targets).on(zoomName, null);
                subject.on(mousedown, mousedowned).on(touchstart, touchstarted);
                dragRestore();
                zoomended(dispatch);
            }
        }
        function mousewheeled() {
            var dispatch = event.of(this, arguments);
            if (mousewheelTimer) clearTimeout(mousewheelTimer); else translate0 = location(center0 = center || d3.mouse(this)), 
            d3_selection_interrupt.call(this), zoomstarted(dispatch);
            mousewheelTimer = setTimeout(function() {
                mousewheelTimer = null;
                zoomended(dispatch);
            }, 50);
            d3_eventPreventDefault();
            scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k);
            translateTo(center0, translate0);
            zoomed(dispatch);
        }
        function dblclicked() {
            var p = d3.mouse(this), k = Math.log(view.k) / Math.LN2;
            zoomTo(this, p, location(p), d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1);
        }
        return d3.rebind(zoom, event, "on");
    };
    var d3_behavior_zoomInfinity = [ 0, Infinity ], d3_behavior_zoomDelta, d3_behavior_zoomWheel;
    d3.color = d3_color;
    function d3_color() {}
    d3_color.prototype.toString = function() {
        return this.rgb() + "";
    };
    d3.hsl = d3_hsl;
    function d3_hsl(h, s, l) {
        return this instanceof d3_hsl ? void (this.h = +h, this.s = +s, this.l = +l) : arguments.length < 2 ? h instanceof d3_hsl ? new d3_hsl(h.h, h.s, h.l) : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl) : new d3_hsl(h, s, l);
    }
    var d3_hslPrototype = d3_hsl.prototype = new d3_color();
    d3_hslPrototype.brighter = function(k) {
        k = Math.pow(.7, arguments.length ? k : 1);
        return new d3_hsl(this.h, this.s, this.l / k);
    };
    d3_hslPrototype.darker = function(k) {
        k = Math.pow(.7, arguments.length ? k : 1);
        return new d3_hsl(this.h, this.s, k * this.l);
    };
    d3_hslPrototype.rgb = function() {
        return d3_hsl_rgb(this.h, this.s, this.l);
    };
    function d3_hsl_rgb(h, s, l) {
        var m1, m2;
        h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h;
        s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s;
        l = l < 0 ? 0 : l > 1 ? 1 : l;
        m2 = l <= .5 ? l * (1 + s) : l + s - l * s;
        m1 = 2 * l - m2;
        function v(h) {
            if (h > 360) h -= 360; else if (h < 0) h += 360;
            if (h < 60) return m1 + (m2 - m1) * h / 60;
            if (h < 180) return m2;
            if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60;
            return m1;
        }
        function vv(h) {
            return Math.round(v(h) * 255);
        }
        return new d3_rgb(vv(h + 120), vv(h), vv(h - 120));
    }
    d3.hcl = d3_hcl;
    function d3_hcl(h, c, l) {
        return this instanceof d3_hcl ? void (this.h = +h, this.c = +c, this.l = +l) : arguments.length < 2 ? h instanceof d3_hcl ? new d3_hcl(h.h, h.c, h.l) : h instanceof d3_lab ? d3_lab_hcl(h.l, h.a, h.b) : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b) : new d3_hcl(h, c, l);
    }
    var d3_hclPrototype = d3_hcl.prototype = new d3_color();
    d3_hclPrototype.brighter = function(k) {
        return new d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)));
    };
    d3_hclPrototype.darker = function(k) {
        return new d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)));
    };
    d3_hclPrototype.rgb = function() {
        return d3_hcl_lab(this.h, this.c, this.l).rgb();
    };
    function d3_hcl_lab(h, c, l) {
        if (isNaN(h)) h = 0;
        if (isNaN(c)) c = 0;
        return new d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c);
    }
    d3.lab = d3_lab;
    function d3_lab(l, a, b) {
        return this instanceof d3_lab ? void (this.l = +l, this.a = +a, this.b = +b) : arguments.length < 2 ? l instanceof d3_lab ? new d3_lab(l.l, l.a, l.b) : l instanceof d3_hcl ? d3_hcl_lab(l.h, l.c, l.l) : d3_rgb_lab((l = d3_rgb(l)).r, l.g, l.b) : new d3_lab(l, a, b);
    }
    var d3_lab_K = 18;
    var d3_lab_X = .95047, d3_lab_Y = 1, d3_lab_Z = 1.08883;
    var d3_labPrototype = d3_lab.prototype = new d3_color();
    d3_labPrototype.brighter = function(k) {
        return new d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
    };
    d3_labPrototype.darker = function(k) {
        return new d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
    };
    d3_labPrototype.rgb = function() {
        return d3_lab_rgb(this.l, this.a, this.b);
    };
    function d3_lab_rgb(l, a, b) {
        var y = (l + 16) / 116, x = y + a / 500, z = y - b / 200;
        x = d3_lab_xyz(x) * d3_lab_X;
        y = d3_lab_xyz(y) * d3_lab_Y;
        z = d3_lab_xyz(z) * d3_lab_Z;
        return new d3_rgb(d3_xyz_rgb(3.2404542 * x - 1.5371385 * y - .4985314 * z), d3_xyz_rgb(-.969266 * x + 1.8760108 * y + .041556 * z), d3_xyz_rgb(.0556434 * x - .2040259 * y + 1.0572252 * z));
    }
    function d3_lab_hcl(l, a, b) {
        return l > 0 ? new d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l) : new d3_hcl(NaN, NaN, l);
    }
    function d3_lab_xyz(x) {
        return x > .206893034 ? x * x * x : (x - 4 / 29) / 7.787037;
    }
    function d3_xyz_lab(x) {
        return x > .008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29;
    }
    function d3_xyz_rgb(r) {
        return Math.round(255 * (r <= .00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - .055));
    }
    d3.rgb = d3_rgb;
    function d3_rgb(r, g, b) {
        return this instanceof d3_rgb ? void (this.r = ~~r, this.g = ~~g, this.b = ~~b) : arguments.length < 2 ? r instanceof d3_rgb ? new d3_rgb(r.r, r.g, r.b) : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb) : new d3_rgb(r, g, b);
    }
    function d3_rgbNumber(value) {
        return new d3_rgb(value >> 16, value >> 8 & 255, value & 255);
    }
    function d3_rgbString(value) {
        return d3_rgbNumber(value) + "";
    }
    var d3_rgbPrototype = d3_rgb.prototype = new d3_color();
    d3_rgbPrototype.brighter = function(k) {
        k = Math.pow(.7, arguments.length ? k : 1);
        var r = this.r, g = this.g, b = this.b, i = 30;
        if (!r && !g && !b) return new d3_rgb(i, i, i);
        if (r && r < i) r = i;
        if (g && g < i) g = i;
        if (b && b < i) b = i;
        return new d3_rgb(Math.min(255, r / k), Math.min(255, g / k), Math.min(255, b / k));
    };
    d3_rgbPrototype.darker = function(k) {
        k = Math.pow(.7, arguments.length ? k : 1);
        return new d3_rgb(k * this.r, k * this.g, k * this.b);
    };
    d3_rgbPrototype.hsl = function() {
        return d3_rgb_hsl(this.r, this.g, this.b);
    };
    d3_rgbPrototype.toString = function() {
        return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b);
    };
    function d3_rgb_hex(v) {
        return v < 16 ? "0" + Math.max(0, v).toString(16) : Math.min(255, v).toString(16);
    }
    function d3_rgb_parse(format, rgb, hsl) {
        var r = 0, g = 0, b = 0, m1, m2, color;
        m1 = /([a-z]+)\((.*)\)/i.exec(format);
        if (m1) {
            m2 = m1[2].split(",");
            switch (m1[1]) {
              case "hsl":
                {
                    return hsl(parseFloat(m2[0]), parseFloat(m2[1]) / 100, parseFloat(m2[2]) / 100);
                }

              case "rgb":
                {
                    return rgb(d3_rgb_parseNumber(m2[0]), d3_rgb_parseNumber(m2[1]), d3_rgb_parseNumber(m2[2]));
                }
            }
        }
        if (color = d3_rgb_names.get(format.toLowerCase())) {
            return rgb(color.r, color.g, color.b);
        }
        if (format != null && format.charAt(0) === "#" && !isNaN(color = parseInt(format.slice(1), 16))) {
            if (format.length === 4) {
                r = (color & 3840) >> 4;
                r = r >> 4 | r;
                g = color & 240;
                g = g >> 4 | g;
                b = color & 15;
                b = b << 4 | b;
            } else if (format.length === 7) {
                r = (color & 16711680) >> 16;
                g = (color & 65280) >> 8;
                b = color & 255;
            }
        }
        return rgb(r, g, b);
    }
    function d3_rgb_hsl(r, g, b) {
        var min = Math.min(r /= 255, g /= 255, b /= 255), max = Math.max(r, g, b), d = max - min, h, s, l = (max + min) / 2;
        if (d) {
            s = l < .5 ? d / (max + min) : d / (2 - max - min);
            if (r == max) h = (g - b) / d + (g < b ? 6 : 0); else if (g == max) h = (b - r) / d + 2; else h = (r - g) / d + 4;
            h *= 60;
        } else {
            h = NaN;
            s = l > 0 && l < 1 ? 0 : h;
        }
        return new d3_hsl(h, s, l);
    }
    function d3_rgb_lab(r, g, b) {
        r = d3_rgb_xyz(r);
        g = d3_rgb_xyz(g);
        b = d3_rgb_xyz(b);
        var x = d3_xyz_lab((.4124564 * r + .3575761 * g + .1804375 * b) / d3_lab_X), y = d3_xyz_lab((.2126729 * r + .7151522 * g + .072175 * b) / d3_lab_Y), z = d3_xyz_lab((.0193339 * r + .119192 * g + .9503041 * b) / d3_lab_Z);
        return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z));
    }
    function d3_rgb_xyz(r) {
        return (r /= 255) <= .04045 ? r / 12.92 : Math.pow((r + .055) / 1.055, 2.4);
    }
    function d3_rgb_parseNumber(c) {
        var f = parseFloat(c);
        return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f;
    }
    var d3_rgb_names = d3.map({
        aliceblue: 15792383,
        antiquewhite: 16444375,
        aqua: 65535,
        aquamarine: 8388564,
        azure: 15794175,
        beige: 16119260,
        bisque: 16770244,
        black: 0,
        blanchedalmond: 16772045,
        blue: 255,
        blueviolet: 9055202,
        brown: 10824234,
        burlywood: 14596231,
        cadetblue: 6266528,
        chartreuse: 8388352,
        chocolate: 13789470,
        coral: 16744272,
        cornflowerblue: 6591981,
        cornsilk: 16775388,
        crimson: 14423100,
        cyan: 65535,
        darkblue: 139,
        darkcyan: 35723,
        darkgoldenrod: 12092939,
        darkgray: 11119017,
        darkgreen: 25600,
        darkgrey: 11119017,
        darkkhaki: 12433259,
        darkmagenta: 9109643,
        darkolivegreen: 5597999,
        darkorange: 16747520,
        darkorchid: 10040012,
        darkred: 9109504,
        darksalmon: 15308410,
        darkseagreen: 9419919,
        darkslateblue: 4734347,
        darkslategray: 3100495,
        darkslategrey: 3100495,
        darkturquoise: 52945,
        darkviolet: 9699539,
        deeppink: 16716947,
        deepskyblue: 49151,
        dimgray: 6908265,
        dimgrey: 6908265,
        dodgerblue: 2003199,
        firebrick: 11674146,
        floralwhite: 16775920,
        forestgreen: 2263842,
        fuchsia: 16711935,
        gainsboro: 14474460,
        ghostwhite: 16316671,
        gold: 16766720,
        goldenrod: 14329120,
        gray: 8421504,
        green: 32768,
        greenyellow: 11403055,
        grey: 8421504,
        honeydew: 15794160,
        hotpink: 16738740,
        indianred: 13458524,
        indigo: 4915330,
        ivory: 16777200,
        khaki: 15787660,
        lavender: 15132410,
        lavenderblush: 16773365,
        lawngreen: 8190976,
        lemonchiffon: 16775885,
        lightblue: 11393254,
        lightcoral: 15761536,
        lightcyan: 14745599,
        lightgoldenrodyellow: 16448210,
        lightgray: 13882323,
        lightgreen: 9498256,
        lightgrey: 13882323,
        lightpink: 16758465,
        lightsalmon: 16752762,
        lightseagreen: 2142890,
        lightskyblue: 8900346,
        lightslategray: 7833753,
        lightslategrey: 7833753,
        lightsteelblue: 11584734,
        lightyellow: 16777184,
        lime: 65280,
        limegreen: 3329330,
        linen: 16445670,
        magenta: 16711935,
        maroon: 8388608,
        mediumaquamarine: 6737322,
        mediumblue: 205,
        mediumorchid: 12211667,
        mediumpurple: 9662683,
        mediumseagreen: 3978097,
        mediumslateblue: 8087790,
        mediumspringgreen: 64154,
        mediumturquoise: 4772300,
        mediumvioletred: 13047173,
        midnightblue: 1644912,
        mintcream: 16121850,
        mistyrose: 16770273,
        moccasin: 16770229,
        navajowhite: 16768685,
        navy: 128,
        oldlace: 16643558,
        olive: 8421376,
        olivedrab: 7048739,
        orange: 16753920,
        orangered: 16729344,
        orchid: 14315734,
        palegoldenrod: 15657130,
        palegreen: 10025880,
        paleturquoise: 11529966,
        palevioletred: 14381203,
        papayawhip: 16773077,
        peachpuff: 16767673,
        peru: 13468991,
        pink: 16761035,
        plum: 14524637,
        powderblue: 11591910,
        purple: 8388736,
        rebeccapurple: 6697881,
        red: 16711680,
        rosybrown: 12357519,
        royalblue: 4286945,
        saddlebrown: 9127187,
        salmon: 16416882,
        sandybrown: 16032864,
        seagreen: 3050327,
        seashell: 16774638,
        sienna: 10506797,
        silver: 12632256,
        skyblue: 8900331,
        slateblue: 6970061,
        slategray: 7372944,
        slategrey: 7372944,
        snow: 16775930,
        springgreen: 65407,
        steelblue: 4620980,
        tan: 13808780,
        teal: 32896,
        thistle: 14204888,
        tomato: 16737095,
        turquoise: 4251856,
        violet: 15631086,
        wheat: 16113331,
        white: 16777215,
        whitesmoke: 16119285,
        yellow: 16776960,
        yellowgreen: 10145074
    });
    d3_rgb_names.forEach(function(key, value) {
        d3_rgb_names.set(key, d3_rgbNumber(value));
    });
    function d3_functor(v) {
        return typeof v === "function" ? v : function() {
            return v;
        };
    }
    d3.functor = d3_functor;
    d3.xhr = d3_xhrType(d3_identity);
    function d3_xhrType(response) {
        return function(url, mimeType, callback) {
            if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType, 
            mimeType = null;
            return d3_xhr(url, mimeType, response, callback);
        };
    }
    function d3_xhr(url, mimeType, response, callback) {
        var xhr = {}, dispatch = d3.dispatch("beforesend", "progress", "load", "error"), headers = {}, request = new XMLHttpRequest(), responseType = null;
        if (this.XDomainRequest && !("withCredentials" in request) && /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest();
        "onload" in request ? request.onload = request.onerror = respond : request.onreadystatechange = function() {
            request.readyState > 3 && respond();
        };
        function respond() {
            var status = request.status, result;
            if (!status && d3_xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) {
                try {
                    result = response.call(xhr, request);
                } catch (e) {
                    dispatch.error.call(xhr, e);
                    return;
                }
                dispatch.load.call(xhr, result);
            } else {
                dispatch.error.call(xhr, request);
            }
        }
        request.onprogress = function(event) {
            var o = d3.event;
            d3.event = event;
            try {
                dispatch.progress.call(xhr, request);
            } finally {
                d3.event = o;
            }
        };
        xhr.header = function(name, value) {
            name = (name + "").toLowerCase();
            if (arguments.length < 2) return headers[name];
            if (value == null) delete headers[name]; else headers[name] = value + "";
            return xhr;
        };
        xhr.mimeType = function(value) {
            if (!arguments.length) return mimeType;
            mimeType = value == null ? null : value + "";
            return xhr;
        };
        xhr.responseType = function(value) {
            if (!arguments.length) return responseType;
            responseType = value;
            return xhr;
        };
        xhr.response = function(value) {
            response = value;
            return xhr;
        };
        [ "get", "post" ].forEach(function(method) {
            xhr[method] = function() {
                return xhr.send.apply(xhr, [ method ].concat(d3_array(arguments)));
            };
        });
        xhr.send = function(method, data, callback) {
            if (arguments.length === 2 && typeof data === "function") callback = data, 
            data = null;
            request.open(method, url, true);
            if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*";
            if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]);
            if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType);
            if (responseType != null) request.responseType = responseType;
            if (callback != null) xhr.on("error", callback).on("load", function(request) {
                callback(null, request);
            });
            dispatch.beforesend.call(xhr, request);
            request.send(data == null ? null : data);
            return xhr;
        };
        xhr.abort = function() {
            request.abort();
            return xhr;
        };
        d3.rebind(xhr, dispatch, "on");
        return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback));
    }
    function d3_xhr_fixCallback(callback) {
        return callback.length === 1 ? function(error, request) {
            callback(error == null ? request : null);
        } : callback;
    }
    function d3_xhrHasResponse(request) {
        var type = request.responseType;
        return type && type !== "text" ? request.response : request.responseText;
    }
    d3.dsv = function(delimiter, mimeType) {
        var reFormat = new RegExp('["' + delimiter + "\n]"), delimiterCode = delimiter.charCodeAt(0);
        function dsv(url, row, callback) {
            if (arguments.length < 3) callback = row, row = null;
            var xhr = d3_xhr(url, mimeType, row == null ? response : typedResponse(row), callback);
            xhr.row = function(_) {
                return arguments.length ? xhr.response((row = _) == null ? response : typedResponse(_)) : row;
            };
            return xhr;
        }
        function response(request) {
            return dsv.parse(request.responseText);
        }
        function typedResponse(f) {
            return function(request) {
                return dsv.parse(request.responseText, f);
            };
        }
        dsv.parse = function(text, f) {
            var o;
            return dsv.parseRows(text, function(row, i) {
                if (o) return o(row, i - 1);
                var a = new Function("d", "return {" + row.map(function(name, i) {
                    return JSON.stringify(name) + ": d[" + i + "]";
                }).join(",") + "}");
                o = f ? function(row, i) {
                    return f(a(row), i);
                } : a;
            });
        };
        dsv.parseRows = function(text, f) {
            var EOL = {}, EOF = {}, rows = [], N = text.length, I = 0, n = 0, t, eol;
            function token() {
                if (I >= N) return EOF;
                if (eol) return eol = false, EOL;
                var j = I;
                if (text.charCodeAt(j) === 34) {
                    var i = j;
                    while (i++ < N) {
                        if (text.charCodeAt(i) === 34) {
                            if (text.charCodeAt(i + 1) !== 34) break;
                            ++i;
                        }
                    }
                    I = i + 2;
                    var c = text.charCodeAt(i + 1);
                    if (c === 13) {
                        eol = true;
                        if (text.charCodeAt(i + 2) === 10) ++I;
                    } else if (c === 10) {
                        eol = true;
                    }
                    return text.slice(j + 1, i).replace(/""/g, '"');
                }
                while (I < N) {
                    var c = text.charCodeAt(I++), k = 1;
                    if (c === 10) eol = true; else if (c === 13) {
                        eol = true;
                        if (text.charCodeAt(I) === 10) ++I, ++k;
                    } else if (c !== delimiterCode) continue;
                    return text.slice(j, I - k);
                }
                return text.slice(j);
            }
            while ((t = token()) !== EOF) {
                var a = [];
                while (t !== EOL && t !== EOF) {
                    a.push(t);
                    t = token();
                }
                if (f && (a = f(a, n++)) == null) continue;
                rows.push(a);
            }
            return rows;
        };
        dsv.format = function(rows) {
            if (Array.isArray(rows[0])) return dsv.formatRows(rows);
            var fieldSet = new d3_Set(), fields = [];
            rows.forEach(function(row) {
                for (var field in row) {
                    if (!fieldSet.has(field)) {
                        fields.push(fieldSet.add(field));
                    }
                }
            });
            return [ fields.map(formatValue).join(delimiter) ].concat(rows.map(function(row) {
                return fields.map(function(field) {
                    return formatValue(row[field]);
                }).join(delimiter);
            })).join("\n");
        };
        dsv.formatRows = function(rows) {
            return rows.map(formatRow).join("\n");
        };
        function formatRow(row) {
            return row.map(formatValue).join(delimiter);
        }
        function formatValue(text) {
            return reFormat.test(text) ? '"' + text.replace(/\"/g, '""') + '"' : text;
        }
        return dsv;
    };
    d3.csv = d3.dsv(",", "text/csv");
    d3.tsv = d3.dsv(" ", "text/tab-separated-values");
    var d3_timer_queueHead, d3_timer_queueTail, d3_timer_interval, d3_timer_timeout, d3_timer_active, d3_timer_frame = this[d3_vendorSymbol(this, "requestAnimationFrame")] || function(callback) {
        setTimeout(callback, 17);
    };
    d3.timer = function(callback, delay, then) {
        var n = arguments.length;
        if (n < 2) delay = 0;
        if (n < 3) then = Date.now();
        var time = then + delay, timer = {
            c: callback,
            t: time,
            f: false,
            n: null
        };
        if (d3_timer_queueTail) d3_timer_queueTail.n = timer; else d3_timer_queueHead = timer;
        d3_timer_queueTail = timer;
        if (!d3_timer_interval) {
            d3_timer_timeout = clearTimeout(d3_timer_timeout);
            d3_timer_interval = 1;
            d3_timer_frame(d3_timer_step);
        }
    };
    function d3_timer_step() {
        var now = d3_timer_mark(), delay = d3_timer_sweep() - now;
        if (delay > 24) {
            if (isFinite(delay)) {
                clearTimeout(d3_timer_timeout);
                d3_timer_timeout = setTimeout(d3_timer_step, delay);
            }
            d3_timer_interval = 0;
        } else {
            d3_timer_interval = 1;
            d3_timer_frame(d3_timer_step);
        }
    }
    d3.timer.flush = function() {
        d3_timer_mark();
        d3_timer_sweep();
    };
    function d3_timer_mark() {
        var now = Date.now();
        d3_timer_active = d3_timer_queueHead;
        while (d3_timer_active) {
            if (now >= d3_timer_active.t) d3_timer_active.f = d3_timer_active.c(now - d3_timer_active.t);
            d3_timer_active = d3_timer_active.n;
        }
        return now;
    }
    function d3_timer_sweep() {
        var t0, t1 = d3_timer_queueHead, time = Infinity;
        while (t1) {
            if (t1.f) {
                t1 = t0 ? t0.n = t1.n : d3_timer_queueHead = t1.n;
            } else {
                if (t1.t < time) time = t1.t;
                t1 = (t0 = t1).n;
            }
        }
        d3_timer_queueTail = t0;
        return time;
    }
    function d3_format_precision(x, p) {
        return p - (x ? Math.ceil(Math.log(x) / Math.LN10) : 1);
    }
    d3.round = function(x, n) {
        return n ? Math.round(x * (n = Math.pow(10, n))) / n : Math.round(x);
    };
    var d3_formatPrefixes = [ "y", "z", "a", "f", "p", "n", "µ", "m", "", "k", "M", "G", "T", "P", "E", "Z", "Y" ].map(d3_formatPrefix);
    d3.formatPrefix = function(value, precision) {
        var i = 0;
        if (value) {
            if (value < 0) value *= -1;
            if (precision) value = d3.round(value, d3_format_precision(value, precision));
            i = 1 + Math.floor(1e-12 + Math.log(value) / Math.LN10);
            i = Math.max(-24, Math.min(24, Math.floor((i - 1) / 3) * 3));
        }
        return d3_formatPrefixes[8 + i / 3];
    };
    function d3_formatPrefix(d, i) {
        var k = Math.pow(10, abs(8 - i) * 3);
        return {
            scale: i > 8 ? function(d) {
                return d / k;
            } : function(d) {
                return d * k;
            },
            symbol: d
        };
    }
    function d3_locale_numberFormat(locale) {
        var locale_decimal = locale.decimal, locale_thousands = locale.thousands, locale_grouping = locale.grouping, locale_currency = locale.currency, formatGroup = locale_grouping && locale_thousands ? function(value, width) {
            var i = value.length, t = [], j = 0, g = locale_grouping[0], length = 0;
            while (i > 0 && g > 0) {
                if (length + g + 1 > width) g = Math.max(1, width - length);
                t.push(value.substring(i -= g, i + g));
                if ((length += g + 1) > width) break;
                g = locale_grouping[j = (j + 1) % locale_grouping.length];
            }
            return t.reverse().join(locale_thousands);
        } : d3_identity;
        return function(specifier) {
            var match = d3_format_re.exec(specifier), fill = match[1] || " ", align = match[2] || ">", sign = match[3] || "-", symbol = match[4] || "", zfill = match[5], width = +match[6], comma = match[7], precision = match[8], type = match[9], scale = 1, prefix = "", suffix = "", integer = false, exponent = true;
            if (precision) precision = +precision.substring(1);
            if (zfill || fill === "0" && align === "=") {
                zfill = fill = "0";
                align = "=";
            }
            switch (type) {
              case "n":
                comma = true;
                type = "g";
                break;

              case "%":
                scale = 100;
                suffix = "%";
                type = "f";
                break;

              case "p":
                scale = 100;
                suffix = "%";
                type = "r";
                break;

              case "b":
              case "o":
              case "x":
              case "X":
                if (symbol === "#") prefix = "0" + type.toLowerCase();

              case "c":
                exponent = false;

              case "d":
                integer = true;
                precision = 0;
                break;

              case "s":
                scale = -1;
                type = "r";
                break;
            }
            if (symbol === "$") prefix = locale_currency[0], suffix = locale_currency[1];
            if (type == "r" && !precision) type = "g";
            if (precision != null) {
                if (type == "g") precision = Math.max(1, Math.min(21, precision)); else if (type == "e" || type == "f") precision = Math.max(0, Math.min(20, precision));
            }
            type = d3_format_types.get(type) || d3_format_typeDefault;
            var zcomma = zfill && comma;
            return function(value) {
                var fullSuffix = suffix;
                if (integer && value % 1) return "";
                var negative = value < 0 || value === 0 && 1 / value < 0 ? (value = -value, 
                "-") : sign === "-" ? "" : sign;
                if (scale < 0) {
                    var unit = d3.formatPrefix(value, precision);
                    value = unit.scale(value);
                    fullSuffix = unit.symbol + suffix;
                } else {
                    value *= scale;
                }
                value = type(value, precision);
                var i = value.lastIndexOf("."), before, after;
                if (i < 0) {
                    var j = exponent ? value.lastIndexOf("e") : -1;
                    if (j < 0) before = value, after = ""; else before = value.substring(0, j), 
                    after = value.substring(j);
                } else {
                    before = value.substring(0, i);
                    after = locale_decimal + value.substring(i + 1);
                }
                if (!zfill && comma) before = formatGroup(before, Infinity);
                var length = prefix.length + before.length + after.length + (zcomma ? 0 : negative.length), padding = length < width ? new Array(length = width - length + 1).join(fill) : "";
                if (zcomma) before = formatGroup(padding + before, padding.length ? width - after.length : Infinity);
                negative += prefix;
                value = before + after;
                return (align === "<" ? negative + value + padding : align === ">" ? padding + negative + value : align === "^" ? padding.substring(0, length >>= 1) + negative + value + padding.substring(length) : negative + (zcomma ? value : padding + value)) + fullSuffix;
            };
        };
    }
    var d3_format_re = /(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i;
    var d3_format_types = d3.map({
        b: function(x) {
            return x.toString(2);
        },
        c: function(x) {
            return String.fromCharCode(x);
        },
        o: function(x) {
            return x.toString(8);
        },
        x: function(x) {
            return x.toString(16);
        },
        X: function(x) {
            return x.toString(16).toUpperCase();
        },
        g: function(x, p) {
            return x.toPrecision(p);
        },
        e: function(x, p) {
            return x.toExponential(p);
        },
        f: function(x, p) {
            return x.toFixed(p);
        },
        r: function(x, p) {
            return (x = d3.round(x, d3_format_precision(x, p))).toFixed(Math.max(0, Math.min(20, d3_format_precision(x * (1 + 1e-15), p))));
        }
    });
    function d3_format_typeDefault(x) {
        return x + "";
    }
    var d3_time = d3.time = {}, d3_date = Date;
    function d3_date_utc() {
        this._ = new Date(arguments.length > 1 ? Date.UTC.apply(this, arguments) : arguments[0]);
    }
    d3_date_utc.prototype = {
        getDate: function() {
            return this._.getUTCDate();
        },
        getDay: function() {
            return this._.getUTCDay();
        },
        getFullYear: function() {
            return this._.getUTCFullYear();
        },
        getHours: function() {
            return this._.getUTCHours();
        },
        getMilliseconds: function() {
            return this._.getUTCMilliseconds();
        },
        getMinutes: function() {
            return this._.getUTCMinutes();
        },
        getMonth: function() {
            return this._.getUTCMonth();
        },
        getSeconds: function() {
            return this._.getUTCSeconds();
        },
        getTime: function() {
            return this._.getTime();
        },
        getTimezoneOffset: function() {
            return 0;
        },
        valueOf: function() {
            return this._.valueOf();
        },
        setDate: function() {
            d3_time_prototype.setUTCDate.apply(this._, arguments);
        },
        setDay: function() {
            d3_time_prototype.setUTCDay.apply(this._, arguments);
        },
        setFullYear: function() {
            d3_time_prototype.setUTCFullYear.apply(this._, arguments);
        },
        setHours: function() {
            d3_time_prototype.setUTCHours.apply(this._, arguments);
        },
        setMilliseconds: function() {
            d3_time_prototype.setUTCMilliseconds.apply(this._, arguments);
        },
        setMinutes: function() {
            d3_time_prototype.setUTCMinutes.apply(this._, arguments);
        },
        setMonth: function() {
            d3_time_prototype.setUTCMonth.apply(this._, arguments);
        },
        setSeconds: function() {
            d3_time_prototype.setUTCSeconds.apply(this._, arguments);
        },
        setTime: function() {
            d3_time_prototype.setTime.apply(this._, arguments);
        }
    };
    var d3_time_prototype = Date.prototype;
    function d3_time_interval(local, step, number) {
        function round(date) {
            var d0 = local(date), d1 = offset(d0, 1);
            return date - d0 < d1 - date ? d0 : d1;
        }
        function ceil(date) {
            step(date = local(new d3_date(date - 1)), 1);
            return date;
        }
        function offset(date, k) {
            step(date = new d3_date(+date), k);
            return date;
        }
        function range(t0, t1, dt) {
            var time = ceil(t0), times = [];
            if (dt > 1) {
                while (time < t1) {
                    if (!(number(time) % dt)) times.push(new Date(+time));
                    step(time, 1);
                }
            } else {
                while (time < t1) times.push(new Date(+time)), step(time, 1);
            }
            return times;
        }
        function range_utc(t0, t1, dt) {
            try {
                d3_date = d3_date_utc;
                var utc = new d3_date_utc();
                utc._ = t0;
                return range(utc, t1, dt);
            } finally {
                d3_date = Date;
            }
        }
        local.floor = local;
        local.round = round;
        local.ceil = ceil;
        local.offset = offset;
        local.range = range;
        var utc = local.utc = d3_time_interval_utc(local);
        utc.floor = utc;
        utc.round = d3_time_interval_utc(round);
        utc.ceil = d3_time_interval_utc(ceil);
        utc.offset = d3_time_interval_utc(offset);
        utc.range = range_utc;
        return local;
    }
    function d3_time_interval_utc(method) {
        return function(date, k) {
            try {
                d3_date = d3_date_utc;
                var utc = new d3_date_utc();
                utc._ = date;
                return method(utc, k)._;
            } finally {
                d3_date = Date;
            }
        };
    }
    d3_time.year = d3_time_interval(function(date) {
        date = d3_time.day(date);
        date.setMonth(0, 1);
        return date;
    }, function(date, offset) {
        date.setFullYear(date.getFullYear() + offset);
    }, function(date) {
        return date.getFullYear();
    });
    d3_time.years = d3_time.year.range;
    d3_time.years.utc = d3_time.year.utc.range;
    d3_time.day = d3_time_interval(function(date) {
        var day = new d3_date(2e3, 0);
        day.setFullYear(date.getFullYear(), date.getMonth(), date.getDate());
        return day;
    }, function(date, offset) {
        date.setDate(date.getDate() + offset);
    }, function(date) {
        return date.getDate() - 1;
    });
    d3_time.days = d3_time.day.range;
    d3_time.days.utc = d3_time.day.utc.range;
    d3_time.dayOfYear = function(date) {
        var year = d3_time.year(date);
        return Math.floor((date - year - (date.getTimezoneOffset() - year.getTimezoneOffset()) * 6e4) / 864e5);
    };
    [ "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday" ].forEach(function(day, i) {
        i = 7 - i;
        var interval = d3_time[day] = d3_time_interval(function(date) {
            (date = d3_time.day(date)).setDate(date.getDate() - (date.getDay() + i) % 7);
            return date;
        }, function(date, offset) {
            date.setDate(date.getDate() + Math.floor(offset) * 7);
        }, function(date) {
            var day = d3_time.year(date).getDay();
            return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7) - (day !== i);
        });
        d3_time[day + "s"] = interval.range;
        d3_time[day + "s"].utc = interval.utc.range;
        d3_time[day + "OfYear"] = function(date) {
            var day = d3_time.year(date).getDay();
            return Math.floor((d3_time.dayOfYear(date) + (day + i) % 7) / 7);
        };
    });
    d3_time.week = d3_time.sunday;
    d3_time.weeks = d3_time.sunday.range;
    d3_time.weeks.utc = d3_time.sunday.utc.range;
    d3_time.weekOfYear = d3_time.sundayOfYear;
    function d3_locale_timeFormat(locale) {
        var locale_dateTime = locale.dateTime, locale_date = locale.date, locale_time = locale.time, locale_periods = locale.periods, locale_days = locale.days, locale_shortDays = locale.shortDays, locale_months = locale.months, locale_shortMonths = locale.shortMonths;
        function d3_time_format(template) {
            var n = template.length;
            function format(date) {
                var string = [], i = -1, j = 0, c, p, f;
                while (++i < n) {
                    if (template.charCodeAt(i) === 37) {
                        string.push(template.slice(j, i));
                        if ((p = d3_time_formatPads[c = template.charAt(++i)]) != null) c = template.charAt(++i);
                        if (f = d3_time_formats[c]) c = f(date, p == null ? c === "e" ? " " : "0" : p);
                        string.push(c);
                        j = i + 1;
                    }
                }
                string.push(template.slice(j, i));
                return string.join("");
            }
            format.parse = function(string) {
                var d = {
                    y: 1900,
                    m: 0,
                    d: 1,
                    H: 0,
                    M: 0,
                    S: 0,
                    L: 0,
                    Z: null
                }, i = d3_time_parse(d, template, string, 0);
                if (i != string.length) return null;
                if ("p" in d) d.H = d.H % 12 + d.p * 12;
                var localZ = d.Z != null && d3_date !== d3_date_utc, date = new (localZ ? d3_date_utc : d3_date)();
                if ("j" in d) date.setFullYear(d.y, 0, d.j); else if ("w" in d && ("W" in d || "U" in d)) {
                    date.setFullYear(d.y, 0, 1);
                    date.setFullYear(d.y, 0, "W" in d ? (d.w + 6) % 7 + d.W * 7 - (date.getDay() + 5) % 7 : d.w + d.U * 7 - (date.getDay() + 6) % 7);
                } else date.setFullYear(d.y, d.m, d.d);
                date.setHours(d.H + (d.Z / 100 | 0), d.M + d.Z % 100, d.S, d.L);
                return localZ ? date._ : date;
            };
            format.toString = function() {
                return template;
            };
            return format;
        }
        function d3_time_parse(date, template, string, j) {
            var c, p, t, i = 0, n = template.length, m = string.length;
            while (i < n) {
                if (j >= m) return -1;
                c = template.charCodeAt(i++);
                if (c === 37) {
                    t = template.charAt(i++);
                    p = d3_time_parsers[t in d3_time_formatPads ? template.charAt(i++) : t];
                    if (!p || (j = p(date, string, j)) < 0) return -1;
                } else if (c != string.charCodeAt(j++)) {
                    return -1;
                }
            }
            return j;
        }
        d3_time_format.utc = function(template) {
            var local = d3_time_format(template);
            function format(date) {
                try {
                    d3_date = d3_date_utc;
                    var utc = new d3_date();
                    utc._ = date;
                    return local(utc);
                } finally {
                    d3_date = Date;
                }
            }
            format.parse = function(string) {
                try {
                    d3_date = d3_date_utc;
                    var date = local.parse(string);
                    return date && date._;
                } finally {
                    d3_date = Date;
                }
            };
            format.toString = local.toString;
            return format;
        };
        d3_time_format.multi = d3_time_format.utc.multi = d3_time_formatMulti;
        var d3_time_periodLookup = d3.map(), d3_time_dayRe = d3_time_formatRe(locale_days), d3_time_dayLookup = d3_time_formatLookup(locale_days), d3_time_dayAbbrevRe = d3_time_formatRe(locale_shortDays), d3_time_dayAbbrevLookup = d3_time_formatLookup(locale_shortDays), d3_time_monthRe = d3_time_formatRe(locale_months), d3_time_monthLookup = d3_time_formatLookup(locale_months), d3_time_monthAbbrevRe = d3_time_formatRe(locale_shortMonths), d3_time_monthAbbrevLookup = d3_time_formatLookup(locale_shortMonths);
        locale_periods.forEach(function(p, i) {
            d3_time_periodLookup.set(p.toLowerCase(), i);
        });
        var d3_time_formats = {
            a: function(d) {
                return locale_shortDays[d.getDay()];
            },
            A: function(d) {
                return locale_days[d.getDay()];
            },
            b: function(d) {
                return locale_shortMonths[d.getMonth()];
            },
            B: function(d) {
                return locale_months[d.getMonth()];
            },
            c: d3_time_format(locale_dateTime),
            d: function(d, p) {
                return d3_time_formatPad(d.getDate(), p, 2);
            },
            e: function(d, p) {
                return d3_time_formatPad(d.getDate(), p, 2);
            },
            H: function(d, p) {
                return d3_time_formatPad(d.getHours(), p, 2);
            },
            I: function(d, p) {
                return d3_time_formatPad(d.getHours() % 12 || 12, p, 2);
            },
            j: function(d, p) {
                return d3_time_formatPad(1 + d3_time.dayOfYear(d), p, 3);
            },
            L: function(d, p) {
                return d3_time_formatPad(d.getMilliseconds(), p, 3);
            },
            m: function(d, p) {
                return d3_time_formatPad(d.getMonth() + 1, p, 2);
            },
            M: function(d, p) {
                return d3_time_formatPad(d.getMinutes(), p, 2);
            },
            p: function(d) {
                return locale_periods[+(d.getHours() >= 12)];
            },
            S: function(d, p) {
                return d3_time_formatPad(d.getSeconds(), p, 2);
            },
            U: function(d, p) {
                return d3_time_formatPad(d3_time.sundayOfYear(d), p, 2);
            },
            w: function(d) {
                return d.getDay();
            },
            W: function(d, p) {
                return d3_time_formatPad(d3_time.mondayOfYear(d), p, 2);
            },
            x: d3_time_format(locale_date),
            X: d3_time_format(locale_time),
            y: function(d, p) {
                return d3_time_formatPad(d.getFullYear() % 100, p, 2);
            },
            Y: function(d, p) {
                return d3_time_formatPad(d.getFullYear() % 1e4, p, 4);
            },
            Z: d3_time_zone,
            "%": function() {
                return "%";
            }
        };
        var d3_time_parsers = {
            a: d3_time_parseWeekdayAbbrev,
            A: d3_time_parseWeekday,
            b: d3_time_parseMonthAbbrev,
            B: d3_time_parseMonth,
            c: d3_time_parseLocaleFull,
            d: d3_time_parseDay,
            e: d3_time_parseDay,
            H: d3_time_parseHour24,
            I: d3_time_parseHour24,
            j: d3_time_parseDayOfYear,
            L: d3_time_parseMilliseconds,
            m: d3_time_parseMonthNumber,
            M: d3_time_parseMinutes,
            p: d3_time_parseAmPm,
            S: d3_time_parseSeconds,
            U: d3_time_parseWeekNumberSunday,
            w: d3_time_parseWeekdayNumber,
            W: d3_time_parseWeekNumberMonday,
            x: d3_time_parseLocaleDate,
            X: d3_time_parseLocaleTime,
            y: d3_time_parseYear,
            Y: d3_time_parseFullYear,
            Z: d3_time_parseZone,
            "%": d3_time_parseLiteralPercent
        };
        function d3_time_parseWeekdayAbbrev(date, string, i) {
            d3_time_dayAbbrevRe.lastIndex = 0;
            var n = d3_time_dayAbbrevRe.exec(string.slice(i));
            return n ? (date.w = d3_time_dayAbbrevLookup.get(n[0].toLowerCase()), 
            i + n[0].length) : -1;
        }
        function d3_time_parseWeekday(date, string, i) {
            d3_time_dayRe.lastIndex = 0;
            var n = d3_time_dayRe.exec(string.slice(i));
            return n ? (date.w = d3_time_dayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
        }
        function d3_time_parseMonthAbbrev(date, string, i) {
            d3_time_monthAbbrevRe.lastIndex = 0;
            var n = d3_time_monthAbbrevRe.exec(string.slice(i));
            return n ? (date.m = d3_time_monthAbbrevLookup.get(n[0].toLowerCase()), 
            i + n[0].length) : -1;
        }
        function d3_time_parseMonth(date, string, i) {
            d3_time_monthRe.lastIndex = 0;
            var n = d3_time_monthRe.exec(string.slice(i));
            return n ? (date.m = d3_time_monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;
        }
        function d3_time_parseLocaleFull(date, string, i) {
            return d3_time_parse(date, d3_time_formats.c.toString(), string, i);
        }
        function d3_time_parseLocaleDate(date, string, i) {
            return d3_time_parse(date, d3_time_formats.x.toString(), string, i);
        }
        function d3_time_parseLocaleTime(date, string, i) {
            return d3_time_parse(date, d3_time_formats.X.toString(), string, i);
        }
        function d3_time_parseAmPm(date, string, i) {
            var n = d3_time_periodLookup.get(string.slice(i, i += 2).toLowerCase());
            return n == null ? -1 : (date.p = n, i);
        }
        return d3_time_format;
    }
    var d3_time_formatPads = {
        "-": "",
        _: " ",
        0: "0"
    }, d3_time_numberRe = /^\s*\d+/, d3_time_percentRe = /^%/;
    function d3_time_formatPad(value, fill, width) {
        var sign = value < 0 ? "-" : "", string = (sign ? -value : value) + "", length = string.length;
        return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string);
    }
    function d3_time_formatRe(names) {
        return new RegExp("^(?:" + names.map(d3.requote).join("|") + ")", "i");
    }
    function d3_time_formatLookup(names) {
        var map = new d3_Map(), i = -1, n = names.length;
        while (++i < n) map.set(names[i].toLowerCase(), i);
        return map;
    }
    function d3_time_parseWeekdayNumber(date, string, i) {
        d3_time_numberRe.lastIndex = 0;
        var n = d3_time_numberRe.exec(string.slice(i, i + 1));
        return n ? (date.w = +n[0], i + n[0].length) : -1;
    }
    function d3_time_parseWeekNumberSunday(date, string, i) {
        d3_time_numberRe.lastIndex = 0;
        var n = d3_time_numberRe.exec(string.slice(i));
        return n ? (date.U = +n[0], i + n[0].length) : -1;
    }
    function d3_time_parseWeekNumberMonday(date, string, i) {
        d3_time_numberRe.lastIndex = 0;
        var n = d3_time_numberRe.exec(string.slice(i));
        return n ? (date.W = +n[0], i + n[0].length) : -1;
    }
    function d3_time_parseFullYear(date, string, i) {
        d3_time_numberRe.lastIndex = 0;
        var n = d3_time_numberRe.exec(string.slice(i, i + 4));
        return n ? (date.y = +n[0], i + n[0].length) : -1;
    }
    function d3_time_parseYear(date, string, i) {
        d3_time_numberRe.lastIndex = 0;
        var n = d3_time_numberRe.exec(string.slice(i, i + 2));
        return n ? (date.y = d3_time_expandYear(+n[0]), i + n[0].length) : -1;
    }
    function d3_time_parseZone(date, string, i) {
        return /^[+-]\d{4}$/.test(string = string.slice(i, i + 5)) ? (date.Z = -string, 
        i + 5) : -1;
    }
    function d3_time_expandYear(d) {
        return d + (d > 68 ? 1900 : 2e3);
    }
    function d3_time_parseMonthNumber(date, string, i) {
        d3_time_numberRe.lastIndex = 0;
        var n = d3_time_numberRe.exec(string.slice(i, i + 2));
        return n ? (date.m = n[0] - 1, i + n[0].length) : -1;
    }
    function d3_time_parseDay(date, string, i) {
        d3_time_numberRe.lastIndex = 0;
        var n = d3_time_numberRe.exec(string.slice(i, i + 2));
        return n ? (date.d = +n[0], i + n[0].length) : -1;
    }
    function d3_time_parseDayOfYear(date, string, i) {
        d3_time_numberRe.lastIndex = 0;
        var n = d3_time_numberRe.exec(string.slice(i, i + 3));
        return n ? (date.j = +n[0], i + n[0].length) : -1;
    }
    function d3_time_parseHour24(date, string, i) {
        d3_time_numberRe.lastIndex = 0;
        var n = d3_time_numberRe.exec(string.slice(i, i + 2));
        return n ? (date.H = +n[0], i + n[0].length) : -1;
    }
    function d3_time_parseMinutes(date, string, i) {
        d3_time_numberRe.lastIndex = 0;
        var n = d3_time_numberRe.exec(string.slice(i, i + 2));
        return n ? (date.M = +n[0], i + n[0].length) : -1;
    }
    function d3_time_parseSeconds(date, string, i) {
        d3_time_numberRe.lastIndex = 0;
        var n = d3_time_numberRe.exec(string.slice(i, i + 2));
        return n ? (date.S = +n[0], i + n[0].length) : -1;
    }
    function d3_time_parseMilliseconds(date, string, i) {
        d3_time_numberRe.lastIndex = 0;
        var n = d3_time_numberRe.exec(string.slice(i, i + 3));
        return n ? (date.L = +n[0], i + n[0].length) : -1;
    }
    function d3_time_zone(d) {
        var z = d.getTimezoneOffset(), zs = z > 0 ? "-" : "+", zh = abs(z) / 60 | 0, zm = abs(z) % 60;
        return zs + d3_time_formatPad(zh, "0", 2) + d3_time_formatPad(zm, "0", 2);
    }
    function d3_time_parseLiteralPercent(date, string, i) {
        d3_time_percentRe.lastIndex = 0;
        var n = d3_time_percentRe.exec(string.slice(i, i + 1));
        return n ? i + n[0].length : -1;
    }
    function d3_time_formatMulti(formats) {
        var n = formats.length, i = -1;
        while (++i < n) formats[i][0] = this(formats[i][0]);
        return function(date) {
            var i = 0, f = formats[i];
            while (!f[1](date)) f = formats[++i];
            return f[0](date);
        };
    }
    d3.locale = function(locale) {
        return {
            numberFormat: d3_locale_numberFormat(locale),
            timeFormat: d3_locale_timeFormat(locale)
        };
    };
    var d3_locale_enUS = d3.locale({
        decimal: ".",
        thousands: ",",
        grouping: [ 3 ],
        currency: [ "$", "" ],
        dateTime: "%a %b %e %X %Y",
        date: "%m/%d/%Y",
        time: "%H:%M:%S",
        periods: [ "AM", "PM" ],
        days: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ],
        shortDays: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ],
        months: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ],
        shortMonths: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]
    });
    d3.format = d3_locale_enUS.numberFormat;
    d3.geo = {};
    function d3_adder() {}
    d3_adder.prototype = {
        s: 0,
        t: 0,
        add: function(y) {
            d3_adderSum(y, this.t, d3_adderTemp);
            d3_adderSum(d3_adderTemp.s, this.s, this);
            if (this.s) this.t += d3_adderTemp.t; else this.s = d3_adderTemp.t;
        },
        reset: function() {
            this.s = this.t = 0;
        },
        valueOf: function() {
            return this.s;
        }
    };
    var d3_adderTemp = new d3_adder();
    function d3_adderSum(a, b, o) {
        var x = o.s = a + b, bv = x - a, av = x - bv;
        o.t = a - av + (b - bv);
    }
    d3.geo.stream = function(object, listener) {
        if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) {
            d3_geo_streamObjectType[object.type](object, listener);
        } else {
            d3_geo_streamGeometry(object, listener);
        }
    };
    function d3_geo_streamGeometry(geometry, listener) {
        if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) {
            d3_geo_streamGeometryType[geometry.type](geometry, listener);
        }
    }
    var d3_geo_streamObjectType = {
        Feature: function(feature, listener) {
            d3_geo_streamGeometry(feature.geometry, listener);
        },
        FeatureCollection: function(object, listener) {
            var features = object.features, i = -1, n = features.length;
            while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener);
        }
    };
    var d3_geo_streamGeometryType = {
        Sphere: function(object, listener) {
            listener.sphere();
        },
        Point: function(object, listener) {
            object = object.coordinates;
            listener.point(object[0], object[1], object[2]);
        },
        MultiPoint: function(object, listener) {
            var coordinates = object.coordinates, i = -1, n = coordinates.length;
            while (++i < n) object = coordinates[i], listener.point(object[0], object[1], object[2]);
        },
        LineString: function(object, listener) {
            d3_geo_streamLine(object.coordinates, listener, 0);
        },
        MultiLineString: function(object, listener) {
            var coordinates = object.coordinates, i = -1, n = coordinates.length;
            while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0);
        },
        Polygon: function(object, listener) {
            d3_geo_streamPolygon(object.coordinates, listener);
        },
        MultiPolygon: function(object, listener) {
            var coordinates = object.coordinates, i = -1, n = coordinates.length;
            while (++i < n) d3_geo_streamPolygon(coordinates[i], listener);
        },
        GeometryCollection: function(object, listener) {
            var geometries = object.geometries, i = -1, n = geometries.length;
            while (++i < n) d3_geo_streamGeometry(geometries[i], listener);
        }
    };
    function d3_geo_streamLine(coordinates, listener, closed) {
        var i = -1, n = coordinates.length - closed, coordinate;
        listener.lineStart();
        while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1], coordinate[2]);
        listener.lineEnd();
    }
    function d3_geo_streamPolygon(coordinates, listener) {
        var i = -1, n = coordinates.length;
        listener.polygonStart();
        while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1);
        listener.polygonEnd();
    }
    d3.geo.area = function(object) {
        d3_geo_areaSum = 0;
        d3.geo.stream(object, d3_geo_area);
        return d3_geo_areaSum;
    };
    var d3_geo_areaSum, d3_geo_areaRingSum = new d3_adder();
    var d3_geo_area = {
        sphere: function() {
            d3_geo_areaSum += 4 * π;
        },
        point: d3_noop,
        lineStart: d3_noop,
        lineEnd: d3_noop,
        polygonStart: function() {
            d3_geo_areaRingSum.reset();
            d3_geo_area.lineStart = d3_geo_areaRingStart;
        },
        polygonEnd: function() {
            var area = 2 * d3_geo_areaRingSum;
            d3_geo_areaSum += area < 0 ? 4 * π + area : area;
            d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop;
        }
    };
    function d3_geo_areaRingStart() {
        var λ00, φ00, λ0, cosφ0, sinφ0;
        d3_geo_area.point = function(λ, φ) {
            d3_geo_area.point = nextPoint;
            λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4), 
            sinφ0 = Math.sin(φ);
        };
        function nextPoint(λ, φ) {
            λ *= d3_radians;
            φ = φ * d3_radians / 2 + π / 4;
            var dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u = cosφ0 * cosφ + k * Math.cos(adλ), v = k * sdλ * Math.sin(adλ);
            d3_geo_areaRingSum.add(Math.atan2(v, u));
            λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ;
        }
        d3_geo_area.lineEnd = function() {
            nextPoint(λ00, φ00);
        };
    }
    function d3_geo_cartesian(spherical) {
        var λ = spherical[0], φ = spherical[1], cosφ = Math.cos(φ);
        return [ cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ) ];
    }
    function d3_geo_cartesianDot(a, b) {
        return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
    }
    function d3_geo_cartesianCross(a, b) {
        return [ a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0] ];
    }
    function d3_geo_cartesianAdd(a, b) {
        a[0] += b[0];
        a[1] += b[1];
        a[2] += b[2];
    }
    function d3_geo_cartesianScale(vector, k) {
        return [ vector[0] * k, vector[1] * k, vector[2] * k ];
    }
    function d3_geo_cartesianNormalize(d) {
        var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
        d[0] /= l;
        d[1] /= l;
        d[2] /= l;
    }
    function d3_geo_spherical(cartesian) {
        return [ Math.atan2(cartesian[1], cartesian[0]), d3_asin(cartesian[2]) ];
    }
    function d3_geo_sphericalEqual(a, b) {
        return abs(a[0] - b[0]) < ε && abs(a[1] - b[1]) < ε;
    }
    d3.geo.bounds = function() {
        var λ0, φ0, λ1, φ1, λ_, λ__, φ__, p0, dλSum, ranges, range;
        var bound = {
            point: point,
            lineStart: lineStart,
            lineEnd: lineEnd,
            polygonStart: function() {
                bound.point = ringPoint;
                bound.lineStart = ringStart;
                bound.lineEnd = ringEnd;
                dλSum = 0;
                d3_geo_area.polygonStart();
            },
            polygonEnd: function() {
                d3_geo_area.polygonEnd();
                bound.point = point;
                bound.lineStart = lineStart;
                bound.lineEnd = lineEnd;
                if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90); else if (dλSum > ε) φ1 = 90; else if (dλSum < -ε) φ0 = -90;
                range[0] = λ0, range[1] = λ1;
            }
        };
        function point(λ, φ) {
            ranges.push(range = [ λ0 = λ, λ1 = λ ]);
            if (φ < φ0) φ0 = φ;
            if (φ > φ1) φ1 = φ;
        }
        function linePoint(λ, φ) {
            var p = d3_geo_cartesian([ λ * d3_radians, φ * d3_radians ]);
            if (p0) {
                var normal = d3_geo_cartesianCross(p0, p), equatorial = [ normal[1], -normal[0], 0 ], inflection = d3_geo_cartesianCross(equatorial, normal);
                d3_geo_cartesianNormalize(inflection);
                inflection = d3_geo_spherical(inflection);
                var dλ = λ - λ_, s = dλ > 0 ? 1 : -1, λi = inflection[0] * d3_degrees * s, antimeridian = abs(dλ) > 180;
                if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) {
                    var φi = inflection[1] * d3_degrees;
                    if (φi > φ1) φ1 = φi;
                } else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) {
                    var φi = -inflection[1] * d3_degrees;
                    if (φi < φ0) φ0 = φi;
                } else {
                    if (φ < φ0) φ0 = φ;
                    if (φ > φ1) φ1 = φ;
                }
                if (antimeridian) {
                    if (λ < λ_) {
                        if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ;
                    } else {
                        if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ;
                    }
                } else {
                    if (λ1 >= λ0) {
                        if (λ < λ0) λ0 = λ;
                        if (λ > λ1) λ1 = λ;
                    } else {
                        if (λ > λ_) {
                            if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ;
                        } else {
                            if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ;
                        }
                    }
                }
            } else {
                point(λ, φ);
            }
            p0 = p, λ_ = λ;
        }
        function lineStart() {
            bound.point = linePoint;
        }
        function lineEnd() {
            range[0] = λ0, range[1] = λ1;
            bound.point = point;
            p0 = null;
        }
        function ringPoint(λ, φ) {
            if (p0) {
                var dλ = λ - λ_;
                dλSum += abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ;
            } else λ__ = λ, φ__ = φ;
            d3_geo_area.point(λ, φ);
            linePoint(λ, φ);
        }
        function ringStart() {
            d3_geo_area.lineStart();
        }
        function ringEnd() {
            ringPoint(λ__, φ__);
            d3_geo_area.lineEnd();
            if (abs(dλSum) > ε) λ0 = -(λ1 = 180);
            range[0] = λ0, range[1] = λ1;
            p0 = null;
        }
        function angle(λ0, λ1) {
            return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1;
        }
        function compareRanges(a, b) {
            return a[0] - b[0];
        }
        function withinRange(x, range) {
            return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;
        }
        return function(feature) {
            φ1 = λ1 = -(λ0 = φ0 = Infinity);
            ranges = [];
            d3.geo.stream(feature, bound);
            var n = ranges.length;
            if (n) {
                ranges.sort(compareRanges);
                for (var i = 1, a = ranges[0], b, merged = [ a ]; i < n; ++i) {
                    b = ranges[i];
                    if (withinRange(b[0], a) || withinRange(b[1], a)) {
                        if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1];
                        if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0];
                    } else {
                        merged.push(a = b);
                    }
                }
                var best = -Infinity, dλ;
                for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, 
                ++i) {
                    b = merged[i];
                    if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1];
                }
            }
            ranges = range = null;
            return λ0 === Infinity || φ0 === Infinity ? [ [ NaN, NaN ], [ NaN, NaN ] ] : [ [ λ0, φ0 ], [ λ1, φ1 ] ];
        };
    }();
    d3.geo.centroid = function(object) {
        d3_geo_centroidW0 = d3_geo_centroidW1 = d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;
        d3.geo.stream(object, d3_geo_centroid);
        var x = d3_geo_centroidX2, y = d3_geo_centroidY2, z = d3_geo_centroidZ2, m = x * x + y * y + z * z;
        if (m < ε2) {
            x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1;
            if (d3_geo_centroidW1 < ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, 
            z = d3_geo_centroidZ0;
            m = x * x + y * y + z * z;
            if (m < ε2) return [ NaN, NaN ];
        }
        return [ Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees ];
    };
    var d3_geo_centroidW0, d3_geo_centroidW1, d3_geo_centroidX0, d3_geo_centroidY0, d3_geo_centroidZ0, d3_geo_centroidX1, d3_geo_centroidY1, d3_geo_centroidZ1, d3_geo_centroidX2, d3_geo_centroidY2, d3_geo_centroidZ2;
    var d3_geo_centroid = {
        sphere: d3_noop,
        point: d3_geo_centroidPoint,
        lineStart: d3_geo_centroidLineStart,
        lineEnd: d3_geo_centroidLineEnd,
        polygonStart: function() {
            d3_geo_centroid.lineStart = d3_geo_centroidRingStart;
        },
        polygonEnd: function() {
            d3_geo_centroid.lineStart = d3_geo_centroidLineStart;
        }
    };
    function d3_geo_centroidPoint(λ, φ) {
        λ *= d3_radians;
        var cosφ = Math.cos(φ *= d3_radians);
        d3_geo_centroidPointXYZ(cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ));
    }
    function d3_geo_centroidPointXYZ(x, y, z) {
        ++d3_geo_centroidW0;
        d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0;
        d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0;
        d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0;
    }
    function d3_geo_centroidLineStart() {
        var x0, y0, z0;
        d3_geo_centroid.point = function(λ, φ) {
            λ *= d3_radians;
            var cosφ = Math.cos(φ *= d3_radians);
            x0 = cosφ * Math.cos(λ);
            y0 = cosφ * Math.sin(λ);
            z0 = Math.sin(φ);
            d3_geo_centroid.point = nextPoint;
            d3_geo_centroidPointXYZ(x0, y0, z0);
        };
        function nextPoint(λ, φ) {
            λ *= d3_radians;
            var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), w = Math.atan2(Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z);
            d3_geo_centroidW1 += w;
            d3_geo_centroidX1 += w * (x0 + (x0 = x));
            d3_geo_centroidY1 += w * (y0 + (y0 = y));
            d3_geo_centroidZ1 += w * (z0 + (z0 = z));
            d3_geo_centroidPointXYZ(x0, y0, z0);
        }
    }
    function d3_geo_centroidLineEnd() {
        d3_geo_centroid.point = d3_geo_centroidPoint;
    }
    function d3_geo_centroidRingStart() {
        var λ00, φ00, x0, y0, z0;
        d3_geo_centroid.point = function(λ, φ) {
            λ00 = λ, φ00 = φ;
            d3_geo_centroid.point = nextPoint;
            λ *= d3_radians;
            var cosφ = Math.cos(φ *= d3_radians);
            x0 = cosφ * Math.cos(λ);
            y0 = cosφ * Math.sin(λ);
            z0 = Math.sin(φ);
            d3_geo_centroidPointXYZ(x0, y0, z0);
        };
        d3_geo_centroid.lineEnd = function() {
            nextPoint(λ00, φ00);
            d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd;
            d3_geo_centroid.point = d3_geo_centroidPoint;
        };
        function nextPoint(λ, φ) {
            λ *= d3_radians;
            var cosφ = Math.cos(φ *= d3_radians), x = cosφ * Math.cos(λ), y = cosφ * Math.sin(λ), z = Math.sin(φ), cx = y0 * z - z0 * y, cy = z0 * x - x0 * z, cz = x0 * y - y0 * x, m = Math.sqrt(cx * cx + cy * cy + cz * cz), u = x0 * x + y0 * y + z0 * z, v = m && -d3_acos(u) / m, w = Math.atan2(m, u);
            d3_geo_centroidX2 += v * cx;
            d3_geo_centroidY2 += v * cy;
            d3_geo_centroidZ2 += v * cz;
            d3_geo_centroidW1 += w;
            d3_geo_centroidX1 += w * (x0 + (x0 = x));
            d3_geo_centroidY1 += w * (y0 + (y0 = y));
            d3_geo_centroidZ1 += w * (z0 + (z0 = z));
            d3_geo_centroidPointXYZ(x0, y0, z0);
        }
    }
    function d3_geo_compose(a, b) {
        function compose(x, y) {
            return x = a(x, y), b(x[0], x[1]);
        }
        if (a.invert && b.invert) compose.invert = function(x, y) {
            return x = b.invert(x, y), x && a.invert(x[0], x[1]);
        };
        return compose;
    }
    function d3_true() {
        return true;
    }
    function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) {
        var subject = [], clip = [];
        segments.forEach(function(segment) {
            if ((n = segment.length - 1) <= 0) return;
            var n, p0 = segment[0], p1 = segment[n];
            if (d3_geo_sphericalEqual(p0, p1)) {
                listener.lineStart();
                for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]);
                listener.lineEnd();
                return;
            }
            var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true), b = new d3_geo_clipPolygonIntersection(p0, null, a, false);
            a.o = b;
            subject.push(a);
            clip.push(b);
            a = new d3_geo_clipPolygonIntersection(p1, segment, null, false);
            b = new d3_geo_clipPolygonIntersection(p1, null, a, true);
            a.o = b;
            subject.push(a);
            clip.push(b);
        });
        clip.sort(compare);
        d3_geo_clipPolygonLinkCircular(subject);
        d3_geo_clipPolygonLinkCircular(clip);
        if (!subject.length) return;
        for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) {
            clip[i].e = entry = !entry;
        }
        var start = subject[0], points, point;
        while (1) {
            var current = start, isSubject = true;
            while (current.v) if ((current = current.n) === start) return;
            points = current.z;
            listener.lineStart();
            do {
                current.v = current.o.v = true;
                if (current.e) {
                    if (isSubject) {
                        for (var i = 0, n = points.length; i < n; ++i) listener.point((point = points[i])[0], point[1]);
                    } else {
                        interpolate(current.x, current.n.x, 1, listener);
                    }
                    current = current.n;
                } else {
                    if (isSubject) {
                        points = current.p.z;
                        for (var i = points.length - 1; i >= 0; --i) listener.point((point = points[i])[0], point[1]);
                    } else {
                        interpolate(current.x, current.p.x, -1, listener);
                    }
                    current = current.p;
                }
                current = current.o;
                points = current.z;
                isSubject = !isSubject;
            } while (!current.v);
            listener.lineEnd();
        }
    }
    function d3_geo_clipPolygonLinkCircular(array) {
        if (!(n = array.length)) return;
        var n, i = 0, a = array[0], b;
        while (++i < n) {
            a.n = b = array[i];
            b.p = a;
            a = b;
        }
        a.n = b = array[0];
        b.p = a;
    }
    function d3_geo_clipPolygonIntersection(point, points, other, entry) {
        this.x = point;
        this.z = points;
        this.o = other;
        this.e = entry;
        this.v = false;
        this.n = this.p = null;
    }
    function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) {
        return function(rotate, listener) {
            var line = clipLine(listener), rotatedClipStart = rotate.invert(clipStart[0], clipStart[1]);
            var clip = {
                point: point,
                lineStart: lineStart,
                lineEnd: lineEnd,
                polygonStart: function() {
                    clip.point = pointRing;
                    clip.lineStart = ringStart;
                    clip.lineEnd = ringEnd;
                    segments = [];
                    polygon = [];
                },
                polygonEnd: function() {
                    clip.point = point;
                    clip.lineStart = lineStart;
                    clip.lineEnd = lineEnd;
                    segments = d3.merge(segments);
                    var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon);
                    if (segments.length) {
                        if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
                        d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener);
                    } else if (clipStartInside) {
                        if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
                        listener.lineStart();
                        interpolate(null, null, 1, listener);
                        listener.lineEnd();
                    }
                    if (polygonStarted) listener.polygonEnd(), polygonStarted = false;
                    segments = polygon = null;
                },
                sphere: function() {
                    listener.polygonStart();
                    listener.lineStart();
                    interpolate(null, null, 1, listener);
                    listener.lineEnd();
                    listener.polygonEnd();
                }
            };
            function point(λ, φ) {
                var point = rotate(λ, φ);
                if (pointVisible(λ = point[0], φ = point[1])) listener.point(λ, φ);
            }
            function pointLine(λ, φ) {
                var point = rotate(λ, φ);
                line.point(point[0], point[1]);
            }
            function lineStart() {
                clip.point = pointLine;
                line.lineStart();
            }
            function lineEnd() {
                clip.point = point;
                line.lineEnd();
            }
            var segments;
            var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygonStarted = false, polygon, ring;
            function pointRing(λ, φ) {
                ring.push([ λ, φ ]);
                var point = rotate(λ, φ);
                ringListener.point(point[0], point[1]);
            }
            function ringStart() {
                ringListener.lineStart();
                ring = [];
            }
            function ringEnd() {
                pointRing(ring[0][0], ring[0][1]);
                ringListener.lineEnd();
                var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length;
                ring.pop();
                polygon.push(ring);
                ring = null;
                if (!n) return;
                if (clean & 1) {
                    segment = ringSegments[0];
                    var n = segment.length - 1, i = -1, point;
                    if (n > 0) {
                        if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
                        listener.lineStart();
                        while (++i < n) listener.point((point = segment[i])[0], point[1]);
                        listener.lineEnd();
                    }
                    return;
                }
                if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
                segments.push(ringSegments.filter(d3_geo_clipSegmentLength1));
            }
            return clip;
        };
    }
    function d3_geo_clipSegmentLength1(segment) {
        return segment.length > 1;
    }
    function d3_geo_clipBufferListener() {
        var lines = [], line;
        return {
            lineStart: function() {
                lines.push(line = []);
            },
            point: function(λ, φ) {
                line.push([ λ, φ ]);
            },
            lineEnd: d3_noop,
            buffer: function() {
                var buffer = lines;
                lines = [];
                line = null;
                return buffer;
            },
            rejoin: function() {
                if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));
            }
        };
    }
    function d3_geo_clipSort(a, b) {
        return ((a = a.x)[0] < 0 ? a[1] - halfπ - ε : halfπ - a[1]) - ((b = b.x)[0] < 0 ? b[1] - halfπ - ε : halfπ - b[1]);
    }
    var d3_geo_clipAntimeridian = d3_geo_clip(d3_true, d3_geo_clipAntimeridianLine, d3_geo_clipAntimeridianInterpolate, [ -π, -π / 2 ]);
    function d3_geo_clipAntimeridianLine(listener) {
        var λ0 = NaN, φ0 = NaN, sλ0 = NaN, clean;
        return {
            lineStart: function() {
                listener.lineStart();
                clean = 1;
            },
            point: function(λ1, φ1) {
                var sλ1 = λ1 > 0 ? π : -π, dλ = abs(λ1 - λ0);
                if (abs(dλ - π) < ε) {
                    listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? halfπ : -halfπ);
                    listener.point(sλ0, φ0);
                    listener.lineEnd();
                    listener.lineStart();
                    listener.point(sλ1, φ0);
                    listener.point(λ1, φ0);
                    clean = 0;
                } else if (sλ0 !== sλ1 && dλ >= π) {
                    if (abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε;
                    if (abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε;
                    φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1);
                    listener.point(sλ0, φ0);
                    listener.lineEnd();
                    listener.lineStart();
                    listener.point(sλ1, φ0);
                    clean = 0;
                }
                listener.point(λ0 = λ1, φ0 = φ1);
                sλ0 = sλ1;
            },
            lineEnd: function() {
                listener.lineEnd();
                λ0 = φ0 = NaN;
            },
            clean: function() {
                return 2 - clean;
            }
        };
    }
    function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) {
        var cosφ0, cosφ1, sinλ0_λ1 = Math.sin(λ0 - λ1);
        return abs(sinλ0_λ1) > ε ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1) - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0)) / (cosφ0 * cosφ1 * sinλ0_λ1)) : (φ0 + φ1) / 2;
    }
    function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) {
        var φ;
        if (from == null) {
            φ = direction * halfπ;
            listener.point(-π, φ);
            listener.point(0, φ);
            listener.point(π, φ);
            listener.point(π, 0);
            listener.point(π, -φ);
            listener.point(0, -φ);
            listener.point(-π, -φ);
            listener.point(-π, 0);
            listener.point(-π, φ);
        } else if (abs(from[0] - to[0]) > ε) {
            var s = from[0] < to[0] ? π : -π;
            φ = direction * s / 2;
            listener.point(-s, φ);
            listener.point(0, φ);
            listener.point(s, φ);
        } else {
            listener.point(to[0], to[1]);
        }
    }
    function d3_geo_pointInPolygon(point, polygon) {
        var meridian = point[0], parallel = point[1], meridianNormal = [ Math.sin(meridian), -Math.cos(meridian), 0 ], polarAngle = 0, winding = 0;
        d3_geo_areaRingSum.reset();
        for (var i = 0, n = polygon.length; i < n; ++i) {
            var ring = polygon[i], m = ring.length;
            if (!m) continue;
            var point0 = ring[0], λ0 = point0[0], φ0 = point0[1] / 2 + π / 4, sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), j = 1;
            while (true) {
                if (j === m) j = 0;
                point = ring[j];
                var λ = point[0], φ = point[1] / 2 + π / 4, sinφ = Math.sin(φ), cosφ = Math.cos(φ), dλ = λ - λ0, sdλ = dλ >= 0 ? 1 : -1, adλ = sdλ * dλ, antimeridian = adλ > π, k = sinφ0 * sinφ;
                d3_geo_areaRingSum.add(Math.atan2(k * sdλ * Math.sin(adλ), cosφ0 * cosφ + k * Math.cos(adλ)));
                polarAngle += antimeridian ? dλ + sdλ * τ : dλ;
                if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) {
                    var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point));
                    d3_geo_cartesianNormalize(arc);
                    var intersection = d3_geo_cartesianCross(meridianNormal, arc);
                    d3_geo_cartesianNormalize(intersection);
                    var φarc = (antimeridian ^ dλ >= 0 ? -1 : 1) * d3_asin(intersection[2]);
                    if (parallel > φarc || parallel === φarc && (arc[0] || arc[1])) {
                        winding += antimeridian ^ dλ >= 0 ? 1 : -1;
                    }
                }
                if (!j++) break;
                λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ, point0 = point;
            }
        }
        return (polarAngle < -ε || polarAngle < ε && d3_geo_areaRingSum < 0) ^ winding & 1;
    }
    function d3_geo_clipCircle(radius) {
        var cr = Math.cos(radius), smallRadius = cr > 0, notHemisphere = abs(cr) > ε, interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians);
        return d3_geo_clip(visible, clipLine, interpolate, smallRadius ? [ 0, -radius ] : [ -π, radius - π ]);
        function visible(λ, φ) {
            return Math.cos(λ) * Math.cos(φ) > cr;
        }
        function clipLine(listener) {
            var point0, c0, v0, v00, clean;
            return {
                lineStart: function() {
                    v00 = v0 = false;
                    clean = 1;
                },
                point: function(λ, φ) {
                    var point1 = [ λ, φ ], point2, v = visible(λ, φ), c = smallRadius ? v ? 0 : code(λ, φ) : v ? code(λ + (λ < 0 ? π : -π), φ) : 0;
                    if (!point0 && (v00 = v0 = v)) listener.lineStart();
                    if (v !== v0) {
                        point2 = intersect(point0, point1);
                        if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) {
                            point1[0] += ε;
                            point1[1] += ε;
                            v = visible(point1[0], point1[1]);
                        }
                    }
                    if (v !== v0) {
                        clean = 0;
                        if (v) {
                            listener.lineStart();
                            point2 = intersect(point1, point0);
                            listener.point(point2[0], point2[1]);
                        } else {
                            point2 = intersect(point0, point1);
                            listener.point(point2[0], point2[1]);
                            listener.lineEnd();
                        }
                        point0 = point2;
                    } else if (notHemisphere && point0 && smallRadius ^ v) {
                        var t;
                        if (!(c & c0) && (t = intersect(point1, point0, true))) {
                            clean = 0;
                            if (smallRadius) {
                                listener.lineStart();
                                listener.point(t[0][0], t[0][1]);
                                listener.point(t[1][0], t[1][1]);
                                listener.lineEnd();
                            } else {
                                listener.point(t[1][0], t[1][1]);
                                listener.lineEnd();
                                listener.lineStart();
                                listener.point(t[0][0], t[0][1]);
                            }
                        }
                    }
                    if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) {
                        listener.point(point1[0], point1[1]);
                    }
                    point0 = point1, v0 = v, c0 = c;
                },
                lineEnd: function() {
                    if (v0) listener.lineEnd();
                    point0 = null;
                },
                clean: function() {
                    return clean | (v00 && v0) << 1;
                }
            };
        }
        function intersect(a, b, two) {
            var pa = d3_geo_cartesian(a), pb = d3_geo_cartesian(b);
            var n1 = [ 1, 0, 0 ], n2 = d3_geo_cartesianCross(pa, pb), n2n2 = d3_geo_cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2;
            if (!determinant) return !two && a;
            var c1 = cr * n2n2 / determinant, c2 = -cr * n1n2 / determinant, n1xn2 = d3_geo_cartesianCross(n1, n2), A = d3_geo_cartesianScale(n1, c1), B = d3_geo_cartesianScale(n2, c2);
            d3_geo_cartesianAdd(A, B);
            var u = n1xn2, w = d3_geo_cartesianDot(A, u), uu = d3_geo_cartesianDot(u, u), t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1);
            if (t2 < 0) return;
            var t = Math.sqrt(t2), q = d3_geo_cartesianScale(u, (-w - t) / uu);
            d3_geo_cartesianAdd(q, A);
            q = d3_geo_spherical(q);
            if (!two) return q;
            var λ0 = a[0], λ1 = b[0], φ0 = a[1], φ1 = b[1], z;
            if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z;
            var δλ = λ1 - λ0, polar = abs(δλ - π) < ε, meridian = polar || δλ < ε;
            if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z;
            if (meridian ? polar ? φ0 + φ1 > 0 ^ q[1] < (abs(q[0] - λ0) < ε ? φ0 : φ1) : φ0 <= q[1] && q[1] <= φ1 : δλ > π ^ (λ0 <= q[0] && q[0] <= λ1)) {
                var q1 = d3_geo_cartesianScale(u, (-w + t) / uu);
                d3_geo_cartesianAdd(q1, A);
                return [ q, d3_geo_spherical(q1) ];
            }
        }
        function code(λ, φ) {
            var r = smallRadius ? radius : π - radius, code = 0;
            if (λ < -r) code |= 1; else if (λ > r) code |= 2;
            if (φ < -r) code |= 4; else if (φ > r) code |= 8;
            return code;
        }
    }
    function d3_geom_clipLine(x0, y0, x1, y1) {
        return function(line) {
            var a = line.a, b = line.b, ax = a.x, ay = a.y, bx = b.x, by = b.y, t0 = 0, t1 = 1, dx = bx - ax, dy = by - ay, r;
            r = x0 - ax;
            if (!dx && r > 0) return;
            r /= dx;
            if (dx < 0) {
                if (r < t0) return;
                if (r < t1) t1 = r;
            } else if (dx > 0) {
                if (r > t1) return;
                if (r > t0) t0 = r;
            }
            r = x1 - ax;
            if (!dx && r < 0) return;
            r /= dx;
            if (dx < 0) {
                if (r > t1) return;
                if (r > t0) t0 = r;
            } else if (dx > 0) {
                if (r < t0) return;
                if (r < t1) t1 = r;
            }
            r = y0 - ay;
            if (!dy && r > 0) return;
            r /= dy;
            if (dy < 0) {
                if (r < t0) return;
                if (r < t1) t1 = r;
            } else if (dy > 0) {
                if (r > t1) return;
                if (r > t0) t0 = r;
            }
            r = y1 - ay;
            if (!dy && r < 0) return;
            r /= dy;
            if (dy < 0) {
                if (r > t1) return;
                if (r > t0) t0 = r;
            } else if (dy > 0) {
                if (r < t0) return;
                if (r < t1) t1 = r;
            }
            if (t0 > 0) line.a = {
                x: ax + t0 * dx,
                y: ay + t0 * dy
            };
            if (t1 < 1) line.b = {
                x: ax + t1 * dx,
                y: ay + t1 * dy
            };
            return line;
        };
    }
    var d3_geo_clipExtentMAX = 1e9;
    d3.geo.clipExtent = function() {
        var x0, y0, x1, y1, stream, clip, clipExtent = {
            stream: function(output) {
                if (stream) stream.valid = false;
                stream = clip(output);
                stream.valid = true;
                return stream;
            },
            extent: function(_) {
                if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ];
                clip = d3_geo_clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]);
                if (stream) stream.valid = false, stream = null;
                return clipExtent;
            }
        };
        return clipExtent.extent([ [ 0, 0 ], [ 960, 500 ] ]);
    };
    function d3_geo_clipExtent(x0, y0, x1, y1) {
        return function(listener) {
            var listener_ = listener, bufferListener = d3_geo_clipBufferListener(), clipLine = d3_geom_clipLine(x0, y0, x1, y1), segments, polygon, ring;
            var clip = {
                point: point,
                lineStart: lineStart,
                lineEnd: lineEnd,
                polygonStart: function() {
                    listener = bufferListener;
                    segments = [];
                    polygon = [];
                    clean = true;
                },
                polygonEnd: function() {
                    listener = listener_;
                    segments = d3.merge(segments);
                    var clipStartInside = insidePolygon([ x0, y1 ]), inside = clean && clipStartInside, visible = segments.length;
                    if (inside || visible) {
                        listener.polygonStart();
                        if (inside) {
                            listener.lineStart();
                            interpolate(null, null, 1, listener);
                            listener.lineEnd();
                        }
                        if (visible) {
                            d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener);
                        }
                        listener.polygonEnd();
                    }
                    segments = polygon = ring = null;
                }
            };
            function insidePolygon(p) {
                var wn = 0, n = polygon.length, y = p[1];
                for (var i = 0; i < n; ++i) {
                    for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) {
                        b = v[j];
                        if (a[1] <= y) {
                            if (b[1] > y && d3_cross2d(a, b, p) > 0) ++wn;
                        } else {
                            if (b[1] <= y && d3_cross2d(a, b, p) < 0) --wn;
                        }
                        a = b;
                    }
                }
                return wn !== 0;
            }
            function interpolate(from, to, direction, listener) {
                var a = 0, a1 = 0;
                if (from == null || (a = corner(from, direction)) !== (a1 = corner(to, direction)) || comparePoints(from, to) < 0 ^ direction > 0) {
                    do {
                        listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);
                    } while ((a = (a + direction + 4) % 4) !== a1);
                } else {
                    listener.point(to[0], to[1]);
                }
            }
            function pointVisible(x, y) {
                return x0 <= x && x <= x1 && y0 <= y && y <= y1;
            }
            function point(x, y) {
                if (pointVisible(x, y)) listener.point(x, y);
            }
            var x__, y__, v__, x_, y_, v_, first, clean;
            function lineStart() {
                clip.point = linePoint;
                if (polygon) polygon.push(ring = []);
                first = true;
                v_ = false;
                x_ = y_ = NaN;
            }
            function lineEnd() {
                if (segments) {
                    linePoint(x__, y__);
                    if (v__ && v_) bufferListener.rejoin();
                    segments.push(bufferListener.buffer());
                }
                clip.point = point;
                if (v_) listener.lineEnd();
            }
            function linePoint(x, y) {
                x = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, x));
                y = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, y));
                var v = pointVisible(x, y);
                if (polygon) ring.push([ x, y ]);
                if (first) {
                    x__ = x, y__ = y, v__ = v;
                    first = false;
                    if (v) {
                        listener.lineStart();
                        listener.point(x, y);
                    }
                } else {
                    if (v && v_) listener.point(x, y); else {
                        var l = {
                            a: {
                                x: x_,
                                y: y_
                            },
                            b: {
                                x: x,
                                y: y
                            }
                        };
                        if (clipLine(l)) {
                            if (!v_) {
                                listener.lineStart();
                                listener.point(l.a.x, l.a.y);
                            }
                            listener.point(l.b.x, l.b.y);
                            if (!v) listener.lineEnd();
                            clean = false;
                        } else if (v) {
                            listener.lineStart();
                            listener.point(x, y);
                            clean = false;
                        }
                    }
                }
                x_ = x, y_ = y, v_ = v;
            }
            return clip;
        };
        function corner(p, direction) {
            return abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3 : abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1 : abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2;
        }
        function compare(a, b) {
            return comparePoints(a.x, b.x);
        }
        function comparePoints(a, b) {
            var ca = corner(a, 1), cb = corner(b, 1);
            return ca !== cb ? ca - cb : ca === 0 ? b[1] - a[1] : ca === 1 ? a[0] - b[0] : ca === 2 ? a[1] - b[1] : b[0] - a[0];
        }
    }
    function d3_geo_conic(projectAt) {
        var φ0 = 0, φ1 = π / 3, m = d3_geo_projectionMutator(projectAt), p = m(φ0, φ1);
        p.parallels = function(_) {
            if (!arguments.length) return [ φ0 / π * 180, φ1 / π * 180 ];
            return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180);
        };
        return p;
    }
    function d3_geo_conicEqualArea(φ0, φ1) {
        var sinφ0 = Math.sin(φ0), n = (sinφ0 + Math.sin(φ1)) / 2, C = 1 + sinφ0 * (2 * n - sinφ0), ρ0 = Math.sqrt(C) / n;
        function forward(λ, φ) {
            var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n;
            return [ ρ * Math.sin(λ *= n), ρ0 - ρ * Math.cos(λ) ];
        }
        forward.invert = function(x, y) {
            var ρ0_y = ρ0 - y;
            return [ Math.atan2(x, ρ0_y) / n, d3_asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n)) ];
        };
        return forward;
    }
    (d3.geo.conicEqualArea = function() {
        return d3_geo_conic(d3_geo_conicEqualArea);
    }).raw = d3_geo_conicEqualArea;
    d3.geo.albers = function() {
        return d3.geo.conicEqualArea().rotate([ 96, 0 ]).center([ -.6, 38.7 ]).parallels([ 29.5, 45.5 ]).scale(1070);
    };
    d3.geo.albersUsa = function() {
        var lower48 = d3.geo.albers();
        var alaska = d3.geo.conicEqualArea().rotate([ 154, 0 ]).center([ -2, 58.5 ]).parallels([ 55, 65 ]);
        var hawaii = d3.geo.conicEqualArea().rotate([ 157, 0 ]).center([ -3, 19.9 ]).parallels([ 8, 18 ]);
        var point, pointStream = {
            point: function(x, y) {
                point = [ x, y ];
            }
        }, lower48Point, alaskaPoint, hawaiiPoint;
        function albersUsa(coordinates) {
            var x = coordinates[0], y = coordinates[1];
            point = null;
            (lower48Point(x, y), point) || (alaskaPoint(x, y), point) || hawaiiPoint(x, y);
            return point;
        }
        albersUsa.invert = function(coordinates) {
            var k = lower48.scale(), t = lower48.translate(), x = (coordinates[0] - t[0]) / k, y = (coordinates[1] - t[1]) / k;
            return (y >= .12 && y < .234 && x >= -.425 && x < -.214 ? alaska : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii : lower48).invert(coordinates);
        };
        albersUsa.stream = function(stream) {
            var lower48Stream = lower48.stream(stream), alaskaStream = alaska.stream(stream), hawaiiStream = hawaii.stream(stream);
            return {
                point: function(x, y) {
                    lower48Stream.point(x, y);
                    alaskaStream.point(x, y);
                    hawaiiStream.point(x, y);
                },
                sphere: function() {
                    lower48Stream.sphere();
                    alaskaStream.sphere();
                    hawaiiStream.sphere();
                },
                lineStart: function() {
                    lower48Stream.lineStart();
                    alaskaStream.lineStart();
                    hawaiiStream.lineStart();
                },
                lineEnd: function() {
                    lower48Stream.lineEnd();
                    alaskaStream.lineEnd();
                    hawaiiStream.lineEnd();
                },
                polygonStart: function() {
                    lower48Stream.polygonStart();
                    alaskaStream.polygonStart();
                    hawaiiStream.polygonStart();
                },
                polygonEnd: function() {
                    lower48Stream.polygonEnd();
                    alaskaStream.polygonEnd();
                    hawaiiStream.polygonEnd();
                }
            };
        };
        albersUsa.precision = function(_) {
            if (!arguments.length) return lower48.precision();
            lower48.precision(_);
            alaska.precision(_);
            hawaii.precision(_);
            return albersUsa;
        };
        albersUsa.scale = function(_) {
            if (!arguments.length) return lower48.scale();
            lower48.scale(_);
            alaska.scale(_ * .35);
            hawaii.scale(_);
            return albersUsa.translate(lower48.translate());
        };
        albersUsa.translate = function(_) {
            if (!arguments.length) return lower48.translate();
            var k = lower48.scale(), x = +_[0], y = +_[1];
            lower48Point = lower48.translate(_).clipExtent([ [ x - .455 * k, y - .238 * k ], [ x + .455 * k, y + .238 * k ] ]).stream(pointStream).point;
            alaskaPoint = alaska.translate([ x - .307 * k, y + .201 * k ]).clipExtent([ [ x - .425 * k + ε, y + .12 * k + ε ], [ x - .214 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point;
            hawaiiPoint = hawaii.translate([ x - .205 * k, y + .212 * k ]).clipExtent([ [ x - .214 * k + ε, y + .166 * k + ε ], [ x - .115 * k - ε, y + .234 * k - ε ] ]).stream(pointStream).point;
            return albersUsa;
        };
        return albersUsa.scale(1070);
    };
    var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = {
        point: d3_noop,
        lineStart: d3_noop,
        lineEnd: d3_noop,
        polygonStart: function() {
            d3_geo_pathAreaPolygon = 0;
            d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart;
        },
        polygonEnd: function() {
            d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop;
            d3_geo_pathAreaSum += abs(d3_geo_pathAreaPolygon / 2);
        }
    };
    function d3_geo_pathAreaRingStart() {
        var x00, y00, x0, y0;
        d3_geo_pathArea.point = function(x, y) {
            d3_geo_pathArea.point = nextPoint;
            x00 = x0 = x, y00 = y0 = y;
        };
        function nextPoint(x, y) {
            d3_geo_pathAreaPolygon += y0 * x - x0 * y;
            x0 = x, y0 = y;
        }
        d3_geo_pathArea.lineEnd = function() {
            nextPoint(x00, y00);
        };
    }
    var d3_geo_pathBoundsX0, d3_geo_pathBoundsY0, d3_geo_pathBoundsX1, d3_geo_pathBoundsY1;
    var d3_geo_pathBounds = {
        point: d3_geo_pathBoundsPoint,
        lineStart: d3_noop,
        lineEnd: d3_noop,
        polygonStart: d3_noop,
        polygonEnd: d3_noop
    };
    function d3_geo_pathBoundsPoint(x, y) {
        if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x;
        if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x;
        if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y;
        if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y;
    }
    function d3_geo_pathBuffer() {
        var pointCircle = d3_geo_pathBufferCircle(4.5), buffer = [];
        var stream = {
            point: point,
            lineStart: function() {
                stream.point = pointLineStart;
            },
            lineEnd: lineEnd,
            polygonStart: function() {
                stream.lineEnd = lineEndPolygon;
            },
            polygonEnd: function() {
                stream.lineEnd = lineEnd;
                stream.point = point;
            },
            pointRadius: function(_) {
                pointCircle = d3_geo_pathBufferCircle(_);
                return stream;
            },
            result: function() {
                if (buffer.length) {
                    var result = buffer.join("");
                    buffer = [];
                    return result;
                }
            }
        };
        function point(x, y) {
            buffer.push("M", x, ",", y, pointCircle);
        }
        function pointLineStart(x, y) {
            buffer.push("M", x, ",", y);
            stream.point = pointLine;
        }
        function pointLine(x, y) {
            buffer.push("L", x, ",", y);
        }
        function lineEnd() {
            stream.point = point;
        }
        function lineEndPolygon() {
            buffer.push("Z");
        }
        return stream;
    }
    function d3_geo_pathBufferCircle(radius) {
        return "m0," + radius + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius + "z";
    }
    var d3_geo_pathCentroid = {
        point: d3_geo_pathCentroidPoint,
        lineStart: d3_geo_pathCentroidLineStart,
        lineEnd: d3_geo_pathCentroidLineEnd,
        polygonStart: function() {
            d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart;
        },
        polygonEnd: function() {
            d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
            d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart;
            d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd;
        }
    };
    function d3_geo_pathCentroidPoint(x, y) {
        d3_geo_centroidX0 += x;
        d3_geo_centroidY0 += y;
        ++d3_geo_centroidZ0;
    }
    function d3_geo_pathCentroidLineStart() {
        var x0, y0;
        d3_geo_pathCentroid.point = function(x, y) {
            d3_geo_pathCentroid.point = nextPoint;
            d3_geo_pathCentroidPoint(x0 = x, y0 = y);
        };
        function nextPoint(x, y) {
            var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
            d3_geo_centroidX1 += z * (x0 + x) / 2;
            d3_geo_centroidY1 += z * (y0 + y) / 2;
            d3_geo_centroidZ1 += z;
            d3_geo_pathCentroidPoint(x0 = x, y0 = y);
        }
    }
    function d3_geo_pathCentroidLineEnd() {
        d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
    }
    function d3_geo_pathCentroidRingStart() {
        var x00, y00, x0, y0;
        d3_geo_pathCentroid.point = function(x, y) {
            d3_geo_pathCentroid.point = nextPoint;
            d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y);
        };
        function nextPoint(x, y) {
            var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
            d3_geo_centroidX1 += z * (x0 + x) / 2;
            d3_geo_centroidY1 += z * (y0 + y) / 2;
            d3_geo_centroidZ1 += z;
            z = y0 * x - x0 * y;
            d3_geo_centroidX2 += z * (x0 + x);
            d3_geo_centroidY2 += z * (y0 + y);
            d3_geo_centroidZ2 += z * 3;
            d3_geo_pathCentroidPoint(x0 = x, y0 = y);
        }
        d3_geo_pathCentroid.lineEnd = function() {
            nextPoint(x00, y00);
        };
    }
    function d3_geo_pathContext(context) {
        var pointRadius = 4.5;
        var stream = {
            point: point,
            lineStart: function() {
                stream.point = pointLineStart;
            },
            lineEnd: lineEnd,
            polygonStart: function() {
                stream.lineEnd = lineEndPolygon;
            },
            polygonEnd: function() {
                stream.lineEnd = lineEnd;
                stream.point = point;
            },
            pointRadius: function(_) {
                pointRadius = _;
                return stream;
            },
            result: d3_noop
        };
        function point(x, y) {
            context.moveTo(x + pointRadius, y);
            context.arc(x, y, pointRadius, 0, τ);
        }
        function pointLineStart(x, y) {
            context.moveTo(x, y);
            stream.point = pointLine;
        }
        function pointLine(x, y) {
            context.lineTo(x, y);
        }
        function lineEnd() {
            stream.point = point;
        }
        function lineEndPolygon() {
            context.closePath();
        }
        return stream;
    }
    function d3_geo_resample(project) {
        var δ2 = .5, cosMinDistance = Math.cos(30 * d3_radians), maxDepth = 16;
        function resample(stream) {
            return (maxDepth ? resampleRecursive : resampleNone)(stream);
        }
        function resampleNone(stream) {
            return d3_geo_transformPoint(stream, function(x, y) {
                x = project(x, y);
                stream.point(x[0], x[1]);
            });
        }
        function resampleRecursive(stream) {
            var λ00, φ00, x00, y00, a00, b00, c00, λ0, x0, y0, a0, b0, c0;
            var resample = {
                point: point,
                lineStart: lineStart,
                lineEnd: lineEnd,
                polygonStart: function() {
                    stream.polygonStart();
                    resample.lineStart = ringStart;
                },
                polygonEnd: function() {
                    stream.polygonEnd();
                    resample.lineStart = lineStart;
                }
            };
            function point(x, y) {
                x = project(x, y);
                stream.point(x[0], x[1]);
            }
            function lineStart() {
                x0 = NaN;
                resample.point = linePoint;
                stream.lineStart();
            }
            function linePoint(λ, φ) {
                var c = d3_geo_cartesian([ λ, φ ]), p = project(λ, φ);
                resampleLineTo(x0, y0, λ0, a0, b0, c0, x0 = p[0], y0 = p[1], λ0 = λ, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream);
                stream.point(x0, y0);
            }
            function lineEnd() {
                resample.point = point;
                stream.lineEnd();
            }
            function ringStart() {
                lineStart();
                resample.point = ringPoint;
                resample.lineEnd = ringEnd;
            }
            function ringPoint(λ, φ) {
                linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, 
                c00 = c0;
                resample.point = linePoint;
            }
            function ringEnd() {
                resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream);
                resample.lineEnd = lineEnd;
                lineEnd();
            }
            return resample;
        }
        function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) {
            var dx = x1 - x0, dy = y1 - y0, d2 = dx * dx + dy * dy;
            if (d2 > 4 * δ2 && depth--) {
                var a = a0 + a1, b = b0 + b1, c = c0 + c1, m = Math.sqrt(a * a + b * b + c * c), φ2 = Math.asin(c /= m), λ2 = abs(abs(c) - 1) < ε || abs(λ0 - λ1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a), p = project(λ2, φ2), x2 = p[0], y2 = p[1], dx2 = x2 - x0, dy2 = y2 - y0, dz = dy * dx2 - dx * dy2;
                if (dz * dz / d2 > δ2 || abs((dx * dx2 + dy * dy2) / d2 - .5) > .3 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) {
                    resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream);
                    stream.point(x2, y2);
                    resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream);
                }
            }
        }
        resample.precision = function(_) {
            if (!arguments.length) return Math.sqrt(δ2);
            maxDepth = (δ2 = _ * _) > 0 && 16;
            return resample;
        };
        return resample;
    }
    d3.geo.path = function() {
        var pointRadius = 4.5, projection, context, projectStream, contextStream, cacheStream;
        function path(object) {
            if (object) {
                if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments));
                if (!cacheStream || !cacheStream.valid) cacheStream = projectStream(contextStream);
                d3.geo.stream(object, cacheStream);
            }
            return contextStream.result();
        }
        path.area = function(object) {
            d3_geo_pathAreaSum = 0;
            d3.geo.stream(object, projectStream(d3_geo_pathArea));
            return d3_geo_pathAreaSum;
        };
        path.centroid = function(object) {
            d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 = d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 = d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;
            d3.geo.stream(object, projectStream(d3_geo_pathCentroid));
            return d3_geo_centroidZ2 ? [ d3_geo_centroidX2 / d3_geo_centroidZ2, d3_geo_centroidY2 / d3_geo_centroidZ2 ] : d3_geo_centroidZ1 ? [ d3_geo_centroidX1 / d3_geo_centroidZ1, d3_geo_centroidY1 / d3_geo_centroidZ1 ] : d3_geo_centroidZ0 ? [ d3_geo_centroidX0 / d3_geo_centroidZ0, d3_geo_centroidY0 / d3_geo_centroidZ0 ] : [ NaN, NaN ];
        };
        path.bounds = function(object) {
            d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity);
            d3.geo.stream(object, projectStream(d3_geo_pathBounds));
            return [ [ d3_geo_pathBoundsX0, d3_geo_pathBoundsY0 ], [ d3_geo_pathBoundsX1, d3_geo_pathBoundsY1 ] ];
        };
        path.projection = function(_) {
            if (!arguments.length) return projection;
            projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity;
            return reset();
        };
        path.context = function(_) {
            if (!arguments.length) return context;
            contextStream = (context = _) == null ? new d3_geo_pathBuffer() : new d3_geo_pathContext(_);
            if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius);
            return reset();
        };
        path.pointRadius = function(_) {
            if (!arguments.length) return pointRadius;
            pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), 
            +_);
            return path;
        };
        function reset() {
            cacheStream = null;
            return path;
        }
        return path.projection(d3.geo.albersUsa()).context(null);
    };
    function d3_geo_pathProjectStream(project) {
        var resample = d3_geo_resample(function(x, y) {
            return project([ x * d3_degrees, y * d3_degrees ]);
        });
        return function(stream) {
            return d3_geo_projectionRadians(resample(stream));
        };
    }
    d3.geo.transform = function(methods) {
        return {
            stream: function(stream) {
                var transform = new d3_geo_transform(stream);
                for (var k in methods) transform[k] = methods[k];
                return transform;
            }
        };
    };
    function d3_geo_transform(stream) {
        this.stream = stream;
    }
    d3_geo_transform.prototype = {
        point: function(x, y) {
            this.stream.point(x, y);
        },
        sphere: function() {
            this.stream.sphere();
        },
        lineStart: function() {
            this.stream.lineStart();
        },
        lineEnd: function() {
            this.stream.lineEnd();
        },
        polygonStart: function() {
            this.stream.polygonStart();
        },
        polygonEnd: function() {
            this.stream.polygonEnd();
        }
    };
    function d3_geo_transformPoint(stream, point) {
        return {
            point: point,
            sphere: function() {
                stream.sphere();
            },
            lineStart: function() {
                stream.lineStart();
            },
            lineEnd: function() {
                stream.lineEnd();
            },
            polygonStart: function() {
                stream.polygonStart();
            },
            polygonEnd: function() {
                stream.polygonEnd();
            }
        };
    }
    d3.geo.projection = d3_geo_projection;
    d3.geo.projectionMutator = d3_geo_projectionMutator;
    function d3_geo_projection(project) {
        return d3_geo_projectionMutator(function() {
            return project;
        })();
    }
    function d3_geo_projectionMutator(projectAt) {
        var project, rotate, projectRotate, projectResample = d3_geo_resample(function(x, y) {
            x = project(x, y);
            return [ x[0] * k + δx, δy - x[1] * k ];
        }), k = 150, x = 480, y = 250, λ = 0, φ = 0, δλ = 0, δφ = 0, δγ = 0, δx, δy, preclip = d3_geo_clipAntimeridian, postclip = d3_identity, clipAngle = null, clipExtent = null, stream;
        function projection(point) {
            point = projectRotate(point[0] * d3_radians, point[1] * d3_radians);
            return [ point[0] * k + δx, δy - point[1] * k ];
        }
        function invert(point) {
            point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k);
            return point && [ point[0] * d3_degrees, point[1] * d3_degrees ];
        }
        projection.stream = function(output) {
            if (stream) stream.valid = false;
            stream = d3_geo_projectionRadians(preclip(rotate, projectResample(postclip(output))));
            stream.valid = true;
            return stream;
        };
        projection.clipAngle = function(_) {
            if (!arguments.length) return clipAngle;
            preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians);
            return invalidate();
        };
        projection.clipExtent = function(_) {
            if (!arguments.length) return clipExtent;
            clipExtent = _;
            postclip = _ ? d3_geo_clipExtent(_[0][0], _[0][1], _[1][0], _[1][1]) : d3_identity;
            return invalidate();
        };
        projection.scale = function(_) {
            if (!arguments.length) return k;
            k = +_;
            return reset();
        };
        projection.translate = function(_) {
            if (!arguments.length) return [ x, y ];
            x = +_[0];
            y = +_[1];
            return reset();
        };
        projection.center = function(_) {
            if (!arguments.length) return [ λ * d3_degrees, φ * d3_degrees ];
            λ = _[0] % 360 * d3_radians;
            φ = _[1] % 360 * d3_radians;
            return reset();
        };
        projection.rotate = function(_) {
            if (!arguments.length) return [ δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees ];
            δλ = _[0] % 360 * d3_radians;
            δφ = _[1] % 360 * d3_radians;
            δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0;
            return reset();
        };
        d3.rebind(projection, projectResample, "precision");
        function reset() {
            projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project);
            var center = project(λ, φ);
            δx = x - center[0] * k;
            δy = y + center[1] * k;
            return invalidate();
        }
        function invalidate() {
            if (stream) stream.valid = false, stream = null;
            return projection;
        }
        return function() {
            project = projectAt.apply(this, arguments);
            projection.invert = project.invert && invert;
            return reset();
        };
    }
    function d3_geo_projectionRadians(stream) {
        return d3_geo_transformPoint(stream, function(x, y) {
            stream.point(x * d3_radians, y * d3_radians);
        });
    }
    function d3_geo_equirectangular(λ, φ) {
        return [ λ, φ ];
    }
    (d3.geo.equirectangular = function() {
        return d3_geo_projection(d3_geo_equirectangular);
    }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular;
    d3.geo.rotation = function(rotate) {
        rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0);
        function forward(coordinates) {
            coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
            return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;
        }
        forward.invert = function(coordinates) {
            coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
            return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;
        };
        return forward;
    };
    function d3_geo_identityRotation(λ, φ) {
        return [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ];
    }
    d3_geo_identityRotation.invert = d3_geo_equirectangular;
    function d3_geo_rotation(δλ, δφ, δγ) {
        return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_identityRotation;
    }
    function d3_geo_forwardRotationλ(δλ) {
        return function(λ, φ) {
            return λ += δλ, [ λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ ];
        };
    }
    function d3_geo_rotationλ(δλ) {
        var rotation = d3_geo_forwardRotationλ(δλ);
        rotation.invert = d3_geo_forwardRotationλ(-δλ);
        return rotation;
    }
    function d3_geo_rotationφγ(δφ, δγ) {
        var cosδφ = Math.cos(δφ), sinδφ = Math.sin(δφ), cosδγ = Math.cos(δγ), sinδγ = Math.sin(δγ);
        function rotation(λ, φ) {
            var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδφ + x * sinδφ;
            return [ Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ), d3_asin(k * cosδγ + y * sinδγ) ];
        }
        rotation.invert = function(λ, φ) {
            var cosφ = Math.cos(φ), x = Math.cos(λ) * cosφ, y = Math.sin(λ) * cosφ, z = Math.sin(φ), k = z * cosδγ - y * sinδγ;
            return [ Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ), d3_asin(k * cosδφ - x * sinδφ) ];
        };
        return rotation;
    }
    d3.geo.circle = function() {
        var origin = [ 0, 0 ], angle, precision = 6, interpolate;
        function circle() {
            var center = typeof origin === "function" ? origin.apply(this, arguments) : origin, rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert, ring = [];
            interpolate(null, null, 1, {
                point: function(x, y) {
                    ring.push(x = rotate(x, y));
                    x[0] *= d3_degrees, x[1] *= d3_degrees;
                }
            });
            return {
                type: "Polygon",
                coordinates: [ ring ]
            };
        }
        circle.origin = function(x) {
            if (!arguments.length) return origin;
            origin = x;
            return circle;
        };
        circle.angle = function(x) {
            if (!arguments.length) return angle;
            interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians);
            return circle;
        };
        circle.precision = function(_) {
            if (!arguments.length) return precision;
            interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians);
            return circle;
        };
        return circle.angle(90);
    };
    function d3_geo_circleInterpolate(radius, precision) {
        var cr = Math.cos(radius), sr = Math.sin(radius);
        return function(from, to, direction, listener) {
            var step = direction * precision;
            if (from != null) {
                from = d3_geo_circleAngle(cr, from);
                to = d3_geo_circleAngle(cr, to);
                if (direction > 0 ? from < to : from > to) from += direction * τ;
            } else {
                from = radius + direction * τ;
                to = radius - .5 * step;
            }
            for (var point, t = from; direction > 0 ? t > to : t < to; t -= step) {
                listener.point((point = d3_geo_spherical([ cr, -sr * Math.cos(t), -sr * Math.sin(t) ]))[0], point[1]);
            }
        };
    }
    function d3_geo_circleAngle(cr, point) {
        var a = d3_geo_cartesian(point);
        a[0] -= cr;
        d3_geo_cartesianNormalize(a);
        var angle = d3_acos(-a[1]);
        return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI);
    }
    d3.geo.distance = function(a, b) {
        var Δλ = (b[0] - a[0]) * d3_radians, φ0 = a[1] * d3_radians, φ1 = b[1] * d3_radians, sinΔλ = Math.sin(Δλ), cosΔλ = Math.cos(Δλ), sinφ0 = Math.sin(φ0), cosφ0 = Math.cos(φ0), sinφ1 = Math.sin(φ1), cosφ1 = Math.cos(φ1), t;
        return Math.atan2(Math.sqrt((t = cosφ1 * sinΔλ) * t + (t = cosφ0 * sinφ1 - sinφ0 * cosφ1 * cosΔλ) * t), sinφ0 * sinφ1 + cosφ0 * cosφ1 * cosΔλ);
    };
    d3.geo.graticule = function() {
        var x1, x0, X1, X0, y1, y0, Y1, Y0, dx = 10, dy = dx, DX = 90, DY = 360, x, y, X, Y, precision = 2.5;
        function graticule() {
            return {
                type: "MultiLineString",
                coordinates: lines()
            };
        }
        function lines() {
            return d3.range(Math.ceil(X0 / DX) * DX, X1, DX).map(X).concat(d3.range(Math.ceil(Y0 / DY) * DY, Y1, DY).map(Y)).concat(d3.range(Math.ceil(x0 / dx) * dx, x1, dx).filter(function(x) {
                return abs(x % DX) > ε;
            }).map(x)).concat(d3.range(Math.ceil(y0 / dy) * dy, y1, dy).filter(function(y) {
                return abs(y % DY) > ε;
            }).map(y));
        }
        graticule.lines = function() {
            return lines().map(function(coordinates) {
                return {
                    type: "LineString",
                    coordinates: coordinates
                };
            });
        };
        graticule.outline = function() {
            return {
                type: "Polygon",
                coordinates: [ X(X0).concat(Y(Y1).slice(1), X(X1).reverse().slice(1), Y(Y0).reverse().slice(1)) ]
            };
        };
        graticule.extent = function(_) {
            if (!arguments.length) return graticule.minorExtent();
            return graticule.majorExtent(_).minorExtent(_);
        };
        graticule.majorExtent = function(_) {
            if (!arguments.length) return [ [ X0, Y0 ], [ X1, Y1 ] ];
            X0 = +_[0][0], X1 = +_[1][0];
            Y0 = +_[0][1], Y1 = +_[1][1];
            if (X0 > X1) _ = X0, X0 = X1, X1 = _;
            if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _;
            return graticule.precision(precision);
        };
        graticule.minorExtent = function(_) {
            if (!arguments.length) return [ [ x0, y0 ], [ x1, y1 ] ];
            x0 = +_[0][0], x1 = +_[1][0];
            y0 = +_[0][1], y1 = +_[1][1];
            if (x0 > x1) _ = x0, x0 = x1, x1 = _;
            if (y0 > y1) _ = y0, y0 = y1, y1 = _;
            return graticule.precision(precision);
        };
        graticule.step = function(_) {
            if (!arguments.length) return graticule.minorStep();
            return graticule.majorStep(_).minorStep(_);
        };
        graticule.majorStep = function(_) {
            if (!arguments.length) return [ DX, DY ];
            DX = +_[0], DY = +_[1];
            return graticule;
        };
        graticule.minorStep = function(_) {
            if (!arguments.length) return [ dx, dy ];
            dx = +_[0], dy = +_[1];
            return graticule;
        };
        graticule.precision = function(_) {
            if (!arguments.length) return precision;
            precision = +_;
            x = d3_geo_graticuleX(y0, y1, 90);
            y = d3_geo_graticuleY(x0, x1, precision);
            X = d3_geo_graticuleX(Y0, Y1, 90);
            Y = d3_geo_graticuleY(X0, X1, precision);
            return graticule;
        };
        return graticule.majorExtent([ [ -180, -90 + ε ], [ 180, 90 - ε ] ]).minorExtent([ [ -180, -80 - ε ], [ 180, 80 + ε ] ]);
    };
    function d3_geo_graticuleX(y0, y1, dy) {
        var y = d3.range(y0, y1 - ε, dy).concat(y1);
        return function(x) {
            return y.map(function(y) {
                return [ x, y ];
            });
        };
    }
    function d3_geo_graticuleY(x0, x1, dx) {
        var x = d3.range(x0, x1 - ε, dx).concat(x1);
        return function(y) {
            return x.map(function(x) {
                return [ x, y ];
            });
        };
    }
    function d3_source(d) {
        return d.source;
    }
    function d3_target(d) {
        return d.target;
    }
    d3.geo.greatArc = function() {
        var source = d3_source, source_, target = d3_target, target_;
        function greatArc() {
            return {
                type: "LineString",
                coordinates: [ source_ || source.apply(this, arguments), target_ || target.apply(this, arguments) ]
            };
        }
        greatArc.distance = function() {
            return d3.geo.distance(source_ || source.apply(this, arguments), target_ || target.apply(this, arguments));
        };
        greatArc.source = function(_) {
            if (!arguments.length) return source;
            source = _, source_ = typeof _ === "function" ? null : _;
            return greatArc;
        };
        greatArc.target = function(_) {
            if (!arguments.length) return target;
            target = _, target_ = typeof _ === "function" ? null : _;
            return greatArc;
        };
        greatArc.precision = function() {
            return arguments.length ? greatArc : 0;
        };
        return greatArc;
    };
    d3.geo.interpolate = function(source, target) {
        return d3_geo_interpolate(source[0] * d3_radians, source[1] * d3_radians, target[0] * d3_radians, target[1] * d3_radians);
    };
    function d3_geo_interpolate(x0, y0, x1, y1) {
        var cy0 = Math.cos(y0), sy0 = Math.sin(y0), cy1 = Math.cos(y1), sy1 = Math.sin(y1), kx0 = cy0 * Math.cos(x0), ky0 = cy0 * Math.sin(x0), kx1 = cy1 * Math.cos(x1), ky1 = cy1 * Math.sin(x1), d = 2 * Math.asin(Math.sqrt(d3_haversin(y1 - y0) + cy0 * cy1 * d3_haversin(x1 - x0))), k = 1 / Math.sin(d);
        var interpolate = d ? function(t) {
            var B = Math.sin(t *= d) * k, A = Math.sin(d - t) * k, x = A * kx0 + B * kx1, y = A * ky0 + B * ky1, z = A * sy0 + B * sy1;
            return [ Math.atan2(y, x) * d3_degrees, Math.atan2(z, Math.sqrt(x * x + y * y)) * d3_degrees ];
        } : function() {
            return [ x0 * d3_degrees, y0 * d3_degrees ];
        };
        interpolate.distance = d;
        return interpolate;
    }
    d3.geo.length = function(object) {
        d3_geo_lengthSum = 0;
        d3.geo.stream(object, d3_geo_length);
        return d3_geo_lengthSum;
    };
    var d3_geo_lengthSum;
    var d3_geo_length = {
        sphere: d3_noop,
        point: d3_noop,
        lineStart: d3_geo_lengthLineStart,
        lineEnd: d3_noop,
        polygonStart: d3_noop,
        polygonEnd: d3_noop
    };
    function d3_geo_lengthLineStart() {
        var λ0, sinφ0, cosφ0;
        d3_geo_length.point = function(λ, φ) {
            λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ);
            d3_geo_length.point = nextPoint;
        };
        d3_geo_length.lineEnd = function() {
            d3_geo_length.point = d3_geo_length.lineEnd = d3_noop;
        };
        function nextPoint(λ, φ) {
            var sinφ = Math.sin(φ *= d3_radians), cosφ = Math.cos(φ), t = abs((λ *= d3_radians) - λ0), cosΔλ = Math.cos(t);
            d3_geo_lengthSum += Math.atan2(Math.sqrt((t = cosφ * Math.sin(t)) * t + (t = cosφ0 * sinφ - sinφ0 * cosφ * cosΔλ) * t), sinφ0 * sinφ + cosφ0 * cosφ * cosΔλ);
            λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ;
        }
    }
    function d3_geo_azimuthal(scale, angle) {
        function azimuthal(λ, φ) {
            var cosλ = Math.cos(λ), cosφ = Math.cos(φ), k = scale(cosλ * cosφ);
            return [ k * cosφ * Math.sin(λ), k * Math.sin(φ) ];
        }
        azimuthal.invert = function(x, y) {
            var ρ = Math.sqrt(x * x + y * y), c = angle(ρ), sinc = Math.sin(c), cosc = Math.cos(c);
            return [ Math.atan2(x * sinc, ρ * cosc), Math.asin(ρ && y * sinc / ρ) ];
        };
        return azimuthal;
    }
    var d3_geo_azimuthalEqualArea = d3_geo_azimuthal(function(cosλcosφ) {
        return Math.sqrt(2 / (1 + cosλcosφ));
    }, function(ρ) {
        return 2 * Math.asin(ρ / 2);
    });
    (d3.geo.azimuthalEqualArea = function() {
        return d3_geo_projection(d3_geo_azimuthalEqualArea);
    }).raw = d3_geo_azimuthalEqualArea;
    var d3_geo_azimuthalEquidistant = d3_geo_azimuthal(function(cosλcosφ) {
        var c = Math.acos(cosλcosφ);
        return c && c / Math.sin(c);
    }, d3_identity);
    (d3.geo.azimuthalEquidistant = function() {
        return d3_geo_projection(d3_geo_azimuthalEquidistant);
    }).raw = d3_geo_azimuthalEquidistant;
    function d3_geo_conicConformal(φ0, φ1) {
        var cosφ0 = Math.cos(φ0), t = function(φ) {
            return Math.tan(π / 4 + φ / 2);
        }, n = φ0 === φ1 ? Math.sin(φ0) : Math.log(cosφ0 / Math.cos(φ1)) / Math.log(t(φ1) / t(φ0)), F = cosφ0 * Math.pow(t(φ0), n) / n;
        if (!n) return d3_geo_mercator;
        function forward(λ, φ) {
            if (F > 0) {
                if (φ < -halfπ + ε) φ = -halfπ + ε;
            } else {
                if (φ > halfπ - ε) φ = halfπ - ε;
            }
            var ρ = F / Math.pow(t(φ), n);
            return [ ρ * Math.sin(n * λ), F - ρ * Math.cos(n * λ) ];
        }
        forward.invert = function(x, y) {
            var ρ0_y = F - y, ρ = d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y);
            return [ Math.atan2(x, ρ0_y) / n, 2 * Math.atan(Math.pow(F / ρ, 1 / n)) - halfπ ];
        };
        return forward;
    }
    (d3.geo.conicConformal = function() {
        return d3_geo_conic(d3_geo_conicConformal);
    }).raw = d3_geo_conicConformal;
    function d3_geo_conicEquidistant(φ0, φ1) {
        var cosφ0 = Math.cos(φ0), n = φ0 === φ1 ? Math.sin(φ0) : (cosφ0 - Math.cos(φ1)) / (φ1 - φ0), G = cosφ0 / n + φ0;
        if (abs(n) < ε) return d3_geo_equirectangular;
        function forward(λ, φ) {
            var ρ = G - φ;
            return [ ρ * Math.sin(n * λ), G - ρ * Math.cos(n * λ) ];
        }
        forward.invert = function(x, y) {
            var ρ0_y = G - y;
            return [ Math.atan2(x, ρ0_y) / n, G - d3_sgn(n) * Math.sqrt(x * x + ρ0_y * ρ0_y) ];
        };
        return forward;
    }
    (d3.geo.conicEquidistant = function() {
        return d3_geo_conic(d3_geo_conicEquidistant);
    }).raw = d3_geo_conicEquidistant;
    var d3_geo_gnomonic = d3_geo_azimuthal(function(cosλcosφ) {
        return 1 / cosλcosφ;
    }, Math.atan);
    (d3.geo.gnomonic = function() {
        return d3_geo_projection(d3_geo_gnomonic);
    }).raw = d3_geo_gnomonic;
    function d3_geo_mercator(λ, φ) {
        return [ λ, Math.log(Math.tan(π / 4 + φ / 2)) ];
    }
    d3_geo_mercator.invert = function(x, y) {
        return [ x, 2 * Math.atan(Math.exp(y)) - halfπ ];
    };
    function d3_geo_mercatorProjection(project) {
        var m = d3_geo_projection(project), scale = m.scale, translate = m.translate, clipExtent = m.clipExtent, clipAuto;
        m.scale = function() {
            var v = scale.apply(m, arguments);
            return v === m ? clipAuto ? m.clipExtent(null) : m : v;
        };
        m.translate = function() {
            var v = translate.apply(m, arguments);
            return v === m ? clipAuto ? m.clipExtent(null) : m : v;
        };
        m.clipExtent = function(_) {
            var v = clipExtent.apply(m, arguments);
            if (v === m) {
                if (clipAuto = _ == null) {
                    var k = π * scale(), t = translate();
                    clipExtent([ [ t[0] - k, t[1] - k ], [ t[0] + k, t[1] + k ] ]);
                }
            } else if (clipAuto) {
                v = null;
            }
            return v;
        };
        return m.clipExtent(null);
    }
    (d3.geo.mercator = function() {
        return d3_geo_mercatorProjection(d3_geo_mercator);
    }).raw = d3_geo_mercator;
    var d3_geo_orthographic = d3_geo_azimuthal(function() {
        return 1;
    }, Math.asin);
    (d3.geo.orthographic = function() {
        return d3_geo_projection(d3_geo_orthographic);
    }).raw = d3_geo_orthographic;
    var d3_geo_stereographic = d3_geo_azimuthal(function(cosλcosφ) {
        return 1 / (1 + cosλcosφ);
    }, function(ρ) {
        return 2 * Math.atan(ρ);
    });
    (d3.geo.stereographic = function() {
        return d3_geo_projection(d3_geo_stereographic);
    }).raw = d3_geo_stereographic;
    function d3_geo_transverseMercator(λ, φ) {
        return [ Math.log(Math.tan(π / 4 + φ / 2)), -λ ];
    }
    d3_geo_transverseMercator.invert = function(x, y) {
        return [ -y, 2 * Math.atan(Math.exp(x)) - halfπ ];
    };
    (d3.geo.transverseMercator = function() {
        var projection = d3_geo_mercatorProjection(d3_geo_transverseMercator), center = projection.center, rotate = projection.rotate;
        projection.center = function(_) {
            return _ ? center([ -_[1], _[0] ]) : (_ = center(), [ _[1], -_[0] ]);
        };
        projection.rotate = function(_) {
            return _ ? rotate([ _[0], _[1], _.length > 2 ? _[2] + 90 : 90 ]) : (_ = rotate(), 
            [ _[0], _[1], _[2] - 90 ]);
        };
        return rotate([ 0, 0, 90 ]);
    }).raw = d3_geo_transverseMercator;
    d3.geom = {};
    function d3_geom_pointX(d) {
        return d[0];
    }
    function d3_geom_pointY(d) {
        return d[1];
    }
    d3.geom.hull = function(vertices) {
        var x = d3_geom_pointX, y = d3_geom_pointY;
        if (arguments.length) return hull(vertices);
        function hull(data) {
            if (data.length < 3) return [];
            var fx = d3_functor(x), fy = d3_functor(y), i, n = data.length, points = [], flippedPoints = [];
            for (i = 0; i < n; i++) {
                points.push([ +fx.call(this, data[i], i), +fy.call(this, data[i], i), i ]);
            }
            points.sort(d3_geom_hullOrder);
            for (i = 0; i < n; i++) flippedPoints.push([ points[i][0], -points[i][1] ]);
            var upper = d3_geom_hullUpper(points), lower = d3_geom_hullUpper(flippedPoints);
            var skipLeft = lower[0] === upper[0], skipRight = lower[lower.length - 1] === upper[upper.length - 1], polygon = [];
            for (i = upper.length - 1; i >= 0; --i) polygon.push(data[points[upper[i]][2]]);
            for (i = +skipLeft; i < lower.length - skipRight; ++i) polygon.push(data[points[lower[i]][2]]);
            return polygon;
        }
        hull.x = function(_) {
            return arguments.length ? (x = _, hull) : x;
        };
        hull.y = function(_) {
            return arguments.length ? (y = _, hull) : y;
        };
        return hull;
    };
    function d3_geom_hullUpper(points) {
        var n = points.length, hull = [ 0, 1 ], hs = 2;
        for (var i = 2; i < n; i++) {
            while (hs > 1 && d3_cross2d(points[hull[hs - 2]], points[hull[hs - 1]], points[i]) <= 0) --hs;
            hull[hs++] = i;
        }
        return hull.slice(0, hs);
    }
    function d3_geom_hullOrder(a, b) {
        return a[0] - b[0] || a[1] - b[1];
    }
    d3.geom.polygon = function(coordinates) {
        d3_subclass(coordinates, d3_geom_polygonPrototype);
        return coordinates;
    };
    var d3_geom_polygonPrototype = d3.geom.polygon.prototype = [];
    d3_geom_polygonPrototype.area = function() {
        var i = -1, n = this.length, a, b = this[n - 1], area = 0;
        while (++i < n) {
            a = b;
            b = this[i];
            area += a[1] * b[0] - a[0] * b[1];
        }
        return area * .5;
    };
    d3_geom_polygonPrototype.centroid = function(k) {
        var i = -1, n = this.length, x = 0, y = 0, a, b = this[n - 1], c;
        if (!arguments.length) k = -1 / (6 * this.area());
        while (++i < n) {
            a = b;
            b = this[i];
            c = a[0] * b[1] - b[0] * a[1];
            x += (a[0] + b[0]) * c;
            y += (a[1] + b[1]) * c;
        }
        return [ x * k, y * k ];
    };
    d3_geom_polygonPrototype.clip = function(subject) {
        var input, closed = d3_geom_polygonClosed(subject), i = -1, n = this.length - d3_geom_polygonClosed(this), j, m, a = this[n - 1], b, c, d;
        while (++i < n) {
            input = subject.slice();
            subject.length = 0;
            b = this[i];
            c = input[(m = input.length - closed) - 1];
            j = -1;
            while (++j < m) {
                d = input[j];
                if (d3_geom_polygonInside(d, a, b)) {
                    if (!d3_geom_polygonInside(c, a, b)) {
                        subject.push(d3_geom_polygonIntersect(c, d, a, b));
                    }
                    subject.push(d);
                } else if (d3_geom_polygonInside(c, a, b)) {
                    subject.push(d3_geom_polygonIntersect(c, d, a, b));
                }
                c = d;
            }
            if (closed) subject.push(subject[0]);
            a = b;
        }
        return subject;
    };
    function d3_geom_polygonInside(p, a, b) {
        return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]);
    }
    function d3_geom_polygonIntersect(c, d, a, b) {
        var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3, y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3, ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21);
        return [ x1 + ua * x21, y1 + ua * y21 ];
    }
    function d3_geom_polygonClosed(coordinates) {
        var a = coordinates[0], b = coordinates[coordinates.length - 1];
        return !(a[0] - b[0] || a[1] - b[1]);
    }
    var d3_geom_voronoiEdges, d3_geom_voronoiCells, d3_geom_voronoiBeaches, d3_geom_voronoiBeachPool = [], d3_geom_voronoiFirstCircle, d3_geom_voronoiCircles, d3_geom_voronoiCirclePool = [];
    function d3_geom_voronoiBeach() {
        d3_geom_voronoiRedBlackNode(this);
        this.edge = this.site = this.circle = null;
    }
    function d3_geom_voronoiCreateBeach(site) {
        var beach = d3_geom_voronoiBeachPool.pop() || new d3_geom_voronoiBeach();
        beach.site = site;
        return beach;
    }
    function d3_geom_voronoiDetachBeach(beach) {
        d3_geom_voronoiDetachCircle(beach);
        d3_geom_voronoiBeaches.remove(beach);
        d3_geom_voronoiBeachPool.push(beach);
        d3_geom_voronoiRedBlackNode(beach);
    }
    function d3_geom_voronoiRemoveBeach(beach) {
        var circle = beach.circle, x = circle.x, y = circle.cy, vertex = {
            x: x,
            y: y
        }, previous = beach.P, next = beach.N, disappearing = [ beach ];
        d3_geom_voronoiDetachBeach(beach);
        var lArc = previous;
        while (lArc.circle && abs(x - lArc.circle.x) < ε && abs(y - lArc.circle.cy) < ε) {
            previous = lArc.P;
            disappearing.unshift(lArc);
            d3_geom_voronoiDetachBeach(lArc);
            lArc = previous;
        }
        disappearing.unshift(lArc);
        d3_geom_voronoiDetachCircle(lArc);
        var rArc = next;
        while (rArc.circle && abs(x - rArc.circle.x) < ε && abs(y - rArc.circle.cy) < ε) {
            next = rArc.N;
            disappearing.push(rArc);
            d3_geom_voronoiDetachBeach(rArc);
            rArc = next;
        }
        disappearing.push(rArc);
        d3_geom_voronoiDetachCircle(rArc);
        var nArcs = disappearing.length, iArc;
        for (iArc = 1; iArc < nArcs; ++iArc) {
            rArc = disappearing[iArc];
            lArc = disappearing[iArc - 1];
            d3_geom_voronoiSetEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex);
        }
        lArc = disappearing[0];
        rArc = disappearing[nArcs - 1];
        rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, rArc.site, null, vertex);
        d3_geom_voronoiAttachCircle(lArc);
        d3_geom_voronoiAttachCircle(rArc);
    }
    function d3_geom_voronoiAddBeach(site) {
        var x = site.x, directrix = site.y, lArc, rArc, dxl, dxr, node = d3_geom_voronoiBeaches._;
        while (node) {
            dxl = d3_geom_voronoiLeftBreakPoint(node, directrix) - x;
            if (dxl > ε) node = node.L; else {
                dxr = x - d3_geom_voronoiRightBreakPoint(node, directrix);
                if (dxr > ε) {
                    if (!node.R) {
                        lArc = node;
                        break;
                    }
                    node = node.R;
                } else {
                    if (dxl > -ε) {
                        lArc = node.P;
                        rArc = node;
                    } else if (dxr > -ε) {
                        lArc = node;
                        rArc = node.N;
                    } else {
                        lArc = rArc = node;
                    }
                    break;
                }
            }
        }
        var newArc = d3_geom_voronoiCreateBeach(site);
        d3_geom_voronoiBeaches.insert(lArc, newArc);
        if (!lArc && !rArc) return;
        if (lArc === rArc) {
            d3_geom_voronoiDetachCircle(lArc);
            rArc = d3_geom_voronoiCreateBeach(lArc.site);
            d3_geom_voronoiBeaches.insert(newArc, rArc);
            newArc.edge = rArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site);
            d3_geom_voronoiAttachCircle(lArc);
            d3_geom_voronoiAttachCircle(rArc);
            return;
        }
        if (!rArc) {
            newArc.edge = d3_geom_voronoiCreateEdge(lArc.site, newArc.site);
            return;
        }
        d3_geom_voronoiDetachCircle(lArc);
        d3_geom_voronoiDetachCircle(rArc);
        var lSite = lArc.site, ax = lSite.x, ay = lSite.y, bx = site.x - ax, by = site.y - ay, rSite = rArc.site, cx = rSite.x - ax, cy = rSite.y - ay, d = 2 * (bx * cy - by * cx), hb = bx * bx + by * by, hc = cx * cx + cy * cy, vertex = {
            x: (cy * hb - by * hc) / d + ax,
            y: (bx * hc - cx * hb) / d + ay
        };
        d3_geom_voronoiSetEdgeEnd(rArc.edge, lSite, rSite, vertex);
        newArc.edge = d3_geom_voronoiCreateEdge(lSite, site, null, vertex);
        rArc.edge = d3_geom_voronoiCreateEdge(site, rSite, null, vertex);
        d3_geom_voronoiAttachCircle(lArc);
        d3_geom_voronoiAttachCircle(rArc);
    }
    function d3_geom_voronoiLeftBreakPoint(arc, directrix) {
        var site = arc.site, rfocx = site.x, rfocy = site.y, pby2 = rfocy - directrix;
        if (!pby2) return rfocx;
        var lArc = arc.P;
        if (!lArc) return -Infinity;
        site = lArc.site;
        var lfocx = site.x, lfocy = site.y, plby2 = lfocy - directrix;
        if (!plby2) return lfocx;
        var hl = lfocx - rfocx, aby2 = 1 / pby2 - 1 / plby2, b = hl / plby2;
        if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx;
        return (rfocx + lfocx) / 2;
    }
    function d3_geom_voronoiRightBreakPoint(arc, directrix) {
        var rArc = arc.N;
        if (rArc) return d3_geom_voronoiLeftBreakPoint(rArc, directrix);
        var site = arc.site;
        return site.y === directrix ? site.x : Infinity;
    }
    function d3_geom_voronoiCell(site) {
        this.site = site;
        this.edges = [];
    }
    d3_geom_voronoiCell.prototype.prepare = function() {
        var halfEdges = this.edges, iHalfEdge = halfEdges.length, edge;
        while (iHalfEdge--) {
            edge = halfEdges[iHalfEdge].edge;
            if (!edge.b || !edge.a) halfEdges.splice(iHalfEdge, 1);
        }
        halfEdges.sort(d3_geom_voronoiHalfEdgeOrder);
        return halfEdges.length;
    };
    function d3_geom_voronoiCloseCells(extent) {
        var x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], x2, y2, x3, y3, cells = d3_geom_voronoiCells, iCell = cells.length, cell, iHalfEdge, halfEdges, nHalfEdges, start, end;
        while (iCell--) {
            cell = cells[iCell];
            if (!cell || !cell.prepare()) continue;
            halfEdges = cell.edges;
            nHalfEdges = halfEdges.length;
            iHalfEdge = 0;
            while (iHalfEdge < nHalfEdges) {
                end = halfEdges[iHalfEdge].end(), x3 = end.x, y3 = end.y;
                start = halfEdges[++iHalfEdge % nHalfEdges].start(), x2 = start.x, 
                y2 = start.y;
                if (abs(x3 - x2) > ε || abs(y3 - y2) > ε) {
                    halfEdges.splice(iHalfEdge, 0, new d3_geom_voronoiHalfEdge(d3_geom_voronoiCreateBorderEdge(cell.site, end, abs(x3 - x0) < ε && y1 - y3 > ε ? {
                        x: x0,
                        y: abs(x2 - x0) < ε ? y2 : y1
                    } : abs(y3 - y1) < ε && x1 - x3 > ε ? {
                        x: abs(y2 - y1) < ε ? x2 : x1,
                        y: y1
                    } : abs(x3 - x1) < ε && y3 - y0 > ε ? {
                        x: x1,
                        y: abs(x2 - x1) < ε ? y2 : y0
                    } : abs(y3 - y0) < ε && x3 - x0 > ε ? {
                        x: abs(y2 - y0) < ε ? x2 : x0,
                        y: y0
                    } : null), cell.site, null));
                    ++nHalfEdges;
                }
            }
        }
    }
    function d3_geom_voronoiHalfEdgeOrder(a, b) {
        return b.angle - a.angle;
    }
    function d3_geom_voronoiCircle() {
        d3_geom_voronoiRedBlackNode(this);
        this.x = this.y = this.arc = this.site = this.cy = null;
    }
    function d3_geom_voronoiAttachCircle(arc) {
        var lArc = arc.P, rArc = arc.N;
        if (!lArc || !rArc) return;
        var lSite = lArc.site, cSite = arc.site, rSite = rArc.site;
        if (lSite === rSite) return;
        var bx = cSite.x, by = cSite.y, ax = lSite.x - bx, ay = lSite.y - by, cx = rSite.x - bx, cy = rSite.y - by;
        var d = 2 * (ax * cy - ay * cx);
        if (d >= -ε2) return;
        var ha = ax * ax + ay * ay, hc = cx * cx + cy * cy, x = (cy * ha - ay * hc) / d, y = (ax * hc - cx * ha) / d, cy = y + by;
        var circle = d3_geom_voronoiCirclePool.pop() || new d3_geom_voronoiCircle();
        circle.arc = arc;
        circle.site = cSite;
        circle.x = x + bx;
        circle.y = cy + Math.sqrt(x * x + y * y);
        circle.cy = cy;
        arc.circle = circle;
        var before = null, node = d3_geom_voronoiCircles._;
        while (node) {
            if (circle.y < node.y || circle.y === node.y && circle.x <= node.x) {
                if (node.L) node = node.L; else {
                    before = node.P;
                    break;
                }
            } else {
                if (node.R) node = node.R; else {
                    before = node;
                    break;
                }
            }
        }
        d3_geom_voronoiCircles.insert(before, circle);
        if (!before) d3_geom_voronoiFirstCircle = circle;
    }
    function d3_geom_voronoiDetachCircle(arc) {
        var circle = arc.circle;
        if (circle) {
            if (!circle.P) d3_geom_voronoiFirstCircle = circle.N;
            d3_geom_voronoiCircles.remove(circle);
            d3_geom_voronoiCirclePool.push(circle);
            d3_geom_voronoiRedBlackNode(circle);
            arc.circle = null;
        }
    }
    function d3_geom_voronoiClipEdges(extent) {
        var edges = d3_geom_voronoiEdges, clip = d3_geom_clipLine(extent[0][0], extent[0][1], extent[1][0], extent[1][1]), i = edges.length, e;
        while (i--) {
            e = edges[i];
            if (!d3_geom_voronoiConnectEdge(e, extent) || !clip(e) || abs(e.a.x - e.b.x) < ε && abs(e.a.y - e.b.y) < ε) {
                e.a = e.b = null;
                edges.splice(i, 1);
            }
        }
    }
    function d3_geom_voronoiConnectEdge(edge, extent) {
        var vb = edge.b;
        if (vb) return true;
        var va = edge.a, x0 = extent[0][0], x1 = extent[1][0], y0 = extent[0][1], y1 = extent[1][1], lSite = edge.l, rSite = edge.r, lx = lSite.x, ly = lSite.y, rx = rSite.x, ry = rSite.y, fx = (lx + rx) / 2, fy = (ly + ry) / 2, fm, fb;
        if (ry === ly) {
            if (fx < x0 || fx >= x1) return;
            if (lx > rx) {
                if (!va) va = {
                    x: fx,
                    y: y0
                }; else if (va.y >= y1) return;
                vb = {
                    x: fx,
                    y: y1
                };
            } else {
                if (!va) va = {
                    x: fx,
                    y: y1
                }; else if (va.y < y0) return;
                vb = {
                    x: fx,
                    y: y0
                };
            }
        } else {
            fm = (lx - rx) / (ry - ly);
            fb = fy - fm * fx;
            if (fm < -1 || fm > 1) {
                if (lx > rx) {
                    if (!va) va = {
                        x: (y0 - fb) / fm,
                        y: y0
                    }; else if (va.y >= y1) return;
                    vb = {
                        x: (y1 - fb) / fm,
                        y: y1
                    };
                } else {
                    if (!va) va = {
                        x: (y1 - fb) / fm,
                        y: y1
                    }; else if (va.y < y0) return;
                    vb = {
                        x: (y0 - fb) / fm,
                        y: y0
                    };
                }
            } else {
                if (ly < ry) {
                    if (!va) va = {
                        x: x0,
                        y: fm * x0 + fb
                    }; else if (va.x >= x1) return;
                    vb = {
                        x: x1,
                        y: fm * x1 + fb
                    };
                } else {
                    if (!va) va = {
                        x: x1,
                        y: fm * x1 + fb
                    }; else if (va.x < x0) return;
                    vb = {
                        x: x0,
                        y: fm * x0 + fb
                    };
                }
            }
        }
        edge.a = va;
        edge.b = vb;
        return true;
    }
    function d3_geom_voronoiEdge(lSite, rSite) {
        this.l = lSite;
        this.r = rSite;
        this.a = this.b = null;
    }
    function d3_geom_voronoiCreateEdge(lSite, rSite, va, vb) {
        var edge = new d3_geom_voronoiEdge(lSite, rSite);
        d3_geom_voronoiEdges.push(edge);
        if (va) d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, va);
        if (vb) d3_geom_voronoiSetEdgeEnd(edge, rSite, lSite, vb);
        d3_geom_voronoiCells[lSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, lSite, rSite));
        d3_geom_voronoiCells[rSite.i].edges.push(new d3_geom_voronoiHalfEdge(edge, rSite, lSite));
        return edge;
    }
    function d3_geom_voronoiCreateBorderEdge(lSite, va, vb) {
        var edge = new d3_geom_voronoiEdge(lSite, null);
        edge.a = va;
        edge.b = vb;
        d3_geom_voronoiEdges.push(edge);
        return edge;
    }
    function d3_geom_voronoiSetEdgeEnd(edge, lSite, rSite, vertex) {
        if (!edge.a && !edge.b) {
            edge.a = vertex;
            edge.l = lSite;
            edge.r = rSite;
        } else if (edge.l === rSite) {
            edge.b = vertex;
        } else {
            edge.a = vertex;
        }
    }
    function d3_geom_voronoiHalfEdge(edge, lSite, rSite) {
        var va = edge.a, vb = edge.b;
        this.edge = edge;
        this.site = lSite;
        this.angle = rSite ? Math.atan2(rSite.y - lSite.y, rSite.x - lSite.x) : edge.l === lSite ? Math.atan2(vb.x - va.x, va.y - vb.y) : Math.atan2(va.x - vb.x, vb.y - va.y);
    }
    d3_geom_voronoiHalfEdge.prototype = {
        start: function() {
            return this.edge.l === this.site ? this.edge.a : this.edge.b;
        },
        end: function() {
            return this.edge.l === this.site ? this.edge.b : this.edge.a;
        }
    };
    function d3_geom_voronoiRedBlackTree() {
        this._ = null;
    }
    function d3_geom_voronoiRedBlackNode(node) {
        node.U = node.C = node.L = node.R = node.P = node.N = null;
    }
    d3_geom_voronoiRedBlackTree.prototype = {
        insert: function(after, node) {
            var parent, grandpa, uncle;
            if (after) {
                node.P = after;
                node.N = after.N;
                if (after.N) after.N.P = node;
                after.N = node;
                if (after.R) {
                    after = after.R;
                    while (after.L) after = after.L;
                    after.L = node;
                } else {
                    after.R = node;
                }
                parent = after;
            } else if (this._) {
                after = d3_geom_voronoiRedBlackFirst(this._);
                node.P = null;
                node.N = after;
                after.P = after.L = node;
                parent = after;
            } else {
                node.P = node.N = null;
                this._ = node;
                parent = null;
            }
            node.L = node.R = null;
            node.U = parent;
            node.C = true;
            after = node;
            while (parent && parent.C) {
                grandpa = parent.U;
                if (parent === grandpa.L) {
                    uncle = grandpa.R;
                    if (uncle && uncle.C) {
                        parent.C = uncle.C = false;
                        grandpa.C = true;
                        after = grandpa;
                    } else {
                        if (after === parent.R) {
                            d3_geom_voronoiRedBlackRotateLeft(this, parent);
                            after = parent;
                            parent = after.U;
                        }
                        parent.C = false;
                        grandpa.C = true;
                        d3_geom_voronoiRedBlackRotateRight(this, grandpa);
                    }
                } else {
                    uncle = grandpa.L;
                    if (uncle && uncle.C) {
                        parent.C = uncle.C = false;
                        grandpa.C = true;
                        after = grandpa;
                    } else {
                        if (after === parent.L) {
                            d3_geom_voronoiRedBlackRotateRight(this, parent);
                            after = parent;
                            parent = after.U;
                        }
                        parent.C = false;
                        grandpa.C = true;
                        d3_geom_voronoiRedBlackRotateLeft(this, grandpa);
                    }
                }
                parent = after.U;
            }
            this._.C = false;
        },
        remove: function(node) {
            if (node.N) node.N.P = node.P;
            if (node.P) node.P.N = node.N;
            node.N = node.P = null;
            var parent = node.U, sibling, left = node.L, right = node.R, next, red;
            if (!left) next = right; else if (!right) next = left; else next = d3_geom_voronoiRedBlackFirst(right);
            if (parent) {
                if (parent.L === node) parent.L = next; else parent.R = next;
            } else {
                this._ = next;
            }
            if (left && right) {
                red = next.C;
                next.C = node.C;
                next.L = left;
                left.U = next;
                if (next !== right) {
                    parent = next.U;
                    next.U = node.U;
                    node = next.R;
                    parent.L = node;
                    next.R = right;
                    right.U = next;
                } else {
                    next.U = parent;
                    parent = next;
                    node = next.R;
                }
            } else {
                red = node.C;
                node = next;
            }
            if (node) node.U = parent;
            if (red) return;
            if (node && node.C) {
                node.C = false;
                return;
            }
            do {
                if (node === this._) break;
                if (node === parent.L) {
                    sibling = parent.R;
                    if (sibling.C) {
                        sibling.C = false;
                        parent.C = true;
                        d3_geom_voronoiRedBlackRotateLeft(this, parent);
                        sibling = parent.R;
                    }
                    if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) {
                        if (!sibling.R || !sibling.R.C) {
                            sibling.L.C = false;
                            sibling.C = true;
                            d3_geom_voronoiRedBlackRotateRight(this, sibling);
                            sibling = parent.R;
                        }
                        sibling.C = parent.C;
                        parent.C = sibling.R.C = false;
                        d3_geom_voronoiRedBlackRotateLeft(this, parent);
                        node = this._;
                        break;
                    }
                } else {
                    sibling = parent.L;
                    if (sibling.C) {
                        sibling.C = false;
                        parent.C = true;
                        d3_geom_voronoiRedBlackRotateRight(this, parent);
                        sibling = parent.L;
                    }
                    if (sibling.L && sibling.L.C || sibling.R && sibling.R.C) {
                        if (!sibling.L || !sibling.L.C) {
                            sibling.R.C = false;
                            sibling.C = true;
                            d3_geom_voronoiRedBlackRotateLeft(this, sibling);
                            sibling = parent.L;
                        }
                        sibling.C = parent.C;
                        parent.C = sibling.L.C = false;
                        d3_geom_voronoiRedBlackRotateRight(this, parent);
                        node = this._;
                        break;
                    }
                }
                sibling.C = true;
                node = parent;
                parent = parent.U;
            } while (!node.C);
            if (node) node.C = false;
        }
    };
    function d3_geom_voronoiRedBlackRotateLeft(tree, node) {
        var p = node, q = node.R, parent = p.U;
        if (parent) {
            if (parent.L === p) parent.L = q; else parent.R = q;
        } else {
            tree._ = q;
        }
        q.U = parent;
        p.U = q;
        p.R = q.L;
        if (p.R) p.R.U = p;
        q.L = p;
    }
    function d3_geom_voronoiRedBlackRotateRight(tree, node) {
        var p = node, q = node.L, parent = p.U;
        if (parent) {
            if (parent.L === p) parent.L = q; else parent.R = q;
        } else {
            tree._ = q;
        }
        q.U = parent;
        p.U = q;
        p.L = q.R;
        if (p.L) p.L.U = p;
        q.R = p;
    }
    function d3_geom_voronoiRedBlackFirst(node) {
        while (node.L) node = node.L;
        return node;
    }
    function d3_geom_voronoi(sites, bbox) {
        var site = sites.sort(d3_geom_voronoiVertexOrder).pop(), x0, y0, circle;
        d3_geom_voronoiEdges = [];
        d3_geom_voronoiCells = new Array(sites.length);
        d3_geom_voronoiBeaches = new d3_geom_voronoiRedBlackTree();
        d3_geom_voronoiCircles = new d3_geom_voronoiRedBlackTree();
        while (true) {
            circle = d3_geom_voronoiFirstCircle;
            if (site && (!circle || site.y < circle.y || site.y === circle.y && site.x < circle.x)) {
                if (site.x !== x0 || site.y !== y0) {
                    d3_geom_voronoiCells[site.i] = new d3_geom_voronoiCell(site);
                    d3_geom_voronoiAddBeach(site);
                    x0 = site.x, y0 = site.y;
                }
                site = sites.pop();
            } else if (circle) {
                d3_geom_voronoiRemoveBeach(circle.arc);
            } else {
                break;
            }
        }
        if (bbox) d3_geom_voronoiClipEdges(bbox), d3_geom_voronoiCloseCells(bbox);
        var diagram = {
            cells: d3_geom_voronoiCells,
            edges: d3_geom_voronoiEdges
        };
        d3_geom_voronoiBeaches = d3_geom_voronoiCircles = d3_geom_voronoiEdges = d3_geom_voronoiCells = null;
        return diagram;
    }
    function d3_geom_voronoiVertexOrder(a, b) {
        return b.y - a.y || b.x - a.x;
    }
    d3.geom.voronoi = function(points) {
        var x = d3_geom_pointX, y = d3_geom_pointY, fx = x, fy = y, clipExtent = d3_geom_voronoiClipExtent;
        if (points) return voronoi(points);
        function voronoi(data) {
            var polygons = new Array(data.length), x0 = clipExtent[0][0], y0 = clipExtent[0][1], x1 = clipExtent[1][0], y1 = clipExtent[1][1];
            d3_geom_voronoi(sites(data), clipExtent).cells.forEach(function(cell, i) {
                var edges = cell.edges, site = cell.site, polygon = polygons[i] = edges.length ? edges.map(function(e) {
                    var s = e.start();
                    return [ s.x, s.y ];
                }) : site.x >= x0 && site.x <= x1 && site.y >= y0 && site.y <= y1 ? [ [ x0, y1 ], [ x1, y1 ], [ x1, y0 ], [ x0, y0 ] ] : [];
                polygon.point = data[i];
            });
            return polygons;
        }
        function sites(data) {
            return data.map(function(d, i) {
                return {
                    x: Math.round(fx(d, i) / ε) * ε,
                    y: Math.round(fy(d, i) / ε) * ε,
                    i: i
                };
            });
        }
        voronoi.links = function(data) {
            return d3_geom_voronoi(sites(data)).edges.filter(function(edge) {
                return edge.l && edge.r;
            }).map(function(edge) {
                return {
                    source: data[edge.l.i],
                    target: data[edge.r.i]
                };
            });
        };
        voronoi.triangles = function(data) {
            var triangles = [];
            d3_geom_voronoi(sites(data)).cells.forEach(function(cell, i) {
                var site = cell.site, edges = cell.edges.sort(d3_geom_voronoiHalfEdgeOrder), j = -1, m = edges.length, e0, s0, e1 = edges[m - 1].edge, s1 = e1.l === site ? e1.r : e1.l;
                while (++j < m) {
                    e0 = e1;
                    s0 = s1;
                    e1 = edges[j].edge;
                    s1 = e1.l === site ? e1.r : e1.l;
                    if (i < s0.i && i < s1.i && d3_geom_voronoiTriangleArea(site, s0, s1) < 0) {
                        triangles.push([ data[i], data[s0.i], data[s1.i] ]);
                    }
                }
            });
            return triangles;
        };
        voronoi.x = function(_) {
            return arguments.length ? (fx = d3_functor(x = _), voronoi) : x;
        };
        voronoi.y = function(_) {
            return arguments.length ? (fy = d3_functor(y = _), voronoi) : y;
        };
        voronoi.clipExtent = function(_) {
            if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent;
            clipExtent = _ == null ? d3_geom_voronoiClipExtent : _;
            return voronoi;
        };
        voronoi.size = function(_) {
            if (!arguments.length) return clipExtent === d3_geom_voronoiClipExtent ? null : clipExtent && clipExtent[1];
            return voronoi.clipExtent(_ && [ [ 0, 0 ], _ ]);
        };
        return voronoi;
    };
    var d3_geom_voronoiClipExtent = [ [ -1e6, -1e6 ], [ 1e6, 1e6 ] ];
    function d3_geom_voronoiTriangleArea(a, b, c) {
        return (a.x - c.x) * (b.y - a.y) - (a.x - b.x) * (c.y - a.y);
    }
    d3.geom.delaunay = function(vertices) {
        return d3.geom.voronoi().triangles(vertices);
    };
    d3.geom.quadtree = function(points, x1, y1, x2, y2) {
        var x = d3_geom_pointX, y = d3_geom_pointY, compat;
        if (compat = arguments.length) {
            x = d3_geom_quadtreeCompatX;
            y = d3_geom_quadtreeCompatY;
            if (compat === 3) {
                y2 = y1;
                x2 = x1;
                y1 = x1 = 0;
            }
            return quadtree(points);
        }
        function quadtree(data) {
            var d, fx = d3_functor(x), fy = d3_functor(y), xs, ys, i, n, x1_, y1_, x2_, y2_;
            if (x1 != null) {
                x1_ = x1, y1_ = y1, x2_ = x2, y2_ = y2;
            } else {
                x2_ = y2_ = -(x1_ = y1_ = Infinity);
                xs = [], ys = [];
                n = data.length;
                if (compat) for (i = 0; i < n; ++i) {
                    d = data[i];
                    if (d.x < x1_) x1_ = d.x;
                    if (d.y < y1_) y1_ = d.y;
                    if (d.x > x2_) x2_ = d.x;
                    if (d.y > y2_) y2_ = d.y;
                    xs.push(d.x);
                    ys.push(d.y);
                } else for (i = 0; i < n; ++i) {
                    var x_ = +fx(d = data[i], i), y_ = +fy(d, i);
                    if (x_ < x1_) x1_ = x_;
                    if (y_ < y1_) y1_ = y_;
                    if (x_ > x2_) x2_ = x_;
                    if (y_ > y2_) y2_ = y_;
                    xs.push(x_);
                    ys.push(y_);
                }
            }
            var dx = x2_ - x1_, dy = y2_ - y1_;
            if (dx > dy) y2_ = y1_ + dx; else x2_ = x1_ + dy;
            function insert(n, d, x, y, x1, y1, x2, y2) {
                if (isNaN(x) || isNaN(y)) return;
                if (n.leaf) {
                    var nx = n.x, ny = n.y;
                    if (nx != null) {
                        if (abs(nx - x) + abs(ny - y) < .01) {
                            insertChild(n, d, x, y, x1, y1, x2, y2);
                        } else {
                            var nPoint = n.point;
                            n.x = n.y = n.point = null;
                            insertChild(n, nPoint, nx, ny, x1, y1, x2, y2);
                            insertChild(n, d, x, y, x1, y1, x2, y2);
                        }
                    } else {
                        n.x = x, n.y = y, n.point = d;
                    }
                } else {
                    insertChild(n, d, x, y, x1, y1, x2, y2);
                }
            }
            function insertChild(n, d, x, y, x1, y1, x2, y2) {
                var xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym, i = below << 1 | right;
                n.leaf = false;
                n = n.nodes[i] || (n.nodes[i] = d3_geom_quadtreeNode());
                if (right) x1 = xm; else x2 = xm;
                if (below) y1 = ym; else y2 = ym;
                insert(n, d, x, y, x1, y1, x2, y2);
            }
            var root = d3_geom_quadtreeNode();
            root.add = function(d) {
                insert(root, d, +fx(d, ++i), +fy(d, i), x1_, y1_, x2_, y2_);
            };
            root.visit = function(f) {
                d3_geom_quadtreeVisit(f, root, x1_, y1_, x2_, y2_);
            };
            root.find = function(point) {
                return d3_geom_quadtreeFind(root, point[0], point[1], x1_, y1_, x2_, y2_);
            };
            i = -1;
            if (x1 == null) {
                while (++i < n) {
                    insert(root, data[i], xs[i], ys[i], x1_, y1_, x2_, y2_);
                }
                --i;
            } else data.forEach(root.add);
            xs = ys = data = d = null;
            return root;
        }
        quadtree.x = function(_) {
            return arguments.length ? (x = _, quadtree) : x;
        };
        quadtree.y = function(_) {
            return arguments.length ? (y = _, quadtree) : y;
        };
        quadtree.extent = function(_) {
            if (!arguments.length) return x1 == null ? null : [ [ x1, y1 ], [ x2, y2 ] ];
            if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = +_[0][0], y1 = +_[0][1], 
            x2 = +_[1][0], y2 = +_[1][1];
            return quadtree;
        };
        quadtree.size = function(_) {
            if (!arguments.length) return x1 == null ? null : [ x2 - x1, y2 - y1 ];
            if (_ == null) x1 = y1 = x2 = y2 = null; else x1 = y1 = 0, x2 = +_[0], 
            y2 = +_[1];
            return quadtree;
        };
        return quadtree;
    };
    function d3_geom_quadtreeCompatX(d) {
        return d.x;
    }
    function d3_geom_quadtreeCompatY(d) {
        return d.y;
    }
    function d3_geom_quadtreeNode() {
        return {
            leaf: true,
            nodes: [],
            point: null,
            x: null,
            y: null
        };
    }
    function d3_geom_quadtreeVisit(f, node, x1, y1, x2, y2) {
        if (!f(node, x1, y1, x2, y2)) {
            var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5, children = node.nodes;
            if (children[0]) d3_geom_quadtreeVisit(f, children[0], x1, y1, sx, sy);
            if (children[1]) d3_geom_quadtreeVisit(f, children[1], sx, y1, x2, sy);
            if (children[2]) d3_geom_quadtreeVisit(f, children[2], x1, sy, sx, y2);
            if (children[3]) d3_geom_quadtreeVisit(f, children[3], sx, sy, x2, y2);
        }
    }
    function d3_geom_quadtreeFind(root, x, y, x0, y0, x3, y3) {
        var minDistance2 = Infinity, closestPoint;
        (function find(node, x1, y1, x2, y2) {
            if (x1 > x3 || y1 > y3 || x2 < x0 || y2 < y0) return;
            if (point = node.point) {
                var point, dx = x - node.x, dy = y - node.y, distance2 = dx * dx + dy * dy;
                if (distance2 < minDistance2) {
                    var distance = Math.sqrt(minDistance2 = distance2);
                    x0 = x - distance, y0 = y - distance;
                    x3 = x + distance, y3 = y + distance;
                    closestPoint = point;
                }
            }
            var children = node.nodes, xm = (x1 + x2) * .5, ym = (y1 + y2) * .5, right = x >= xm, below = y >= ym;
            for (var i = below << 1 | right, j = i + 4; i < j; ++i) {
                if (node = children[i & 3]) switch (i & 3) {
                  case 0:
                    find(node, x1, y1, xm, ym);
                    break;

                  case 1:
                    find(node, xm, y1, x2, ym);
                    break;

                  case 2:
                    find(node, x1, ym, xm, y2);
                    break;

                  case 3:
                    find(node, xm, ym, x2, y2);
                    break;
                }
            }
        })(root, x0, y0, x3, y3);
        return closestPoint;
    }
    d3.interpolateRgb = d3_interpolateRgb;
    function d3_interpolateRgb(a, b) {
        a = d3.rgb(a);
        b = d3.rgb(b);
        var ar = a.r, ag = a.g, ab = a.b, br = b.r - ar, bg = b.g - ag, bb = b.b - ab;
        return function(t) {
            return "#" + d3_rgb_hex(Math.round(ar + br * t)) + d3_rgb_hex(Math.round(ag + bg * t)) + d3_rgb_hex(Math.round(ab + bb * t));
        };
    }
    d3.interpolateObject = d3_interpolateObject;
    function d3_interpolateObject(a, b) {
        var i = {}, c = {}, k;
        for (k in a) {
            if (k in b) {
                i[k] = d3_interpolate(a[k], b[k]);
            } else {
                c[k] = a[k];
            }
        }
        for (k in b) {
            if (!(k in a)) {
                c[k] = b[k];
            }
        }
        return function(t) {
            for (k in i) c[k] = i[k](t);
            return c;
        };
    }
    d3.interpolateNumber = d3_interpolateNumber;
    function d3_interpolateNumber(a, b) {
        a = +a, b = +b;
        return function(t) {
            return a * (1 - t) + b * t;
        };
    }
    d3.interpolateString = d3_interpolateString;
    function d3_interpolateString(a, b) {
        var bi = d3_interpolate_numberA.lastIndex = d3_interpolate_numberB.lastIndex = 0, am, bm, bs, i = -1, s = [], q = [];
        a = a + "", b = b + "";
        while ((am = d3_interpolate_numberA.exec(a)) && (bm = d3_interpolate_numberB.exec(b))) {
            if ((bs = bm.index) > bi) {
                bs = b.slice(bi, bs);
                if (s[i]) s[i] += bs; else s[++i] = bs;
            }
            if ((am = am[0]) === (bm = bm[0])) {
                if (s[i]) s[i] += bm; else s[++i] = bm;
            } else {
                s[++i] = null;
                q.push({
                    i: i,
                    x: d3_interpolateNumber(am, bm)
                });
            }
            bi = d3_interpolate_numberB.lastIndex;
        }
        if (bi < b.length) {
            bs = b.slice(bi);
            if (s[i]) s[i] += bs; else s[++i] = bs;
        }
        return s.length < 2 ? q[0] ? (b = q[0].x, function(t) {
            return b(t) + "";
        }) : function() {
            return b;
        } : (b = q.length, function(t) {
            for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t);
            return s.join("");
        });
    }
    var d3_interpolate_numberA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g, d3_interpolate_numberB = new RegExp(d3_interpolate_numberA.source, "g");
    d3.interpolate = d3_interpolate;
    function d3_interpolate(a, b) {
        var i = d3.interpolators.length, f;
        while (--i >= 0 && !(f = d3.interpolators[i](a, b)));
        return f;
    }
    d3.interpolators = [ function(a, b) {
        var t = typeof b;
        return (t === "string" ? d3_rgb_names.has(b) || /^(#|rgb\(|hsl\()/.test(b) ? d3_interpolateRgb : d3_interpolateString : b instanceof d3_color ? d3_interpolateRgb : Array.isArray(b) ? d3_interpolateArray : t === "object" && isNaN(b) ? d3_interpolateObject : d3_interpolateNumber)(a, b);
    } ];
    d3.interpolateArray = d3_interpolateArray;
    function d3_interpolateArray(a, b) {
        var x = [], c = [], na = a.length, nb = b.length, n0 = Math.min(a.length, b.length), i;
        for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i]));
        for (;i < na; ++i) c[i] = a[i];
        for (;i < nb; ++i) c[i] = b[i];
        return function(t) {
            for (i = 0; i < n0; ++i) c[i] = x[i](t);
            return c;
        };
    }
    var d3_ease_default = function() {
        return d3_identity;
    };
    var d3_ease = d3.map({
        linear: d3_ease_default,
        poly: d3_ease_poly,
        quad: function() {
            return d3_ease_quad;
        },
        cubic: function() {
            return d3_ease_cubic;
        },
        sin: function() {
            return d3_ease_sin;
        },
        exp: function() {
            return d3_ease_exp;
        },
        circle: function() {
            return d3_ease_circle;
        },
        elastic: d3_ease_elastic,
        back: d3_ease_back,
        bounce: function() {
            return d3_ease_bounce;
        }
    });
    var d3_ease_mode = d3.map({
        in: d3_identity,
        out: d3_ease_reverse,
        "in-out": d3_ease_reflect,
        "out-in": function(f) {
            return d3_ease_reflect(d3_ease_reverse(f));
        }
    });
    d3.ease = function(name) {
        var i = name.indexOf("-"), t = i >= 0 ? name.slice(0, i) : name, m = i >= 0 ? name.slice(i + 1) : "in";
        t = d3_ease.get(t) || d3_ease_default;
        m = d3_ease_mode.get(m) || d3_identity;
        return d3_ease_clamp(m(t.apply(null, d3_arraySlice.call(arguments, 1))));
    };
    function d3_ease_clamp(f) {
        return function(t) {
            return t <= 0 ? 0 : t >= 1 ? 1 : f(t);
        };
    }
    function d3_ease_reverse(f) {
        return function(t) {
            return 1 - f(1 - t);
        };
    }
    function d3_ease_reflect(f) {
        return function(t) {
            return .5 * (t < .5 ? f(2 * t) : 2 - f(2 - 2 * t));
        };
    }
    function d3_ease_quad(t) {
        return t * t;
    }
    function d3_ease_cubic(t) {
        return t * t * t;
    }
    function d3_ease_cubicInOut(t) {
        if (t <= 0) return 0;
        if (t >= 1) return 1;
        var t2 = t * t, t3 = t2 * t;
        return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75);
    }
    function d3_ease_poly(e) {
        return function(t) {
            return Math.pow(t, e);
        };
    }
    function d3_ease_sin(t) {
        return 1 - Math.cos(t * halfπ);
    }
    function d3_ease_exp(t) {
        return Math.pow(2, 10 * (t - 1));
    }
    function d3_ease_circle(t) {
        return 1 - Math.sqrt(1 - t * t);
    }
    function d3_ease_elastic(a, p) {
        var s;
        if (arguments.length < 2) p = .45;
        if (arguments.length) s = p / τ * Math.asin(1 / a); else a = 1, s = p / 4;
        return function(t) {
            return 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * τ / p);
        };
    }
    function d3_ease_back(s) {
        if (!s) s = 1.70158;
        return function(t) {
            return t * t * ((s + 1) * t - s);
        };
    }
    function d3_ease_bounce(t) {
        return t < 1 / 2.75 ? 7.5625 * t * t : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75 : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375 : 7.5625 * (t -= 2.625 / 2.75) * t + .984375;
    }
    d3.interpolateHcl = d3_interpolateHcl;
    function d3_interpolateHcl(a, b) {
        a = d3.hcl(a);
        b = d3.hcl(b);
        var ah = a.h, ac = a.c, al = a.l, bh = b.h - ah, bc = b.c - ac, bl = b.l - al;
        if (isNaN(bc)) bc = 0, ac = isNaN(ac) ? b.c : ac;
        if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360;
        return function(t) {
            return d3_hcl_lab(ah + bh * t, ac + bc * t, al + bl * t) + "";
        };
    }
    d3.interpolateHsl = d3_interpolateHsl;
    function d3_interpolateHsl(a, b) {
        a = d3.hsl(a);
        b = d3.hsl(b);
        var ah = a.h, as = a.s, al = a.l, bh = b.h - ah, bs = b.s - as, bl = b.l - al;
        if (isNaN(bs)) bs = 0, as = isNaN(as) ? b.s : as;
        if (isNaN(bh)) bh = 0, ah = isNaN(ah) ? b.h : ah; else if (bh > 180) bh -= 360; else if (bh < -180) bh += 360;
        return function(t) {
            return d3_hsl_rgb(ah + bh * t, as + bs * t, al + bl * t) + "";
        };
    }
    d3.interpolateLab = d3_interpolateLab;
    function d3_interpolateLab(a, b) {
        a = d3.lab(a);
        b = d3.lab(b);
        var al = a.l, aa = a.a, ab = a.b, bl = b.l - al, ba = b.a - aa, bb = b.b - ab;
        return function(t) {
            return d3_lab_rgb(al + bl * t, aa + ba * t, ab + bb * t) + "";
        };
    }
    d3.interpolateRound = d3_interpolateRound;
    function d3_interpolateRound(a, b) {
        b -= a;
        return function(t) {
            return Math.round(a + b * t);
        };
    }
    d3.transform = function(string) {
        var g = d3_document.createElementNS(d3.ns.prefix.svg, "g");
        return (d3.transform = function(string) {
            if (string != null) {
                g.setAttribute("transform", string);
                var t = g.transform.baseVal.consolidate();
            }
            return new d3_transform(t ? t.matrix : d3_transformIdentity);
        })(string);
    };
    function d3_transform(m) {
        var r0 = [ m.a, m.b ], r1 = [ m.c, m.d ], kx = d3_transformNormalize(r0), kz = d3_transformDot(r0, r1), ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0;
        if (r0[0] * r1[1] < r1[0] * r0[1]) {
            r0[0] *= -1;
            r0[1] *= -1;
            kx *= -1;
            kz *= -1;
        }
        this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees;
        this.translate = [ m.e, m.f ];
        this.scale = [ kx, ky ];
        this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0;
    }
    d3_transform.prototype.toString = function() {
        return "translate(" + this.translate + ")rotate(" + this.rotate + ")skewX(" + this.skew + ")scale(" + this.scale + ")";
    };
    function d3_transformDot(a, b) {
        return a[0] * b[0] + a[1] * b[1];
    }
    function d3_transformNormalize(a) {
        var k = Math.sqrt(d3_transformDot(a, a));
        if (k) {
            a[0] /= k;
            a[1] /= k;
        }
        return k;
    }
    function d3_transformCombine(a, b, k) {
        a[0] += k * b[0];
        a[1] += k * b[1];
        return a;
    }
    var d3_transformIdentity = {
        a: 1,
        b: 0,
        c: 0,
        d: 1,
        e: 0,
        f: 0
    };
    d3.interpolateTransform = d3_interpolateTransform;
    function d3_interpolateTransform(a, b) {
        var s = [], q = [], n, A = d3.transform(a), B = d3.transform(b), ta = A.translate, tb = B.translate, ra = A.rotate, rb = B.rotate, wa = A.skew, wb = B.skew, ka = A.scale, kb = B.scale;
        if (ta[0] != tb[0] || ta[1] != tb[1]) {
            s.push("translate(", null, ",", null, ")");
            q.push({
                i: 1,
                x: d3_interpolateNumber(ta[0], tb[0])
            }, {
                i: 3,
                x: d3_interpolateNumber(ta[1], tb[1])
            });
        } else if (tb[0] || tb[1]) {
            s.push("translate(" + tb + ")");
        } else {
            s.push("");
        }
        if (ra != rb) {
            if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360;
            q.push({
                i: s.push(s.pop() + "rotate(", null, ")") - 2,
                x: d3_interpolateNumber(ra, rb)
            });
        } else if (rb) {
            s.push(s.pop() + "rotate(" + rb + ")");
        }
        if (wa != wb) {
            q.push({
                i: s.push(s.pop() + "skewX(", null, ")") - 2,
                x: d3_interpolateNumber(wa, wb)
            });
        } else if (wb) {
            s.push(s.pop() + "skewX(" + wb + ")");
        }
        if (ka[0] != kb[0] || ka[1] != kb[1]) {
            n = s.push(s.pop() + "scale(", null, ",", null, ")");
            q.push({
                i: n - 4,
                x: d3_interpolateNumber(ka[0], kb[0])
            }, {
                i: n - 2,
                x: d3_interpolateNumber(ka[1], kb[1])
            });
        } else if (kb[0] != 1 || kb[1] != 1) {
            s.push(s.pop() + "scale(" + kb + ")");
        }
        n = q.length;
        return function(t) {
            var i = -1, o;
            while (++i < n) s[(o = q[i]).i] = o.x(t);
            return s.join("");
        };
    }
    function d3_uninterpolateNumber(a, b) {
        b = (b -= a = +a) || 1 / b;
        return function(x) {
            return (x - a) / b;
        };
    }
    function d3_uninterpolateClamp(a, b) {
        b = (b -= a = +a) || 1 / b;
        return function(x) {
            return Math.max(0, Math.min(1, (x - a) / b));
        };
    }
    d3.layout = {};
    d3.layout.bundle = function() {
        return function(links) {
            var paths = [], i = -1, n = links.length;
            while (++i < n) paths.push(d3_layout_bundlePath(links[i]));
            return paths;
        };
    };
    function d3_layout_bundlePath(link) {
        var start = link.source, end = link.target, lca = d3_layout_bundleLeastCommonAncestor(start, end), points = [ start ];
        while (start !== lca) {
            start = start.parent;
            points.push(start);
        }
        var k = points.length;
        while (end !== lca) {
            points.splice(k, 0, end);
            end = end.parent;
        }
        return points;
    }
    function d3_layout_bundleAncestors(node) {
        var ancestors = [], parent = node.parent;
        while (parent != null) {
            ancestors.push(node);
            node = parent;
            parent = parent.parent;
        }
        ancestors.push(node);
        return ancestors;
    }
    function d3_layout_bundleLeastCommonAncestor(a, b) {
        if (a === b) return a;
        var aNodes = d3_layout_bundleAncestors(a), bNodes = d3_layout_bundleAncestors(b), aNode = aNodes.pop(), bNode = bNodes.pop(), sharedNode = null;
        while (aNode === bNode) {
            sharedNode = aNode;
            aNode = aNodes.pop();
            bNode = bNodes.pop();
        }
        return sharedNode;
    }
    d3.layout.chord = function() {
        var chord = {}, chords, groups, matrix, n, padding = 0, sortGroups, sortSubgroups, sortChords;
        function relayout() {
            var subgroups = {}, groupSums = [], groupIndex = d3.range(n), subgroupIndex = [], k, x, x0, i, j;
            chords = [];
            groups = [];
            k = 0, i = -1;
            while (++i < n) {
                x = 0, j = -1;
                while (++j < n) {
                    x += matrix[i][j];
                }
                groupSums.push(x);
                subgroupIndex.push(d3.range(n));
                k += x;
            }
            if (sortGroups) {
                groupIndex.sort(function(a, b) {
                    return sortGroups(groupSums[a], groupSums[b]);
                });
            }
            if (sortSubgroups) {
                subgroupIndex.forEach(function(d, i) {
                    d.sort(function(a, b) {
                        return sortSubgroups(matrix[i][a], matrix[i][b]);
                    });
                });
            }
            k = (τ - padding * n) / k;
            x = 0, i = -1;
            while (++i < n) {
                x0 = x, j = -1;
                while (++j < n) {
                    var di = groupIndex[i], dj = subgroupIndex[di][j], v = matrix[di][dj], a0 = x, a1 = x += v * k;
                    subgroups[di + "-" + dj] = {
                        index: di,
                        subindex: dj,
                        startAngle: a0,
                        endAngle: a1,
                        value: v
                    };
                }
                groups[di] = {
                    index: di,
                    startAngle: x0,
                    endAngle: x,
                    value: (x - x0) / k
                };
                x += padding;
            }
            i = -1;
            while (++i < n) {
                j = i - 1;
                while (++j < n) {
                    var source = subgroups[i + "-" + j], target = subgroups[j + "-" + i];
                    if (source.value || target.value) {
                        chords.push(source.value < target.value ? {
                            source: target,
                            target: source
                        } : {
                            source: source,
                            target: target
                        });
                    }
                }
            }
            if (sortChords) resort();
        }
        function resort() {
            chords.sort(function(a, b) {
                return sortChords((a.source.value + a.target.value) / 2, (b.source.value + b.target.value) / 2);
            });
        }
        chord.matrix = function(x) {
            if (!arguments.length) return matrix;
            n = (matrix = x) && matrix.length;
            chords = groups = null;
            return chord;
        };
        chord.padding = function(x) {
            if (!arguments.length) return padding;
            padding = x;
            chords = groups = null;
            return chord;
        };
        chord.sortGroups = function(x) {
            if (!arguments.length) return sortGroups;
            sortGroups = x;
            chords = groups = null;
            return chord;
        };
        chord.sortSubgroups = function(x) {
            if (!arguments.length) return sortSubgroups;
            sortSubgroups = x;
            chords = null;
            return chord;
        };
        chord.sortChords = function(x) {
            if (!arguments.length) return sortChords;
            sortChords = x;
            if (chords) resort();
            return chord;
        };
        chord.chords = function() {
            if (!chords) relayout();
            return chords;
        };
        chord.groups = function() {
            if (!groups) relayout();
            return groups;
        };
        return chord;
    };
    d3.layout.force = function() {
        var force = {}, event = d3.dispatch("start", "tick", "end"), size = [ 1, 1 ], drag, alpha, friction = .9, linkDistance = d3_layout_forceLinkDistance, linkStrength = d3_layout_forceLinkStrength, charge = -30, chargeDistance2 = d3_layout_forceChargeDistance2, gravity = .1, theta2 = .64, nodes = [], links = [], distances, strengths, charges;
        function repulse(node) {
            return function(quad, x1, _, x2) {
                if (quad.point !== node) {
                    var dx = quad.cx - node.x, dy = quad.cy - node.y, dw = x2 - x1, dn = dx * dx + dy * dy;
                    if (dw * dw / theta2 < dn) {
                        if (dn < chargeDistance2) {
                            var k = quad.charge / dn;
                            node.px -= dx * k;
                            node.py -= dy * k;
                        }
                        return true;
                    }
                    if (quad.point && dn && dn < chargeDistance2) {
                        var k = quad.pointCharge / dn;
                        node.px -= dx * k;
                        node.py -= dy * k;
                    }
                }
                return !quad.charge;
            };
        }
        force.tick = function() {
            if ((alpha *= .99) < .005) {
                event.end({
                    type: "end",
                    alpha: alpha = 0
                });
                return true;
            }
            var n = nodes.length, m = links.length, q, i, o, s, t, l, k, x, y;
            for (i = 0; i < m; ++i) {
                o = links[i];
                s = o.source;
                t = o.target;
                x = t.x - s.x;
                y = t.y - s.y;
                if (l = x * x + y * y) {
                    l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l;
                    x *= l;
                    y *= l;
                    t.x -= x * (k = s.weight / (t.weight + s.weight));
                    t.y -= y * k;
                    s.x += x * (k = 1 - k);
                    s.y += y * k;
                }
            }
            if (k = alpha * gravity) {
                x = size[0] / 2;
                y = size[1] / 2;
                i = -1;
                if (k) while (++i < n) {
                    o = nodes[i];
                    o.x += (x - o.x) * k;
                    o.y += (y - o.y) * k;
                }
            }
            if (charge) {
                d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes), alpha, charges);
                i = -1;
                while (++i < n) {
                    if (!(o = nodes[i]).fixed) {
                        q.visit(repulse(o));
                    }
                }
            }
            i = -1;
            while (++i < n) {
                o = nodes[i];
                if (o.fixed) {
                    o.x = o.px;
                    o.y = o.py;
                } else {
                    o.x -= (o.px - (o.px = o.x)) * friction;
                    o.y -= (o.py - (o.py = o.y)) * friction;
                }
            }
            event.tick({
                type: "tick",
                alpha: alpha
            });
        };
        force.nodes = function(x) {
            if (!arguments.length) return nodes;
            nodes = x;
            return force;
        };
        force.links = function(x) {
            if (!arguments.length) return links;
            links = x;
            return force;
        };
        force.size = function(x) {
            if (!arguments.length) return size;
            size = x;
            return force;
        };
        force.linkDistance = function(x) {
            if (!arguments.length) return linkDistance;
            linkDistance = typeof x === "function" ? x : +x;
            return force;
        };
        force.distance = force.linkDistance;
        force.linkStrength = function(x) {
            if (!arguments.length) return linkStrength;
            linkStrength = typeof x === "function" ? x : +x;
            return force;
        };
        force.friction = function(x) {
            if (!arguments.length) return friction;
            friction = +x;
            return force;
        };
        force.charge = function(x) {
            if (!arguments.length) return charge;
            charge = typeof x === "function" ? x : +x;
            return force;
        };
        force.chargeDistance = function(x) {
            if (!arguments.length) return Math.sqrt(chargeDistance2);
            chargeDistance2 = x * x;
            return force;
        };
        force.gravity = function(x) {
            if (!arguments.length) return gravity;
            gravity = +x;
            return force;
        };
        force.theta = function(x) {
            if (!arguments.length) return Math.sqrt(theta2);
            theta2 = x * x;
            return force;
        };
        force.alpha = function(x) {
            if (!arguments.length) return alpha;
            x = +x;
            if (alpha) {
                if (x > 0) alpha = x; else alpha = 0;
            } else if (x > 0) {
                event.start({
                    type: "start",
                    alpha: alpha = x
                });
                d3.timer(force.tick);
            }
            return force;
        };
        force.start = function() {
            var i, n = nodes.length, m = links.length, w = size[0], h = size[1], neighbors, o;
            for (i = 0; i < n; ++i) {
                (o = nodes[i]).index = i;
                o.weight = 0;
            }
            for (i = 0; i < m; ++i) {
                o = links[i];
                if (typeof o.source == "number") o.source = nodes[o.source];
                if (typeof o.target == "number") o.target = nodes[o.target];
                ++o.source.weight;
                ++o.target.weight;
            }
            for (i = 0; i < n; ++i) {
                o = nodes[i];
                if (isNaN(o.x)) o.x = position("x", w);
                if (isNaN(o.y)) o.y = position("y", h);
                if (isNaN(o.px)) o.px = o.x;
                if (isNaN(o.py)) o.py = o.y;
            }
            distances = [];
            if (typeof linkDistance === "function") for (i = 0; i < m; ++i) distances[i] = +linkDistance.call(this, links[i], i); else for (i = 0; i < m; ++i) distances[i] = linkDistance;
            strengths = [];
            if (typeof linkStrength === "function") for (i = 0; i < m; ++i) strengths[i] = +linkStrength.call(this, links[i], i); else for (i = 0; i < m; ++i) strengths[i] = linkStrength;
            charges = [];
            if (typeof charge === "function") for (i = 0; i < n; ++i) charges[i] = +charge.call(this, nodes[i], i); else for (i = 0; i < n; ++i) charges[i] = charge;
            function position(dimension, size) {
                if (!neighbors) {
                    neighbors = new Array(n);
                    for (j = 0; j < n; ++j) {
                        neighbors[j] = [];
                    }
                    for (j = 0; j < m; ++j) {
                        var o = links[j];
                        neighbors[o.source.index].push(o.target);
                        neighbors[o.target.index].push(o.source);
                    }
                }
                var candidates = neighbors[i], j = -1, l = candidates.length, x;
                while (++j < l) if (!isNaN(x = candidates[j][dimension])) return x;
                return Math.random() * size;
            }
            return force.resume();
        };
        force.resume = function() {
            return force.alpha(.1);
        };
        force.stop = function() {
            return force.alpha(0);
        };
        force.drag = function() {
            if (!drag) drag = d3.behavior.drag().origin(d3_identity).on("dragstart.force", d3_layout_forceDragstart).on("drag.force", dragmove).on("dragend.force", d3_layout_forceDragend);
            if (!arguments.length) return drag;
            this.on("mouseover.force", d3_layout_forceMouseover).on("mouseout.force", d3_layout_forceMouseout).call(drag);
        };
        function dragmove(d) {
            d.px = d3.event.x, d.py = d3.event.y;
            force.resume();
        }
        return d3.rebind(force, event, "on");
    };
    function d3_layout_forceDragstart(d) {
        d.fixed |= 2;
    }
    function d3_layout_forceDragend(d) {
        d.fixed &= ~6;
    }
    function d3_layout_forceMouseover(d) {
        d.fixed |= 4;
        d.px = d.x, d.py = d.y;
    }
    function d3_layout_forceMouseout(d) {
        d.fixed &= ~4;
    }
    function d3_layout_forceAccumulate(quad, alpha, charges) {
        var cx = 0, cy = 0;
        quad.charge = 0;
        if (!quad.leaf) {
            var nodes = quad.nodes, n = nodes.length, i = -1, c;
            while (++i < n) {
                c = nodes[i];
                if (c == null) continue;
                d3_layout_forceAccumulate(c, alpha, charges);
                quad.charge += c.charge;
                cx += c.charge * c.cx;
                cy += c.charge * c.cy;
            }
        }
        if (quad.point) {
            if (!quad.leaf) {
                quad.point.x += Math.random() - .5;
                quad.point.y += Math.random() - .5;
            }
            var k = alpha * charges[quad.point.index];
            quad.charge += quad.pointCharge = k;
            cx += k * quad.point.x;
            cy += k * quad.point.y;
        }
        quad.cx = cx / quad.charge;
        quad.cy = cy / quad.charge;
    }
    var d3_layout_forceLinkDistance = 20, d3_layout_forceLinkStrength = 1, d3_layout_forceChargeDistance2 = Infinity;
    d3.layout.hierarchy = function() {
        var sort = d3_layout_hierarchySort, children = d3_layout_hierarchyChildren, value = d3_layout_hierarchyValue;
        function hierarchy(root) {
            var stack = [ root ], nodes = [], node;
            root.depth = 0;
            while ((node = stack.pop()) != null) {
                nodes.push(node);
                if ((childs = children.call(hierarchy, node, node.depth)) && (n = childs.length)) {
                    var n, childs, child;
                    while (--n >= 0) {
                        stack.push(child = childs[n]);
                        child.parent = node;
                        child.depth = node.depth + 1;
                    }
                    if (value) node.value = 0;
                    node.children = childs;
                } else {
                    if (value) node.value = +value.call(hierarchy, node, node.depth) || 0;
                    delete node.children;
                }
            }
            d3_layout_hierarchyVisitAfter(root, function(node) {
                var childs, parent;
                if (sort && (childs = node.children)) childs.sort(sort);
                if (value && (parent = node.parent)) parent.value += node.value;
            });
            return nodes;
        }
        hierarchy.sort = function(x) {
            if (!arguments.length) return sort;
            sort = x;
            return hierarchy;
        };
        hierarchy.children = function(x) {
            if (!arguments.length) return children;
            children = x;
            return hierarchy;
        };
        hierarchy.value = function(x) {
            if (!arguments.length) return value;
            value = x;
            return hierarchy;
        };
        hierarchy.revalue = function(root) {
            if (value) {
                d3_layout_hierarchyVisitBefore(root, function(node) {
                    if (node.children) node.value = 0;
                });
                d3_layout_hierarchyVisitAfter(root, function(node) {
                    var parent;
                    if (!node.children) node.value = +value.call(hierarchy, node, node.depth) || 0;
                    if (parent = node.parent) parent.value += node.value;
                });
            }
            return root;
        };
        return hierarchy;
    };
    function d3_layout_hierarchyRebind(object, hierarchy) {
        d3.rebind(object, hierarchy, "sort", "children", "value");
        object.nodes = object;
        object.links = d3_layout_hierarchyLinks;
        return object;
    }
    function d3_layout_hierarchyVisitBefore(node, callback) {
        var nodes = [ node ];
        while ((node = nodes.pop()) != null) {
            callback(node);
            if ((children = node.children) && (n = children.length)) {
                var n, children;
                while (--n >= 0) nodes.push(children[n]);
            }
        }
    }
    function d3_layout_hierarchyVisitAfter(node, callback) {
        var nodes = [ node ], nodes2 = [];
        while ((node = nodes.pop()) != null) {
            nodes2.push(node);
            if ((children = node.children) && (n = children.length)) {
                var i = -1, n, children;
                while (++i < n) nodes.push(children[i]);
            }
        }
        while ((node = nodes2.pop()) != null) {
            callback(node);
        }
    }
    function d3_layout_hierarchyChildren(d) {
        return d.children;
    }
    function d3_layout_hierarchyValue(d) {
        return d.value;
    }
    function d3_layout_hierarchySort(a, b) {
        return b.value - a.value;
    }
    function d3_layout_hierarchyLinks(nodes) {
        return d3.merge(nodes.map(function(parent) {
            return (parent.children || []).map(function(child) {
                return {
                    source: parent,
                    target: child
                };
            });
        }));
    }
    d3.layout.partition = function() {
        var hierarchy = d3.layout.hierarchy(), size = [ 1, 1 ];
        function position(node, x, dx, dy) {
            var children = node.children;
            node.x = x;
            node.y = node.depth * dy;
            node.dx = dx;
            node.dy = dy;
            if (children && (n = children.length)) {
                var i = -1, n, c, d;
                dx = node.value ? dx / node.value : 0;
                while (++i < n) {
                    position(c = children[i], x, d = c.value * dx, dy);
                    x += d;
                }
            }
        }
        function depth(node) {
            var children = node.children, d = 0;
            if (children && (n = children.length)) {
                var i = -1, n;
                while (++i < n) d = Math.max(d, depth(children[i]));
            }
            return 1 + d;
        }
        function partition(d, i) {
            var nodes = hierarchy.call(this, d, i);
            position(nodes[0], 0, size[0], size[1] / depth(nodes[0]));
            return nodes;
        }
        partition.size = function(x) {
            if (!arguments.length) return size;
            size = x;
            return partition;
        };
        return d3_layout_hierarchyRebind(partition, hierarchy);
    };
    d3.layout.pie = function() {
        var value = Number, sort = d3_layout_pieSortByValue, startAngle = 0, endAngle = τ, padAngle = 0;
        function pie(data) {
            var n = data.length, values = data.map(function(d, i) {
                return +value.call(pie, d, i);
            }), a = +(typeof startAngle === "function" ? startAngle.apply(this, arguments) : startAngle), da = (typeof endAngle === "function" ? endAngle.apply(this, arguments) : endAngle) - a, p = Math.min(Math.abs(da) / n, +(typeof padAngle === "function" ? padAngle.apply(this, arguments) : padAngle)), pa = p * (da < 0 ? -1 : 1), k = (da - n * pa) / d3.sum(values), index = d3.range(n), arcs = [], v;
            if (sort != null) index.sort(sort === d3_layout_pieSortByValue ? function(i, j) {
                return values[j] - values[i];
            } : function(i, j) {
                return sort(data[i], data[j]);
            });
            index.forEach(function(i) {
                arcs[i] = {
                    data: data[i],
                    value: v = values[i],
                    startAngle: a,
                    endAngle: a += v * k + pa,
                    padAngle: p
                };
            });
            return arcs;
        }
        pie.value = function(_) {
            if (!arguments.length) return value;
            value = _;
            return pie;
        };
        pie.sort = function(_) {
            if (!arguments.length) return sort;
            sort = _;
            return pie;
        };
        pie.startAngle = function(_) {
            if (!arguments.length) return startAngle;
            startAngle = _;
            return pie;
        };
        pie.endAngle = function(_) {
            if (!arguments.length) return endAngle;
            endAngle = _;
            return pie;
        };
        pie.padAngle = function(_) {
            if (!arguments.length) return padAngle;
            padAngle = _;
            return pie;
        };
        return pie;
    };
    var d3_layout_pieSortByValue = {};
    d3.layout.stack = function() {
        var values = d3_identity, order = d3_layout_stackOrderDefault, offset = d3_layout_stackOffsetZero, out = d3_layout_stackOut, x = d3_layout_stackX, y = d3_layout_stackY;
        function stack(data, index) {
            if (!(n = data.length)) return data;
            var series = data.map(function(d, i) {
                return values.call(stack, d, i);
            });
            var points = series.map(function(d) {
                return d.map(function(v, i) {
                    return [ x.call(stack, v, i), y.call(stack, v, i) ];
                });
            });
            var orders = order.call(stack, points, index);
            series = d3.permute(series, orders);
            points = d3.permute(points, orders);
            var offsets = offset.call(stack, points, index);
            var m = series[0].length, n, i, j, o;
            for (j = 0; j < m; ++j) {
                out.call(stack, series[0][j], o = offsets[j], points[0][j][1]);
                for (i = 1; i < n; ++i) {
                    out.call(stack, series[i][j], o += points[i - 1][j][1], points[i][j][1]);
                }
            }
            return data;
        }
        stack.values = function(x) {
            if (!arguments.length) return values;
            values = x;
            return stack;
        };
        stack.order = function(x) {
            if (!arguments.length) return order;
            order = typeof x === "function" ? x : d3_layout_stackOrders.get(x) || d3_layout_stackOrderDefault;
            return stack;
        };
        stack.offset = function(x) {
            if (!arguments.length) return offset;
            offset = typeof x === "function" ? x : d3_layout_stackOffsets.get(x) || d3_layout_stackOffsetZero;
            return stack;
        };
        stack.x = function(z) {
            if (!arguments.length) return x;
            x = z;
            return stack;
        };
        stack.y = function(z) {
            if (!arguments.length) return y;
            y = z;
            return stack;
        };
        stack.out = function(z) {
            if (!arguments.length) return out;
            out = z;
            return stack;
        };
        return stack;
    };
    function d3_layout_stackX(d) {
        return d.x;
    }
    function d3_layout_stackY(d) {
        return d.y;
    }
    function d3_layout_stackOut(d, y0, y) {
        d.y0 = y0;
        d.y = y;
    }
    var d3_layout_stackOrders = d3.map({
        "inside-out": function(data) {
            var n = data.length, i, j, max = data.map(d3_layout_stackMaxIndex), sums = data.map(d3_layout_stackReduceSum), index = d3.range(n).sort(function(a, b) {
                return max[a] - max[b];
            }), top = 0, bottom = 0, tops = [], bottoms = [];
            for (i = 0; i < n; ++i) {
                j = index[i];
                if (top < bottom) {
                    top += sums[j];
                    tops.push(j);
                } else {
                    bottom += sums[j];
                    bottoms.push(j);
                }
            }
            return bottoms.reverse().concat(tops);
        },
        reverse: function(data) {
            return d3.range(data.length).reverse();
        },
        default: d3_layout_stackOrderDefault
    });
    var d3_layout_stackOffsets = d3.map({
        silhouette: function(data) {
            var n = data.length, m = data[0].length, sums = [], max = 0, i, j, o, y0 = [];
            for (j = 0; j < m; ++j) {
                for (i = 0, o = 0; i < n; i++) o += data[i][j][1];
                if (o > max) max = o;
                sums.push(o);
            }
            for (j = 0; j < m; ++j) {
                y0[j] = (max - sums[j]) / 2;
            }
            return y0;
        },
        wiggle: function(data) {
            var n = data.length, x = data[0], m = x.length, i, j, k, s1, s2, s3, dx, o, o0, y0 = [];
            y0[0] = o = o0 = 0;
            for (j = 1; j < m; ++j) {
                for (i = 0, s1 = 0; i < n; ++i) s1 += data[i][j][1];
                for (i = 0, s2 = 0, dx = x[j][0] - x[j - 1][0]; i < n; ++i) {
                    for (k = 0, s3 = (data[i][j][1] - data[i][j - 1][1]) / (2 * dx); k < i; ++k) {
                        s3 += (data[k][j][1] - data[k][j - 1][1]) / dx;
                    }
                    s2 += s3 * data[i][j][1];
                }
                y0[j] = o -= s1 ? s2 / s1 * dx : 0;
                if (o < o0) o0 = o;
            }
            for (j = 0; j < m; ++j) y0[j] -= o0;
            return y0;
        },
        expand: function(data) {
            var n = data.length, m = data[0].length, k = 1 / n, i, j, o, y0 = [];
            for (j = 0; j < m; ++j) {
                for (i = 0, o = 0; i < n; i++) o += data[i][j][1];
                if (o) for (i = 0; i < n; i++) data[i][j][1] /= o; else for (i = 0; i < n; i++) data[i][j][1] = k;
            }
            for (j = 0; j < m; ++j) y0[j] = 0;
            return y0;
        },
        zero: d3_layout_stackOffsetZero
    });
    function d3_layout_stackOrderDefault(data) {
        return d3.range(data.length);
    }
    function d3_layout_stackOffsetZero(data) {
        var j = -1, m = data[0].length, y0 = [];
        while (++j < m) y0[j] = 0;
        return y0;
    }
    function d3_layout_stackMaxIndex(array) {
        var i = 1, j = 0, v = array[0][1], k, n = array.length;
        for (;i < n; ++i) {
            if ((k = array[i][1]) > v) {
                j = i;
                v = k;
            }
        }
        return j;
    }
    function d3_layout_stackReduceSum(d) {
        return d.reduce(d3_layout_stackSum, 0);
    }
    function d3_layout_stackSum(p, d) {
        return p + d[1];
    }
    d3.layout.histogram = function() {
        var frequency = true, valuer = Number, ranger = d3_layout_histogramRange, binner = d3_layout_histogramBinSturges;
        function histogram(data, i) {
            var bins = [], values = data.map(valuer, this), range = ranger.call(this, values, i), thresholds = binner.call(this, range, values, i), bin, i = -1, n = values.length, m = thresholds.length - 1, k = frequency ? 1 : 1 / n, x;
            while (++i < m) {
                bin = bins[i] = [];
                bin.dx = thresholds[i + 1] - (bin.x = thresholds[i]);
                bin.y = 0;
            }
            if (m > 0) {
                i = -1;
                while (++i < n) {
                    x = values[i];
                    if (x >= range[0] && x <= range[1]) {
                        bin = bins[d3.bisect(thresholds, x, 1, m) - 1];
                        bin.y += k;
                        bin.push(data[i]);
                    }
                }
            }
            return bins;
        }
        histogram.value = function(x) {
            if (!arguments.length) return valuer;
            valuer = x;
            return histogram;
        };
        histogram.range = function(x) {
            if (!arguments.length) return ranger;
            ranger = d3_functor(x);
            return histogram;
        };
        histogram.bins = function(x) {
            if (!arguments.length) return binner;
            binner = typeof x === "number" ? function(range) {
                return d3_layout_histogramBinFixed(range, x);
            } : d3_functor(x);
            return histogram;
        };
        histogram.frequency = function(x) {
            if (!arguments.length) return frequency;
            frequency = !!x;
            return histogram;
        };
        return histogram;
    };
    function d3_layout_histogramBinSturges(range, values) {
        return d3_layout_histogramBinFixed(range, Math.ceil(Math.log(values.length) / Math.LN2 + 1));
    }
    function d3_layout_histogramBinFixed(range, n) {
        var x = -1, b = +range[0], m = (range[1] - b) / n, f = [];
        while (++x <= n) f[x] = m * x + b;
        return f;
    }
    function d3_layout_histogramRange(values) {
        return [ d3.min(values), d3.max(values) ];
    }
    d3.layout.pack = function() {
        var hierarchy = d3.layout.hierarchy().sort(d3_layout_packSort), padding = 0, size = [ 1, 1 ], radius;
        function pack(d, i) {
            var nodes = hierarchy.call(this, d, i), root = nodes[0], w = size[0], h = size[1], r = radius == null ? Math.sqrt : typeof radius === "function" ? radius : function() {
                return radius;
            };
            root.x = root.y = 0;
            d3_layout_hierarchyVisitAfter(root, function(d) {
                d.r = +r(d.value);
            });
            d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings);
            if (padding) {
                var dr = padding * (radius ? 1 : Math.max(2 * root.r / w, 2 * root.r / h)) / 2;
                d3_layout_hierarchyVisitAfter(root, function(d) {
                    d.r += dr;
                });
                d3_layout_hierarchyVisitAfter(root, d3_layout_packSiblings);
                d3_layout_hierarchyVisitAfter(root, function(d) {
                    d.r -= dr;
                });
            }
            d3_layout_packTransform(root, w / 2, h / 2, radius ? 1 : 1 / Math.max(2 * root.r / w, 2 * root.r / h));
            return nodes;
        }
        pack.size = function(_) {
            if (!arguments.length) return size;
            size = _;
            return pack;
        };
        pack.radius = function(_) {
            if (!arguments.length) return radius;
            radius = _ == null || typeof _ === "function" ? _ : +_;
            return pack;
        };
        pack.padding = function(_) {
            if (!arguments.length) return padding;
            padding = +_;
            return pack;
        };
        return d3_layout_hierarchyRebind(pack, hierarchy);
    };
    function d3_layout_packSort(a, b) {
        return a.value - b.value;
    }
    function d3_layout_packInsert(a, b) {
        var c = a._pack_next;
        a._pack_next = b;
        b._pack_prev = a;
        b._pack_next = c;
        c._pack_prev = b;
    }
    function d3_layout_packSplice(a, b) {
        a._pack_next = b;
        b._pack_prev = a;
    }
    function d3_layout_packIntersects(a, b) {
        var dx = b.x - a.x, dy = b.y - a.y, dr = a.r + b.r;
        return .999 * dr * dr > dx * dx + dy * dy;
    }
    function d3_layout_packSiblings(node) {
        if (!(nodes = node.children) || !(n = nodes.length)) return;
        var nodes, xMin = Infinity, xMax = -Infinity, yMin = Infinity, yMax = -Infinity, a, b, c, i, j, k, n;
        function bound(node) {
            xMin = Math.min(node.x - node.r, xMin);
            xMax = Math.max(node.x + node.r, xMax);
            yMin = Math.min(node.y - node.r, yMin);
            yMax = Math.max(node.y + node.r, yMax);
        }
        nodes.forEach(d3_layout_packLink);
        a = nodes[0];
        a.x = -a.r;
        a.y = 0;
        bound(a);
        if (n > 1) {
            b = nodes[1];
            b.x = b.r;
            b.y = 0;
            bound(b);
            if (n > 2) {
                c = nodes[2];
                d3_layout_packPlace(a, b, c);
                bound(c);
                d3_layout_packInsert(a, c);
                a._pack_prev = c;
                d3_layout_packInsert(c, b);
                b = a._pack_next;
                for (i = 3; i < n; i++) {
                    d3_layout_packPlace(a, b, c = nodes[i]);
                    var isect = 0, s1 = 1, s2 = 1;
                    for (j = b._pack_next; j !== b; j = j._pack_next, s1++) {
                        if (d3_layout_packIntersects(j, c)) {
                            isect = 1;
                            break;
                        }
                    }
                    if (isect == 1) {
                        for (k = a._pack_prev; k !== j._pack_prev; k = k._pack_prev, 
                        s2++) {
                            if (d3_layout_packIntersects(k, c)) {
                                break;
                            }
                        }
                    }
                    if (isect) {
                        if (s1 < s2 || s1 == s2 && b.r < a.r) d3_layout_packSplice(a, b = j); else d3_layout_packSplice(a = k, b);
                        i--;
                    } else {
                        d3_layout_packInsert(a, c);
                        b = c;
                        bound(c);
                    }
                }
            }
        }
        var cx = (xMin + xMax) / 2, cy = (yMin + yMax) / 2, cr = 0;
        for (i = 0; i < n; i++) {
            c = nodes[i];
            c.x -= cx;
            c.y -= cy;
            cr = Math.max(cr, c.r + Math.sqrt(c.x * c.x + c.y * c.y));
        }
        node.r = cr;
        nodes.forEach(d3_layout_packUnlink);
    }
    function d3_layout_packLink(node) {
        node._pack_next = node._pack_prev = node;
    }
    function d3_layout_packUnlink(node) {
        delete node._pack_next;
        delete node._pack_prev;
    }
    function d3_layout_packTransform(node, x, y, k) {
        var children = node.children;
        node.x = x += k * node.x;
        node.y = y += k * node.y;
        node.r *= k;
        if (children) {
            var i = -1, n = children.length;
            while (++i < n) d3_layout_packTransform(children[i], x, y, k);
        }
    }
    function d3_layout_packPlace(a, b, c) {
        var db = a.r + c.r, dx = b.x - a.x, dy = b.y - a.y;
        if (db && (dx || dy)) {
            var da = b.r + c.r, dc = dx * dx + dy * dy;
            da *= da;
            db *= db;
            var x = .5 + (db - da) / (2 * dc), y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc);
            c.x = a.x + x * dx + y * dy;
            c.y = a.y + x * dy - y * dx;
        } else {
            c.x = a.x + db;
            c.y = a.y;
        }
    }
    d3.layout.tree = function() {
        var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = null;
        function tree(d, i) {
            var nodes = hierarchy.call(this, d, i), root0 = nodes[0], root1 = wrapTree(root0);
            d3_layout_hierarchyVisitAfter(root1, firstWalk), root1.parent.m = -root1.z;
            d3_layout_hierarchyVisitBefore(root1, secondWalk);
            if (nodeSize) d3_layout_hierarchyVisitBefore(root0, sizeNode); else {
                var left = root0, right = root0, bottom = root0;
                d3_layout_hierarchyVisitBefore(root0, function(node) {
                    if (node.x < left.x) left = node;
                    if (node.x > right.x) right = node;
                    if (node.depth > bottom.depth) bottom = node;
                });
                var tx = separation(left, right) / 2 - left.x, kx = size[0] / (right.x + separation(right, left) / 2 + tx), ky = size[1] / (bottom.depth || 1);
                d3_layout_hierarchyVisitBefore(root0, function(node) {
                    node.x = (node.x + tx) * kx;
                    node.y = node.depth * ky;
                });
            }
            return nodes;
        }
        function wrapTree(root0) {
            var root1 = {
                A: null,
                children: [ root0 ]
            }, queue = [ root1 ], node1;
            while ((node1 = queue.pop()) != null) {
                for (var children = node1.children, child, i = 0, n = children.length; i < n; ++i) {
                    queue.push((children[i] = child = {
                        _: children[i],
                        parent: node1,
                        children: (child = children[i].children) && child.slice() || [],
                        A: null,
                        a: null,
                        z: 0,
                        m: 0,
                        c: 0,
                        s: 0,
                        t: null,
                        i: i
                    }).a = child);
                }
            }
            return root1.children[0];
        }
        function firstWalk(v) {
            var children = v.children, siblings = v.parent.children, w = v.i ? siblings[v.i - 1] : null;
            if (children.length) {
                d3_layout_treeShift(v);
                var midpoint = (children[0].z + children[children.length - 1].z) / 2;
                if (w) {
                    v.z = w.z + separation(v._, w._);
                    v.m = v.z - midpoint;
                } else {
                    v.z = midpoint;
                }
            } else if (w) {
                v.z = w.z + separation(v._, w._);
            }
            v.parent.A = apportion(v, w, v.parent.A || siblings[0]);
        }
        function secondWalk(v) {
            v._.x = v.z + v.parent.m;
            v.m += v.parent.m;
        }
        function apportion(v, w, ancestor) {
            if (w) {
                var vip = v, vop = v, vim = w, vom = vip.parent.children[0], sip = vip.m, sop = vop.m, sim = vim.m, som = vom.m, shift;
                while (vim = d3_layout_treeRight(vim), vip = d3_layout_treeLeft(vip), 
                vim && vip) {
                    vom = d3_layout_treeLeft(vom);
                    vop = d3_layout_treeRight(vop);
                    vop.a = v;
                    shift = vim.z + sim - vip.z - sip + separation(vim._, vip._);
                    if (shift > 0) {
                        d3_layout_treeMove(d3_layout_treeAncestor(vim, v, ancestor), v, shift);
                        sip += shift;
                        sop += shift;
                    }
                    sim += vim.m;
                    sip += vip.m;
                    som += vom.m;
                    sop += vop.m;
                }
                if (vim && !d3_layout_treeRight(vop)) {
                    vop.t = vim;
                    vop.m += sim - sop;
                }
                if (vip && !d3_layout_treeLeft(vom)) {
                    vom.t = vip;
                    vom.m += sip - som;
                    ancestor = v;
                }
            }
            return ancestor;
        }
        function sizeNode(node) {
            node.x *= size[0];
            node.y = node.depth * size[1];
        }
        tree.separation = function(x) {
            if (!arguments.length) return separation;
            separation = x;
            return tree;
        };
        tree.size = function(x) {
            if (!arguments.length) return nodeSize ? null : size;
            nodeSize = (size = x) == null ? sizeNode : null;
            return tree;
        };
        tree.nodeSize = function(x) {
            if (!arguments.length) return nodeSize ? size : null;
            nodeSize = (size = x) == null ? null : sizeNode;
            return tree;
        };
        return d3_layout_hierarchyRebind(tree, hierarchy);
    };
    function d3_layout_treeSeparation(a, b) {
        return a.parent == b.parent ? 1 : 2;
    }
    function d3_layout_treeLeft(v) {
        var children = v.children;
        return children.length ? children[0] : v.t;
    }
    function d3_layout_treeRight(v) {
        var children = v.children, n;
        return (n = children.length) ? children[n - 1] : v.t;
    }
    function d3_layout_treeMove(wm, wp, shift) {
        var change = shift / (wp.i - wm.i);
        wp.c -= change;
        wp.s += shift;
        wm.c += change;
        wp.z += shift;
        wp.m += shift;
    }
    function d3_layout_treeShift(v) {
        var shift = 0, change = 0, children = v.children, i = children.length, w;
        while (--i >= 0) {
            w = children[i];
            w.z += shift;
            w.m += shift;
            shift += w.s + (change += w.c);
        }
    }
    function d3_layout_treeAncestor(vim, v, ancestor) {
        return vim.a.parent === v.parent ? vim.a : ancestor;
    }
    d3.layout.cluster = function() {
        var hierarchy = d3.layout.hierarchy().sort(null).value(null), separation = d3_layout_treeSeparation, size = [ 1, 1 ], nodeSize = false;
        function cluster(d, i) {
            var nodes = hierarchy.call(this, d, i), root = nodes[0], previousNode, x = 0;
            d3_layout_hierarchyVisitAfter(root, function(node) {
                var children = node.children;
                if (children && children.length) {
                    node.x = d3_layout_clusterX(children);
                    node.y = d3_layout_clusterY(children);
                } else {
                    node.x = previousNode ? x += separation(node, previousNode) : 0;
                    node.y = 0;
                    previousNode = node;
                }
            });
            var left = d3_layout_clusterLeft(root), right = d3_layout_clusterRight(root), x0 = left.x - separation(left, right) / 2, x1 = right.x + separation(right, left) / 2;
            d3_layout_hierarchyVisitAfter(root, nodeSize ? function(node) {
                node.x = (node.x - root.x) * size[0];
                node.y = (root.y - node.y) * size[1];
            } : function(node) {
                node.x = (node.x - x0) / (x1 - x0) * size[0];
                node.y = (1 - (root.y ? node.y / root.y : 1)) * size[1];
            });
            return nodes;
        }
        cluster.separation = function(x) {
            if (!arguments.length) return separation;
            separation = x;
            return cluster;
        };
        cluster.size = function(x) {
            if (!arguments.length) return nodeSize ? null : size;
            nodeSize = (size = x) == null;
            return cluster;
        };
        cluster.nodeSize = function(x) {
            if (!arguments.length) return nodeSize ? size : null;
            nodeSize = (size = x) != null;
            return cluster;
        };
        return d3_layout_hierarchyRebind(cluster, hierarchy);
    };
    function d3_layout_clusterY(children) {
        return 1 + d3.max(children, function(child) {
            return child.y;
        });
    }
    function d3_layout_clusterX(children) {
        return children.reduce(function(x, child) {
            return x + child.x;
        }, 0) / children.length;
    }
    function d3_layout_clusterLeft(node) {
        var children = node.children;
        return children && children.length ? d3_layout_clusterLeft(children[0]) : node;
    }
    function d3_layout_clusterRight(node) {
        var children = node.children, n;
        return children && (n = children.length) ? d3_layout_clusterRight(children[n - 1]) : node;
    }
    d3.layout.treemap = function() {
        var hierarchy = d3.layout.hierarchy(), round = Math.round, size = [ 1, 1 ], padding = null, pad = d3_layout_treemapPadNull, sticky = false, stickies, mode = "squarify", ratio = .5 * (1 + Math.sqrt(5));
        function scale(children, k) {
            var i = -1, n = children.length, child, area;
            while (++i < n) {
                area = (child = children[i]).value * (k < 0 ? 0 : k);
                child.area = isNaN(area) || area <= 0 ? 0 : area;
            }
        }
        function squarify(node) {
            var children = node.children;
            if (children && children.length) {
                var rect = pad(node), row = [], remaining = children.slice(), child, best = Infinity, score, u = mode === "slice" ? rect.dx : mode === "dice" ? rect.dy : mode === "slice-dice" ? node.depth & 1 ? rect.dy : rect.dx : Math.min(rect.dx, rect.dy), n;
                scale(remaining, rect.dx * rect.dy / node.value);
                row.area = 0;
                while ((n = remaining.length) > 0) {
                    row.push(child = remaining[n - 1]);
                    row.area += child.area;
                    if (mode !== "squarify" || (score = worst(row, u)) <= best) {
                        remaining.pop();
                        best = score;
                    } else {
                        row.area -= row.pop().area;
                        position(row, u, rect, false);
                        u = Math.min(rect.dx, rect.dy);
                        row.length = row.area = 0;
                        best = Infinity;
                    }
                }
                if (row.length) {
                    position(row, u, rect, true);
                    row.length = row.area = 0;
                }
                children.forEach(squarify);
            }
        }
        function stickify(node) {
            var children = node.children;
            if (children && children.length) {
                var rect = pad(node), remaining = children.slice(), child, row = [];
                scale(remaining, rect.dx * rect.dy / node.value);
                row.area = 0;
                while (child = remaining.pop()) {
                    row.push(child);
                    row.area += child.area;
                    if (child.z != null) {
                        position(row, child.z ? rect.dx : rect.dy, rect, !remaining.length);
                        row.length = row.area = 0;
                    }
                }
                children.forEach(stickify);
            }
        }
        function worst(row, u) {
            var s = row.area, r, rmax = 0, rmin = Infinity, i = -1, n = row.length;
            while (++i < n) {
                if (!(r = row[i].area)) continue;
                if (r < rmin) rmin = r;
                if (r > rmax) rmax = r;
            }
            s *= s;
            u *= u;
            return s ? Math.max(u * rmax * ratio / s, s / (u * rmin * ratio)) : Infinity;
        }
        function position(row, u, rect, flush) {
            var i = -1, n = row.length, x = rect.x, y = rect.y, v = u ? round(row.area / u) : 0, o;
            if (u == rect.dx) {
                if (flush || v > rect.dy) v = rect.dy;
                while (++i < n) {
                    o = row[i];
                    o.x = x;
                    o.y = y;
                    o.dy = v;
                    x += o.dx = Math.min(rect.x + rect.dx - x, v ? round(o.area / v) : 0);
                }
                o.z = true;
                o.dx += rect.x + rect.dx - x;
                rect.y += v;
                rect.dy -= v;
            } else {
                if (flush || v > rect.dx) v = rect.dx;
                while (++i < n) {
                    o = row[i];
                    o.x = x;
                    o.y = y;
                    o.dx = v;
                    y += o.dy = Math.min(rect.y + rect.dy - y, v ? round(o.area / v) : 0);
                }
                o.z = false;
                o.dy += rect.y + rect.dy - y;
                rect.x += v;
                rect.dx -= v;
            }
        }
        function treemap(d) {
            var nodes = stickies || hierarchy(d), root = nodes[0];
            root.x = 0;
            root.y = 0;
            root.dx = size[0];
            root.dy = size[1];
            if (stickies) hierarchy.revalue(root);
            scale([ root ], root.dx * root.dy / root.value);
            (stickies ? stickify : squarify)(root);
            if (sticky) stickies = nodes;
            return nodes;
        }
        treemap.size = function(x) {
            if (!arguments.length) return size;
            size = x;
            return treemap;
        };
        treemap.padding = function(x) {
            if (!arguments.length) return padding;
            function padFunction(node) {
                var p = x.call(treemap, node, node.depth);
                return p == null ? d3_layout_treemapPadNull(node) : d3_layout_treemapPad(node, typeof p === "number" ? [ p, p, p, p ] : p);
            }
            function padConstant(node) {
                return d3_layout_treemapPad(node, x);
            }
            var type;
            pad = (padding = x) == null ? d3_layout_treemapPadNull : (type = typeof x) === "function" ? padFunction : type === "number" ? (x = [ x, x, x, x ], 
            padConstant) : padConstant;
            return treemap;
        };
        treemap.round = function(x) {
            if (!arguments.length) return round != Number;
            round = x ? Math.round : Number;
            return treemap;
        };
        treemap.sticky = function(x) {
            if (!arguments.length) return sticky;
            sticky = x;
            stickies = null;
            return treemap;
        };
        treemap.ratio = function(x) {
            if (!arguments.length) return ratio;
            ratio = x;
            return treemap;
        };
        treemap.mode = function(x) {
            if (!arguments.length) return mode;
            mode = x + "";
            return treemap;
        };
        return d3_layout_hierarchyRebind(treemap, hierarchy);
    };
    function d3_layout_treemapPadNull(node) {
        return {
            x: node.x,
            y: node.y,
            dx: node.dx,
            dy: node.dy
        };
    }
    function d3_layout_treemapPad(node, padding) {
        var x = node.x + padding[3], y = node.y + padding[0], dx = node.dx - padding[1] - padding[3], dy = node.dy - padding[0] - padding[2];
        if (dx < 0) {
            x += dx / 2;
            dx = 0;
        }
        if (dy < 0) {
            y += dy / 2;
            dy = 0;
        }
        return {
            x: x,
            y: y,
            dx: dx,
            dy: dy
        };
    }
    d3.random = {
        normal: function(µ, σ) {
            var n = arguments.length;
            if (n < 2) σ = 1;
            if (n < 1) µ = 0;
            return function() {
                var x, y, r;
                do {
                    x = Math.random() * 2 - 1;
                    y = Math.random() * 2 - 1;
                    r = x * x + y * y;
                } while (!r || r > 1);
                return µ + σ * x * Math.sqrt(-2 * Math.log(r) / r);
            };
        },
        logNormal: function() {
            var random = d3.random.normal.apply(d3, arguments);
            return function() {
                return Math.exp(random());
            };
        },
        bates: function(m) {
            var random = d3.random.irwinHall(m);
            return function() {
                return random() / m;
            };
        },
        irwinHall: function(m) {
            return function() {
                for (var s = 0, j = 0; j < m; j++) s += Math.random();
                return s;
            };
        }
    };
    d3.scale = {};
    function d3_scaleExtent(domain) {
        var start = domain[0], stop = domain[domain.length - 1];
        return start < stop ? [ start, stop ] : [ stop, start ];
    }
    function d3_scaleRange(scale) {
        return scale.rangeExtent ? scale.rangeExtent() : d3_scaleExtent(scale.range());
    }
    function d3_scale_bilinear(domain, range, uninterpolate, interpolate) {
        var u = uninterpolate(domain[0], domain[1]), i = interpolate(range[0], range[1]);
        return function(x) {
            return i(u(x));
        };
    }
    function d3_scale_nice(domain, nice) {
        var i0 = 0, i1 = domain.length - 1, x0 = domain[i0], x1 = domain[i1], dx;
        if (x1 < x0) {
            dx = i0, i0 = i1, i1 = dx;
            dx = x0, x0 = x1, x1 = dx;
        }
        domain[i0] = nice.floor(x0);
        domain[i1] = nice.ceil(x1);
        return domain;
    }
    function d3_scale_niceStep(step) {
        return step ? {
            floor: function(x) {
                return Math.floor(x / step) * step;
            },
            ceil: function(x) {
                return Math.ceil(x / step) * step;
            }
        } : d3_scale_niceIdentity;
    }
    var d3_scale_niceIdentity = {
        floor: d3_identity,
        ceil: d3_identity
    };
    function d3_scale_polylinear(domain, range, uninterpolate, interpolate) {
        var u = [], i = [], j = 0, k = Math.min(domain.length, range.length) - 1;
        if (domain[k] < domain[0]) {
            domain = domain.slice().reverse();
            range = range.slice().reverse();
        }
        while (++j <= k) {
            u.push(uninterpolate(domain[j - 1], domain[j]));
            i.push(interpolate(range[j - 1], range[j]));
        }
        return function(x) {
            var j = d3.bisect(domain, x, 1, k) - 1;
            return i[j](u[j](x));
        };
    }
    d3.scale.linear = function() {
        return d3_scale_linear([ 0, 1 ], [ 0, 1 ], d3_interpolate, false);
    };
    function d3_scale_linear(domain, range, interpolate, clamp) {
        var output, input;
        function rescale() {
            var linear = Math.min(domain.length, range.length) > 2 ? d3_scale_polylinear : d3_scale_bilinear, uninterpolate = clamp ? d3_uninterpolateClamp : d3_uninterpolateNumber;
            output = linear(domain, range, uninterpolate, interpolate);
            input = linear(range, domain, uninterpolate, d3_interpolate);
            return scale;
        }
        function scale(x) {
            return output(x);
        }
        scale.invert = function(y) {
            return input(y);
        };
        scale.domain = function(x) {
            if (!arguments.length) return domain;
            domain = x.map(Number);
            return rescale();
        };
        scale.range = function(x) {
            if (!arguments.length) return range;
            range = x;
            return rescale();
        };
        scale.rangeRound = function(x) {
            return scale.range(x).interpolate(d3_interpolateRound);
        };
        scale.clamp = function(x) {
            if (!arguments.length) return clamp;
            clamp = x;
            return rescale();
        };
        scale.interpolate = function(x) {
            if (!arguments.length) return interpolate;
            interpolate = x;
            return rescale();
        };
        scale.ticks = function(m) {
            return d3_scale_linearTicks(domain, m);
        };
        scale.tickFormat = function(m, format) {
            return d3_scale_linearTickFormat(domain, m, format);
        };
        scale.nice = function(m) {
            d3_scale_linearNice(domain, m);
            return rescale();
        };
        scale.copy = function() {
            return d3_scale_linear(domain, range, interpolate, clamp);
        };
        return rescale();
    }
    function d3_scale_linearRebind(scale, linear) {
        return d3.rebind(scale, linear, "range", "rangeRound", "interpolate", "clamp");
    }
    function d3_scale_linearNice(domain, m) {
        return d3_scale_nice(domain, d3_scale_niceStep(d3_scale_linearTickRange(domain, m)[2]));
    }
    function d3_scale_linearTickRange(domain, m) {
        if (m == null) m = 10;
        var extent = d3_scaleExtent(domain), span = extent[1] - extent[0], step = Math.pow(10, Math.floor(Math.log(span / m) / Math.LN10)), err = m / span * step;
        if (err <= .15) step *= 10; else if (err <= .35) step *= 5; else if (err <= .75) step *= 2;
        extent[0] = Math.ceil(extent[0] / step) * step;
        extent[1] = Math.floor(extent[1] / step) * step + step * .5;
        extent[2] = step;
        return extent;
    }
    function d3_scale_linearTicks(domain, m) {
        return d3.range.apply(d3, d3_scale_linearTickRange(domain, m));
    }
    function d3_scale_linearTickFormat(domain, m, format) {
        var range = d3_scale_linearTickRange(domain, m);
        if (format) {
            var match = d3_format_re.exec(format);
            match.shift();
            if (match[8] === "s") {
                var prefix = d3.formatPrefix(Math.max(abs(range[0]), abs(range[1])));
                if (!match[7]) match[7] = "." + d3_scale_linearPrecision(prefix.scale(range[2]));
                match[8] = "f";
                format = d3.format(match.join(""));
                return function(d) {
                    return format(prefix.scale(d)) + prefix.symbol;
                };
            }
            if (!match[7]) match[7] = "." + d3_scale_linearFormatPrecision(match[8], range);
            format = match.join("");
        } else {
            format = ",." + d3_scale_linearPrecision(range[2]) + "f";
        }
        return d3.format(format);
    }
    var d3_scale_linearFormatSignificant = {
        s: 1,
        g: 1,
        p: 1,
        r: 1,
        e: 1
    };
    function d3_scale_linearPrecision(value) {
        return -Math.floor(Math.log(value) / Math.LN10 + .01);
    }
    function d3_scale_linearFormatPrecision(type, range) {
        var p = d3_scale_linearPrecision(range[2]);
        return type in d3_scale_linearFormatSignificant ? Math.abs(p - d3_scale_linearPrecision(Math.max(abs(range[0]), abs(range[1])))) + +(type !== "e") : p - (type === "%") * 2;
    }
    d3.scale.log = function() {
        return d3_scale_log(d3.scale.linear().domain([ 0, 1 ]), 10, true, [ 1, 10 ]);
    };
    function d3_scale_log(linear, base, positive, domain) {
        function log(x) {
            return (positive ? Math.log(x < 0 ? 0 : x) : -Math.log(x > 0 ? 0 : -x)) / Math.log(base);
        }
        function pow(x) {
            return positive ? Math.pow(base, x) : -Math.pow(base, -x);
        }
        function scale(x) {
            return linear(log(x));
        }
        scale.invert = function(x) {
            return pow(linear.invert(x));
        };
        scale.domain = function(x) {
            if (!arguments.length) return domain;
            positive = x[0] >= 0;
            linear.domain((domain = x.map(Number)).map(log));
            return scale;
        };
        scale.base = function(_) {
            if (!arguments.length) return base;
            base = +_;
            linear.domain(domain.map(log));
            return scale;
        };
        scale.nice = function() {
            var niced = d3_scale_nice(domain.map(log), positive ? Math : d3_scale_logNiceNegative);
            linear.domain(niced);
            domain = niced.map(pow);
            return scale;
        };
        scale.ticks = function() {
            var extent = d3_scaleExtent(domain), ticks = [], u = extent[0], v = extent[1], i = Math.floor(log(u)), j = Math.ceil(log(v)), n = base % 1 ? 2 : base;
            if (isFinite(j - i)) {
                if (positive) {
                    for (;i < j; i++) for (var k = 1; k < n; k++) ticks.push(pow(i) * k);
                    ticks.push(pow(i));
                } else {
                    ticks.push(pow(i));
                    for (;i++ < j; ) for (var k = n - 1; k > 0; k--) ticks.push(pow(i) * k);
                }
                for (i = 0; ticks[i] < u; i++) {}
                for (j = ticks.length; ticks[j - 1] > v; j--) {}
                ticks = ticks.slice(i, j);
            }
            return ticks;
        };
        scale.tickFormat = function(n, format) {
            if (!arguments.length) return d3_scale_logFormat;
            if (arguments.length < 2) format = d3_scale_logFormat; else if (typeof format !== "function") format = d3.format(format);
            var k = Math.max(.1, n / scale.ticks().length), f = positive ? (e = 1e-12, 
            Math.ceil) : (e = -1e-12, Math.floor), e;
            return function(d) {
                return d / pow(f(log(d) + e)) <= k ? format(d) : "";
            };
        };
        scale.copy = function() {
            return d3_scale_log(linear.copy(), base, positive, domain);
        };
        return d3_scale_linearRebind(scale, linear);
    }
    var d3_scale_logFormat = d3.format(".0e"), d3_scale_logNiceNegative = {
        floor: function(x) {
            return -Math.ceil(-x);
        },
        ceil: function(x) {
            return -Math.floor(-x);
        }
    };
    d3.scale.pow = function() {
        return d3_scale_pow(d3.scale.linear(), 1, [ 0, 1 ]);
    };
    function d3_scale_pow(linear, exponent, domain) {
        var powp = d3_scale_powPow(exponent), powb = d3_scale_powPow(1 / exponent);
        function scale(x) {
            return linear(powp(x));
        }
        scale.invert = function(x) {
            return powb(linear.invert(x));
        };
        scale.domain = function(x) {
            if (!arguments.length) return domain;
            linear.domain((domain = x.map(Number)).map(powp));
            return scale;
        };
        scale.ticks = function(m) {
            return d3_scale_linearTicks(domain, m);
        };
        scale.tickFormat = function(m, format) {
            return d3_scale_linearTickFormat(domain, m, format);
        };
        scale.nice = function(m) {
            return scale.domain(d3_scale_linearNice(domain, m));
        };
        scale.exponent = function(x) {
            if (!arguments.length) return exponent;
            powp = d3_scale_powPow(exponent = x);
            powb = d3_scale_powPow(1 / exponent);
            linear.domain(domain.map(powp));
            return scale;
        };
        scale.copy = function() {
            return d3_scale_pow(linear.copy(), exponent, domain);
        };
        return d3_scale_linearRebind(scale, linear);
    }
    function d3_scale_powPow(e) {
        return function(x) {
            return x < 0 ? -Math.pow(-x, e) : Math.pow(x, e);
        };
    }
    d3.scale.sqrt = function() {
        return d3.scale.pow().exponent(.5);
    };
    d3.scale.ordinal = function() {
        return d3_scale_ordinal([], {
            t: "range",
            a: [ [] ]
        });
    };
    function d3_scale_ordinal(domain, ranger) {
        var index, range, rangeBand;
        function scale(x) {
            return range[((index.get(x) || (ranger.t === "range" ? index.set(x, domain.push(x)) : NaN)) - 1) % range.length];
        }
        function steps(start, step) {
            return d3.range(domain.length).map(function(i) {
                return start + step * i;
            });
        }
        scale.domain = function(x) {
            if (!arguments.length) return domain;
            domain = [];
            index = new d3_Map();
            var i = -1, n = x.length, xi;
            while (++i < n) if (!index.has(xi = x[i])) index.set(xi, domain.push(xi));
            return scale[ranger.t].apply(scale, ranger.a);
        };
        scale.range = function(x) {
            if (!arguments.length) return range;
            range = x;
            rangeBand = 0;
            ranger = {
                t: "range",
                a: arguments
            };
            return scale;
        };
        scale.rangePoints = function(x, padding) {
            if (arguments.length < 2) padding = 0;
            var start = x[0], stop = x[1], step = domain.length < 2 ? (start = (start + stop) / 2, 
            0) : (stop - start) / (domain.length - 1 + padding);
            range = steps(start + step * padding / 2, step);
            rangeBand = 0;
            ranger = {
                t: "rangePoints",
                a: arguments
            };
            return scale;
        };
        scale.rangeRoundPoints = function(x, padding) {
            if (arguments.length < 2) padding = 0;
            var start = x[0], stop = x[1], step = domain.length < 2 ? (start = stop = Math.round((start + stop) / 2), 
            0) : (stop - start) / (domain.length - 1 + padding) | 0;
            range = steps(start + Math.round(step * padding / 2 + (stop - start - (domain.length - 1 + padding) * step) / 2), step);
            rangeBand = 0;
            ranger = {
                t: "rangeRoundPoints",
                a: arguments
            };
            return scale;
        };
        scale.rangeBands = function(x, padding, outerPadding) {
            if (arguments.length < 2) padding = 0;
            if (arguments.length < 3) outerPadding = padding;
            var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = (stop - start) / (domain.length - padding + 2 * outerPadding);
            range = steps(start + step * outerPadding, step);
            if (reverse) range.reverse();
            rangeBand = step * (1 - padding);
            ranger = {
                t: "rangeBands",
                a: arguments
            };
            return scale;
        };
        scale.rangeRoundBands = function(x, padding, outerPadding) {
            if (arguments.length < 2) padding = 0;
            if (arguments.length < 3) outerPadding = padding;
            var reverse = x[1] < x[0], start = x[reverse - 0], stop = x[1 - reverse], step = Math.floor((stop - start) / (domain.length - padding + 2 * outerPadding));
            range = steps(start + Math.round((stop - start - (domain.length - padding) * step) / 2), step);
            if (reverse) range.reverse();
            rangeBand = Math.round(step * (1 - padding));
            ranger = {
                t: "rangeRoundBands",
                a: arguments
            };
            return scale;
        };
        scale.rangeBand = function() {
            return rangeBand;
        };
        scale.rangeExtent = function() {
            return d3_scaleExtent(ranger.a[0]);
        };
        scale.copy = function() {
            return d3_scale_ordinal(domain, ranger);
        };
        return scale.domain(domain);
    }
    d3.scale.category10 = function() {
        return d3.scale.ordinal().range(d3_category10);
    };
    d3.scale.category20 = function() {
        return d3.scale.ordinal().range(d3_category20);
    };
    d3.scale.category20b = function() {
        return d3.scale.ordinal().range(d3_category20b);
    };
    d3.scale.category20c = function() {
        return d3.scale.ordinal().range(d3_category20c);
    };
    var d3_category10 = [ 2062260, 16744206, 2924588, 14034728, 9725885, 9197131, 14907330, 8355711, 12369186, 1556175 ].map(d3_rgbString);
    var d3_category20 = [ 2062260, 11454440, 16744206, 16759672, 2924588, 10018698, 14034728, 16750742, 9725885, 12955861, 9197131, 12885140, 14907330, 16234194, 8355711, 13092807, 12369186, 14408589, 1556175, 10410725 ].map(d3_rgbString);
    var d3_category20b = [ 3750777, 5395619, 7040719, 10264286, 6519097, 9216594, 11915115, 13556636, 9202993, 12426809, 15186514, 15190932, 8666169, 11356490, 14049643, 15177372, 8077683, 10834324, 13528509, 14589654 ].map(d3_rgbString);
    var d3_category20c = [ 3244733, 7057110, 10406625, 13032431, 15095053, 16616764, 16625259, 16634018, 3253076, 7652470, 10607003, 13101504, 7695281, 10394312, 12369372, 14342891, 6513507, 9868950, 12434877, 14277081 ].map(d3_rgbString);
    d3.scale.quantile = function() {
        return d3_scale_quantile([], []);
    };
    function d3_scale_quantile(domain, range) {
        var thresholds;
        function rescale() {
            var k = 0, q = range.length;
            thresholds = [];
            while (++k < q) thresholds[k - 1] = d3.quantile(domain, k / q);
            return scale;
        }
        function scale(x) {
            if (!isNaN(x = +x)) return range[d3.bisect(thresholds, x)];
        }
        scale.domain = function(x) {
            if (!arguments.length) return domain;
            domain = x.map(d3_number).filter(d3_numeric).sort(d3_ascending);
            return rescale();
        };
        scale.range = function(x) {
            if (!arguments.length) return range;
            range = x;
            return rescale();
        };
        scale.quantiles = function() {
            return thresholds;
        };
        scale.invertExtent = function(y) {
            y = range.indexOf(y);
            return y < 0 ? [ NaN, NaN ] : [ y > 0 ? thresholds[y - 1] : domain[0], y < thresholds.length ? thresholds[y] : domain[domain.length - 1] ];
        };
        scale.copy = function() {
            return d3_scale_quantile(domain, range);
        };
        return rescale();
    }
    d3.scale.quantize = function() {
        return d3_scale_quantize(0, 1, [ 0, 1 ]);
    };
    function d3_scale_quantize(x0, x1, range) {
        var kx, i;
        function scale(x) {
            return range[Math.max(0, Math.min(i, Math.floor(kx * (x - x0))))];
        }
        function rescale() {
            kx = range.length / (x1 - x0);
            i = range.length - 1;
            return scale;
        }
        scale.domain = function(x) {
            if (!arguments.length) return [ x0, x1 ];
            x0 = +x[0];
            x1 = +x[x.length - 1];
            return rescale();
        };
        scale.range = function(x) {
            if (!arguments.length) return range;
            range = x;
            return rescale();
        };
        scale.invertExtent = function(y) {
            y = range.indexOf(y);
            y = y < 0 ? NaN : y / kx + x0;
            return [ y, y + 1 / kx ];
        };
        scale.copy = function() {
            return d3_scale_quantize(x0, x1, range);
        };
        return rescale();
    }
    d3.scale.threshold = function() {
        return d3_scale_threshold([ .5 ], [ 0, 1 ]);
    };
    function d3_scale_threshold(domain, range) {
        function scale(x) {
            if (x <= x) return range[d3.bisect(domain, x)];
        }
        scale.domain = function(_) {
            if (!arguments.length) return domain;
            domain = _;
            return scale;
        };
        scale.range = function(_) {
            if (!arguments.length) return range;
            range = _;
            return scale;
        };
        scale.invertExtent = function(y) {
            y = range.indexOf(y);
            return [ domain[y - 1], domain[y] ];
        };
        scale.copy = function() {
            return d3_scale_threshold(domain, range);
        };
        return scale;
    }
    d3.scale.identity = function() {
        return d3_scale_identity([ 0, 1 ]);
    };
    function d3_scale_identity(domain) {
        function identity(x) {
            return +x;
        }
        identity.invert = identity;
        identity.domain = identity.range = function(x) {
            if (!arguments.length) return domain;
            domain = x.map(identity);
            return identity;
        };
        identity.ticks = function(m) {
            return d3_scale_linearTicks(domain, m);
        };
        identity.tickFormat = function(m, format) {
            return d3_scale_linearTickFormat(domain, m, format);
        };
        identity.copy = function() {
            return d3_scale_identity(domain);
        };
        return identity;
    }
    d3.svg = {};
    function d3_zero() {
        return 0;
    }
    d3.svg.arc = function() {
        var innerRadius = d3_svg_arcInnerRadius, outerRadius = d3_svg_arcOuterRadius, cornerRadius = d3_zero, padRadius = d3_svg_arcAuto, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle, padAngle = d3_svg_arcPadAngle;
        function arc() {
            var r0 = Math.max(0, +innerRadius.apply(this, arguments)), r1 = Math.max(0, +outerRadius.apply(this, arguments)), a0 = startAngle.apply(this, arguments) - halfπ, a1 = endAngle.apply(this, arguments) - halfπ, da = Math.abs(a1 - a0), cw = a0 > a1 ? 0 : 1;
            if (r1 < r0) rc = r1, r1 = r0, r0 = rc;
            if (da >= τε) return circleSegment(r1, cw) + (r0 ? circleSegment(r0, 1 - cw) : "") + "Z";
            var rc, cr, rp, ap, p0 = 0, p1 = 0, x0, y0, x1, y1, x2, y2, x3, y3, path = [];
            if (ap = (+padAngle.apply(this, arguments) || 0) / 2) {
                rp = padRadius === d3_svg_arcAuto ? Math.sqrt(r0 * r0 + r1 * r1) : +padRadius.apply(this, arguments);
                if (!cw) p1 *= -1;
                if (r1) p1 = d3_asin(rp / r1 * Math.sin(ap));
                if (r0) p0 = d3_asin(rp / r0 * Math.sin(ap));
            }
            if (r1) {
                x0 = r1 * Math.cos(a0 + p1);
                y0 = r1 * Math.sin(a0 + p1);
                x1 = r1 * Math.cos(a1 - p1);
                y1 = r1 * Math.sin(a1 - p1);
                var l1 = Math.abs(a1 - a0 - 2 * p1) <= π ? 0 : 1;
                if (p1 && d3_svg_arcSweep(x0, y0, x1, y1) === cw ^ l1) {
                    var h1 = (a0 + a1) / 2;
                    x0 = r1 * Math.cos(h1);
                    y0 = r1 * Math.sin(h1);
                    x1 = y1 = null;
                }
            } else {
                x0 = y0 = 0;
            }
            if (r0) {
                x2 = r0 * Math.cos(a1 - p0);
                y2 = r0 * Math.sin(a1 - p0);
                x3 = r0 * Math.cos(a0 + p0);
                y3 = r0 * Math.sin(a0 + p0);
                var l0 = Math.abs(a0 - a1 + 2 * p0) <= π ? 0 : 1;
                if (p0 && d3_svg_arcSweep(x2, y2, x3, y3) === 1 - cw ^ l0) {
                    var h0 = (a0 + a1) / 2;
                    x2 = r0 * Math.cos(h0);
                    y2 = r0 * Math.sin(h0);
                    x3 = y3 = null;
                }
            } else {
                x2 = y2 = 0;
            }
            if ((rc = Math.min(Math.abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments))) > .001) {
                cr = r0 < r1 ^ cw ? 0 : 1;
                var oc = x3 == null ? [ x2, y2 ] : x1 == null ? [ x0, y0 ] : d3_geom_polygonIntersect([ x0, y0 ], [ x3, y3 ], [ x1, y1 ], [ x2, y2 ]), ax = x0 - oc[0], ay = y0 - oc[1], bx = x1 - oc[0], by = y1 - oc[1], kc = 1 / Math.sin(Math.acos((ax * bx + ay * by) / (Math.sqrt(ax * ax + ay * ay) * Math.sqrt(bx * bx + by * by))) / 2), lc = Math.sqrt(oc[0] * oc[0] + oc[1] * oc[1]);
                if (x1 != null) {
                    var rc1 = Math.min(rc, (r1 - lc) / (kc + 1)), t30 = d3_svg_arcCornerTangents(x3 == null ? [ x2, y2 ] : [ x3, y3 ], [ x0, y0 ], r1, rc1, cw), t12 = d3_svg_arcCornerTangents([ x1, y1 ], [ x2, y2 ], r1, rc1, cw);
                    if (rc === rc1) {
                        path.push("M", t30[0], "A", rc1, ",", rc1, " 0 0,", cr, " ", t30[1], "A", r1, ",", r1, " 0 ", 1 - cw ^ d3_svg_arcSweep(t30[1][0], t30[1][1], t12[1][0], t12[1][1]), ",", cw, " ", t12[1], "A", rc1, ",", rc1, " 0 0,", cr, " ", t12[0]);
                    } else {
                        path.push("M", t30[0], "A", rc1, ",", rc1, " 0 1,", cr, " ", t12[0]);
                    }
                } else {
                    path.push("M", x0, ",", y0);
                }
                if (x3 != null) {
                    var rc0 = Math.min(rc, (r0 - lc) / (kc - 1)), t03 = d3_svg_arcCornerTangents([ x0, y0 ], [ x3, y3 ], r0, -rc0, cw), t21 = d3_svg_arcCornerTangents([ x2, y2 ], x1 == null ? [ x0, y0 ] : [ x1, y1 ], r0, -rc0, cw);
                    if (rc === rc0) {
                        path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t21[1], "A", r0, ",", r0, " 0 ", cw ^ d3_svg_arcSweep(t21[1][0], t21[1][1], t03[1][0], t03[1][1]), ",", 1 - cw, " ", t03[1], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]);
                    } else {
                        path.push("L", t21[0], "A", rc0, ",", rc0, " 0 0,", cr, " ", t03[0]);
                    }
                } else {
                    path.push("L", x2, ",", y2);
                }
            } else {
                path.push("M", x0, ",", y0);
                if (x1 != null) path.push("A", r1, ",", r1, " 0 ", l1, ",", cw, " ", x1, ",", y1);
                path.push("L", x2, ",", y2);
                if (x3 != null) path.push("A", r0, ",", r0, " 0 ", l0, ",", 1 - cw, " ", x3, ",", y3);
            }
            path.push("Z");
            return path.join("");
        }
        function circleSegment(r1, cw) {
            return "M0," + r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + -r1 + "A" + r1 + "," + r1 + " 0 1," + cw + " 0," + r1;
        }
        arc.innerRadius = function(v) {
            if (!arguments.length) return innerRadius;
            innerRadius = d3_functor(v);
            return arc;
        };
        arc.outerRadius = function(v) {
            if (!arguments.length) return outerRadius;
            outerRadius = d3_functor(v);
            return arc;
        };
        arc.cornerRadius = function(v) {
            if (!arguments.length) return cornerRadius;
            cornerRadius = d3_functor(v);
            return arc;
        };
        arc.padRadius = function(v) {
            if (!arguments.length) return padRadius;
            padRadius = v == d3_svg_arcAuto ? d3_svg_arcAuto : d3_functor(v);
            return arc;
        };
        arc.startAngle = function(v) {
            if (!arguments.length) return startAngle;
            startAngle = d3_functor(v);
            return arc;
        };
        arc.endAngle = function(v) {
            if (!arguments.length) return endAngle;
            endAngle = d3_functor(v);
            return arc;
        };
        arc.padAngle = function(v) {
            if (!arguments.length) return padAngle;
            padAngle = d3_functor(v);
            return arc;
        };
        arc.centroid = function() {
            var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2, a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - halfπ;
            return [ Math.cos(a) * r, Math.sin(a) * r ];
        };
        return arc;
    };
    var d3_svg_arcAuto = "auto";
    function d3_svg_arcInnerRadius(d) {
        return d.innerRadius;
    }
    function d3_svg_arcOuterRadius(d) {
        return d.outerRadius;
    }
    function d3_svg_arcStartAngle(d) {
        return d.startAngle;
    }
    function d3_svg_arcEndAngle(d) {
        return d.endAngle;
    }
    function d3_svg_arcPadAngle(d) {
        return d && d.padAngle;
    }
    function d3_svg_arcSweep(x0, y0, x1, y1) {
        return (x0 - x1) * y0 - (y0 - y1) * x0 > 0 ? 0 : 1;
    }
    function d3_svg_arcCornerTangents(p0, p1, r1, rc, cw) {
        var x01 = p0[0] - p1[0], y01 = p0[1] - p1[1], lo = (cw ? rc : -rc) / Math.sqrt(x01 * x01 + y01 * y01), ox = lo * y01, oy = -lo * x01, x1 = p0[0] + ox, y1 = p0[1] + oy, x2 = p1[0] + ox, y2 = p1[1] + oy, x3 = (x1 + x2) / 2, y3 = (y1 + y2) / 2, dx = x2 - x1, dy = y2 - y1, d2 = dx * dx + dy * dy, r = r1 - rc, D = x1 * y2 - x2 * y1, d = (dy < 0 ? -1 : 1) * Math.sqrt(r * r * d2 - D * D), cx0 = (D * dy - dx * d) / d2, cy0 = (-D * dx - dy * d) / d2, cx1 = (D * dy + dx * d) / d2, cy1 = (-D * dx + dy * d) / d2, dx0 = cx0 - x3, dy0 = cy0 - y3, dx1 = cx1 - x3, dy1 = cy1 - y3;
        if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1;
        return [ [ cx0 - ox, cy0 - oy ], [ cx0 * r1 / r, cy0 * r1 / r ] ];
    }
    function d3_svg_line(projection) {
        var x = d3_geom_pointX, y = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, tension = .7;
        function line(data) {
            var segments = [], points = [], i = -1, n = data.length, d, fx = d3_functor(x), fy = d3_functor(y);
            function segment() {
                segments.push("M", interpolate(projection(points), tension));
            }
            while (++i < n) {
                if (defined.call(this, d = data[i], i)) {
                    points.push([ +fx.call(this, d, i), +fy.call(this, d, i) ]);
                } else if (points.length) {
                    segment();
                    points = [];
                }
            }
            if (points.length) segment();
            return segments.length ? segments.join("") : null;
        }
        line.x = function(_) {
            if (!arguments.length) return x;
            x = _;
            return line;
        };
        line.y = function(_) {
            if (!arguments.length) return y;
            y = _;
            return line;
        };
        line.defined = function(_) {
            if (!arguments.length) return defined;
            defined = _;
            return line;
        };
        line.interpolate = function(_) {
            if (!arguments.length) return interpolateKey;
            if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;
            return line;
        };
        line.tension = function(_) {
            if (!arguments.length) return tension;
            tension = _;
            return line;
        };
        return line;
    }
    d3.svg.line = function() {
        return d3_svg_line(d3_identity);
    };
    var d3_svg_lineInterpolators = d3.map({
        linear: d3_svg_lineLinear,
        "linear-closed": d3_svg_lineLinearClosed,
        step: d3_svg_lineStep,
        "step-before": d3_svg_lineStepBefore,
        "step-after": d3_svg_lineStepAfter,
        basis: d3_svg_lineBasis,
        "basis-open": d3_svg_lineBasisOpen,
        "basis-closed": d3_svg_lineBasisClosed,
        bundle: d3_svg_lineBundle,
        cardinal: d3_svg_lineCardinal,
        "cardinal-open": d3_svg_lineCardinalOpen,
        "cardinal-closed": d3_svg_lineCardinalClosed,
        monotone: d3_svg_lineMonotone
    });
    d3_svg_lineInterpolators.forEach(function(key, value) {
        value.key = key;
        value.closed = /-closed$/.test(key);
    });
    function d3_svg_lineLinear(points) {
        return points.join("L");
    }
    function d3_svg_lineLinearClosed(points) {
        return d3_svg_lineLinear(points) + "Z";
    }
    function d3_svg_lineStep(points) {
        var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
        while (++i < n) path.push("H", (p[0] + (p = points[i])[0]) / 2, "V", p[1]);
        if (n > 1) path.push("H", p[0]);
        return path.join("");
    }
    function d3_svg_lineStepBefore(points) {
        var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
        while (++i < n) path.push("V", (p = points[i])[1], "H", p[0]);
        return path.join("");
    }
    function d3_svg_lineStepAfter(points) {
        var i = 0, n = points.length, p = points[0], path = [ p[0], ",", p[1] ];
        while (++i < n) path.push("H", (p = points[i])[0], "V", p[1]);
        return path.join("");
    }
    function d3_svg_lineCardinalOpen(points, tension) {
        return points.length < 4 ? d3_svg_lineLinear(points) : points[1] + d3_svg_lineHermite(points.slice(1, -1), d3_svg_lineCardinalTangents(points, tension));
    }
    function d3_svg_lineCardinalClosed(points, tension) {
        return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite((points.push(points[0]), 
        points), d3_svg_lineCardinalTangents([ points[points.length - 2] ].concat(points, [ points[1] ]), tension));
    }
    function d3_svg_lineCardinal(points, tension) {
        return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineCardinalTangents(points, tension));
    }
    function d3_svg_lineHermite(points, tangents) {
        if (tangents.length < 1 || points.length != tangents.length && points.length != tangents.length + 2) {
            return d3_svg_lineLinear(points);
        }
        var quad = points.length != tangents.length, path = "", p0 = points[0], p = points[1], t0 = tangents[0], t = t0, pi = 1;
        if (quad) {
            path += "Q" + (p[0] - t0[0] * 2 / 3) + "," + (p[1] - t0[1] * 2 / 3) + "," + p[0] + "," + p[1];
            p0 = points[1];
            pi = 2;
        }
        if (tangents.length > 1) {
            t = tangents[1];
            p = points[pi];
            pi++;
            path += "C" + (p0[0] + t0[0]) + "," + (p0[1] + t0[1]) + "," + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1];
            for (var i = 2; i < tangents.length; i++, pi++) {
                p = points[pi];
                t = tangents[i];
                path += "S" + (p[0] - t[0]) + "," + (p[1] - t[1]) + "," + p[0] + "," + p[1];
            }
        }
        if (quad) {
            var lp = points[pi];
            path += "Q" + (p[0] + t[0] * 2 / 3) + "," + (p[1] + t[1] * 2 / 3) + "," + lp[0] + "," + lp[1];
        }
        return path;
    }
    function d3_svg_lineCardinalTangents(points, tension) {
        var tangents = [], a = (1 - tension) / 2, p0, p1 = points[0], p2 = points[1], i = 1, n = points.length;
        while (++i < n) {
            p0 = p1;
            p1 = p2;
            p2 = points[i];
            tangents.push([ a * (p2[0] - p0[0]), a * (p2[1] - p0[1]) ]);
        }
        return tangents;
    }
    function d3_svg_lineBasis(points) {
        if (points.length < 3) return d3_svg_lineLinear(points);
        var i = 1, n = points.length, pi = points[0], x0 = pi[0], y0 = pi[1], px = [ x0, x0, x0, (pi = points[1])[0] ], py = [ y0, y0, y0, pi[1] ], path = [ x0, ",", y0, "L", d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ];
        points.push(points[n - 1]);
        while (++i <= n) {
            pi = points[i];
            px.shift();
            px.push(pi[0]);
            py.shift();
            py.push(pi[1]);
            d3_svg_lineBasisBezier(path, px, py);
        }
        points.pop();
        path.push("L", pi);
        return path.join("");
    }
    function d3_svg_lineBasisOpen(points) {
        if (points.length < 4) return d3_svg_lineLinear(points);
        var path = [], i = -1, n = points.length, pi, px = [ 0 ], py = [ 0 ];
        while (++i < 3) {
            pi = points[i];
            px.push(pi[0]);
            py.push(pi[1]);
        }
        path.push(d3_svg_lineDot4(d3_svg_lineBasisBezier3, px) + "," + d3_svg_lineDot4(d3_svg_lineBasisBezier3, py));
        --i;
        while (++i < n) {
            pi = points[i];
            px.shift();
            px.push(pi[0]);
            py.shift();
            py.push(pi[1]);
            d3_svg_lineBasisBezier(path, px, py);
        }
        return path.join("");
    }
    function d3_svg_lineBasisClosed(points) {
        var path, i = -1, n = points.length, m = n + 4, pi, px = [], py = [];
        while (++i < 4) {
            pi = points[i % n];
            px.push(pi[0]);
            py.push(pi[1]);
        }
        path = [ d3_svg_lineDot4(d3_svg_lineBasisBezier3, px), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, py) ];
        --i;
        while (++i < m) {
            pi = points[i % n];
            px.shift();
            px.push(pi[0]);
            py.shift();
            py.push(pi[1]);
            d3_svg_lineBasisBezier(path, px, py);
        }
        return path.join("");
    }
    function d3_svg_lineBundle(points, tension) {
        var n = points.length - 1;
        if (n) {
            var x0 = points[0][0], y0 = points[0][1], dx = points[n][0] - x0, dy = points[n][1] - y0, i = -1, p, t;
            while (++i <= n) {
                p = points[i];
                t = i / n;
                p[0] = tension * p[0] + (1 - tension) * (x0 + t * dx);
                p[1] = tension * p[1] + (1 - tension) * (y0 + t * dy);
            }
        }
        return d3_svg_lineBasis(points);
    }
    function d3_svg_lineDot4(a, b) {
        return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3];
    }
    var d3_svg_lineBasisBezier1 = [ 0, 2 / 3, 1 / 3, 0 ], d3_svg_lineBasisBezier2 = [ 0, 1 / 3, 2 / 3, 0 ], d3_svg_lineBasisBezier3 = [ 0, 1 / 6, 2 / 3, 1 / 6 ];
    function d3_svg_lineBasisBezier(path, x, y) {
        path.push("C", d3_svg_lineDot4(d3_svg_lineBasisBezier1, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier1, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier2, y), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, x), ",", d3_svg_lineDot4(d3_svg_lineBasisBezier3, y));
    }
    function d3_svg_lineSlope(p0, p1) {
        return (p1[1] - p0[1]) / (p1[0] - p0[0]);
    }
    function d3_svg_lineFiniteDifferences(points) {
        var i = 0, j = points.length - 1, m = [], p0 = points[0], p1 = points[1], d = m[0] = d3_svg_lineSlope(p0, p1);
        while (++i < j) {
            m[i] = (d + (d = d3_svg_lineSlope(p0 = p1, p1 = points[i + 1]))) / 2;
        }
        m[i] = d;
        return m;
    }
    function d3_svg_lineMonotoneTangents(points) {
        var tangents = [], d, a, b, s, m = d3_svg_lineFiniteDifferences(points), i = -1, j = points.length - 1;
        while (++i < j) {
            d = d3_svg_lineSlope(points[i], points[i + 1]);
            if (abs(d) < ε) {
                m[i] = m[i + 1] = 0;
            } else {
                a = m[i] / d;
                b = m[i + 1] / d;
                s = a * a + b * b;
                if (s > 9) {
                    s = d * 3 / Math.sqrt(s);
                    m[i] = s * a;
                    m[i + 1] = s * b;
                }
            }
        }
        i = -1;
        while (++i <= j) {
            s = (points[Math.min(j, i + 1)][0] - points[Math.max(0, i - 1)][0]) / (6 * (1 + m[i] * m[i]));
            tangents.push([ s || 0, m[i] * s || 0 ]);
        }
        return tangents;
    }
    function d3_svg_lineMonotone(points) {
        return points.length < 3 ? d3_svg_lineLinear(points) : points[0] + d3_svg_lineHermite(points, d3_svg_lineMonotoneTangents(points));
    }
    d3.svg.line.radial = function() {
        var line = d3_svg_line(d3_svg_lineRadial);
        line.radius = line.x, delete line.x;
        line.angle = line.y, delete line.y;
        return line;
    };
    function d3_svg_lineRadial(points) {
        var point, i = -1, n = points.length, r, a;
        while (++i < n) {
            point = points[i];
            r = point[0];
            a = point[1] - halfπ;
            point[0] = r * Math.cos(a);
            point[1] = r * Math.sin(a);
        }
        return points;
    }
    function d3_svg_area(projection) {
        var x0 = d3_geom_pointX, x1 = d3_geom_pointX, y0 = 0, y1 = d3_geom_pointY, defined = d3_true, interpolate = d3_svg_lineLinear, interpolateKey = interpolate.key, interpolateReverse = interpolate, L = "L", tension = .7;
        function area(data) {
            var segments = [], points0 = [], points1 = [], i = -1, n = data.length, d, fx0 = d3_functor(x0), fy0 = d3_functor(y0), fx1 = x0 === x1 ? function() {
                return x;
            } : d3_functor(x1), fy1 = y0 === y1 ? function() {
                return y;
            } : d3_functor(y1), x, y;
            function segment() {
                segments.push("M", interpolate(projection(points1), tension), L, interpolateReverse(projection(points0.reverse()), tension), "Z");
            }
            while (++i < n) {
                if (defined.call(this, d = data[i], i)) {
                    points0.push([ x = +fx0.call(this, d, i), y = +fy0.call(this, d, i) ]);
                    points1.push([ +fx1.call(this, d, i), +fy1.call(this, d, i) ]);
                } else if (points0.length) {
                    segment();
                    points0 = [];
                    points1 = [];
                }
            }
            if (points0.length) segment();
            return segments.length ? segments.join("") : null;
        }
        area.x = function(_) {
            if (!arguments.length) return x1;
            x0 = x1 = _;
            return area;
        };
        area.x0 = function(_) {
            if (!arguments.length) return x0;
            x0 = _;
            return area;
        };
        area.x1 = function(_) {
            if (!arguments.length) return x1;
            x1 = _;
            return area;
        };
        area.y = function(_) {
            if (!arguments.length) return y1;
            y0 = y1 = _;
            return area;
        };
        area.y0 = function(_) {
            if (!arguments.length) return y0;
            y0 = _;
            return area;
        };
        area.y1 = function(_) {
            if (!arguments.length) return y1;
            y1 = _;
            return area;
        };
        area.defined = function(_) {
            if (!arguments.length) return defined;
            defined = _;
            return area;
        };
        area.interpolate = function(_) {
            if (!arguments.length) return interpolateKey;
            if (typeof _ === "function") interpolateKey = interpolate = _; else interpolateKey = (interpolate = d3_svg_lineInterpolators.get(_) || d3_svg_lineLinear).key;
            interpolateReverse = interpolate.reverse || interpolate;
            L = interpolate.closed ? "M" : "L";
            return area;
        };
        area.tension = function(_) {
            if (!arguments.length) return tension;
            tension = _;
            return area;
        };
        return area;
    }
    d3_svg_lineStepBefore.reverse = d3_svg_lineStepAfter;
    d3_svg_lineStepAfter.reverse = d3_svg_lineStepBefore;
    d3.svg.area = function() {
        return d3_svg_area(d3_identity);
    };
    d3.svg.area.radial = function() {
        var area = d3_svg_area(d3_svg_lineRadial);
        area.radius = area.x, delete area.x;
        area.innerRadius = area.x0, delete area.x0;
        area.outerRadius = area.x1, delete area.x1;
        area.angle = area.y, delete area.y;
        area.startAngle = area.y0, delete area.y0;
        area.endAngle = area.y1, delete area.y1;
        return area;
    };
    d3.svg.chord = function() {
        var source = d3_source, target = d3_target, radius = d3_svg_chordRadius, startAngle = d3_svg_arcStartAngle, endAngle = d3_svg_arcEndAngle;
        function chord(d, i) {
            var s = subgroup(this, source, d, i), t = subgroup(this, target, d, i);
            return "M" + s.p0 + arc(s.r, s.p1, s.a1 - s.a0) + (equals(s, t) ? curve(s.r, s.p1, s.r, s.p0) : curve(s.r, s.p1, t.r, t.p0) + arc(t.r, t.p1, t.a1 - t.a0) + curve(t.r, t.p1, s.r, s.p0)) + "Z";
        }
        function subgroup(self, f, d, i) {
            var subgroup = f.call(self, d, i), r = radius.call(self, subgroup, i), a0 = startAngle.call(self, subgroup, i) - halfπ, a1 = endAngle.call(self, subgroup, i) - halfπ;
            return {
                r: r,
                a0: a0,
                a1: a1,
                p0: [ r * Math.cos(a0), r * Math.sin(a0) ],
                p1: [ r * Math.cos(a1), r * Math.sin(a1) ]
            };
        }
        function equals(a, b) {
            return a.a0 == b.a0 && a.a1 == b.a1;
        }
        function arc(r, p, a) {
            return "A" + r + "," + r + " 0 " + +(a > π) + ",1 " + p;
        }
        function curve(r0, p0, r1, p1) {
            return "Q 0,0 " + p1;
        }
        chord.radius = function(v) {
            if (!arguments.length) return radius;
            radius = d3_functor(v);
            return chord;
        };
        chord.source = function(v) {
            if (!arguments.length) return source;
            source = d3_functor(v);
            return chord;
        };
        chord.target = function(v) {
            if (!arguments.length) return target;
            target = d3_functor(v);
            return chord;
        };
        chord.startAngle = function(v) {
            if (!arguments.length) return startAngle;
            startAngle = d3_functor(v);
            return chord;
        };
        chord.endAngle = function(v) {
            if (!arguments.length) return endAngle;
            endAngle = d3_functor(v);
            return chord;
        };
        return chord;
    };
    function d3_svg_chordRadius(d) {
        return d.radius;
    }
    d3.svg.diagonal = function() {
        var source = d3_source, target = d3_target, projection = d3_svg_diagonalProjection;
        function diagonal(d, i) {
            var p0 = source.call(this, d, i), p3 = target.call(this, d, i), m = (p0.y + p3.y) / 2, p = [ p0, {
                x: p0.x,
                y: m
            }, {
                x: p3.x,
                y: m
            }, p3 ];
            p = p.map(projection);
            return "M" + p[0] + "C" + p[1] + " " + p[2] + " " + p[3];
        }
        diagonal.source = function(x) {
            if (!arguments.length) return source;
            source = d3_functor(x);
            return diagonal;
        };
        diagonal.target = function(x) {
            if (!arguments.length) return target;
            target = d3_functor(x);
            return diagonal;
        };
        diagonal.projection = function(x) {
            if (!arguments.length) return projection;
            projection = x;
            return diagonal;
        };
        return diagonal;
    };
    function d3_svg_diagonalProjection(d) {
        return [ d.x, d.y ];
    }
    d3.svg.diagonal.radial = function() {
        var diagonal = d3.svg.diagonal(), projection = d3_svg_diagonalProjection, projection_ = diagonal.projection;
        diagonal.projection = function(x) {
            return arguments.length ? projection_(d3_svg_diagonalRadialProjection(projection = x)) : projection;
        };
        return diagonal;
    };
    function d3_svg_diagonalRadialProjection(projection) {
        return function() {
            var d = projection.apply(this, arguments), r = d[0], a = d[1] - halfπ;
            return [ r * Math.cos(a), r * Math.sin(a) ];
        };
    }
    d3.svg.symbol = function() {
        var type = d3_svg_symbolType, size = d3_svg_symbolSize;
        function symbol(d, i) {
            return (d3_svg_symbols.get(type.call(this, d, i)) || d3_svg_symbolCircle)(size.call(this, d, i));
        }
        symbol.type = function(x) {
            if (!arguments.length) return type;
            type = d3_functor(x);
            return symbol;
        };
        symbol.size = function(x) {
            if (!arguments.length) return size;
            size = d3_functor(x);
            return symbol;
        };
        return symbol;
    };
    function d3_svg_symbolSize() {
        return 64;
    }
    function d3_svg_symbolType() {
        return "circle";
    }
    function d3_svg_symbolCircle(size) {
        var r = Math.sqrt(size / π);
        return "M0," + r + "A" + r + "," + r + " 0 1,1 0," + -r + "A" + r + "," + r + " 0 1,1 0," + r + "Z";
    }
    var d3_svg_symbols = d3.map({
        circle: d3_svg_symbolCircle,
        cross: function(size) {
            var r = Math.sqrt(size / 5) / 2;
            return "M" + -3 * r + "," + -r + "H" + -r + "V" + -3 * r + "H" + r + "V" + -r + "H" + 3 * r + "V" + r + "H" + r + "V" + 3 * r + "H" + -r + "V" + r + "H" + -3 * r + "Z";
        },
        diamond: function(size) {
            var ry = Math.sqrt(size / (2 * d3_svg_symbolTan30)), rx = ry * d3_svg_symbolTan30;
            return "M0," + -ry + "L" + rx + ",0" + " 0," + ry + " " + -rx + ",0" + "Z";
        },
        square: function(size) {
            var r = Math.sqrt(size) / 2;
            return "M" + -r + "," + -r + "L" + r + "," + -r + " " + r + "," + r + " " + -r + "," + r + "Z";
        },
        "triangle-down": function(size) {
            var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;
            return "M0," + ry + "L" + rx + "," + -ry + " " + -rx + "," + -ry + "Z";
        },
        "triangle-up": function(size) {
            var rx = Math.sqrt(size / d3_svg_symbolSqrt3), ry = rx * d3_svg_symbolSqrt3 / 2;
            return "M0," + -ry + "L" + rx + "," + ry + " " + -rx + "," + ry + "Z";
        }
    });
    d3.svg.symbolTypes = d3_svg_symbols.keys();
    var d3_svg_symbolSqrt3 = Math.sqrt(3), d3_svg_symbolTan30 = Math.tan(30 * d3_radians);
    d3_selectionPrototype.transition = function(name) {
        var id = d3_transitionInheritId || ++d3_transitionId, ns = d3_transitionNamespace(name), subgroups = [], subgroup, node, transition = d3_transitionInherit || {
            time: Date.now(),
            ease: d3_ease_cubicInOut,
            delay: 0,
            duration: 250
        };
        for (var j = -1, m = this.length; ++j < m; ) {
            subgroups.push(subgroup = []);
            for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
                if (node = group[i]) d3_transitionNode(node, i, ns, id, transition);
                subgroup.push(node);
            }
        }
        return d3_transition(subgroups, ns, id);
    };
    d3_selectionPrototype.interrupt = function(name) {
        return this.each(name == null ? d3_selection_interrupt : d3_selection_interruptNS(d3_transitionNamespace(name)));
    };
    var d3_selection_interrupt = d3_selection_interruptNS(d3_transitionNamespace());
    function d3_selection_interruptNS(ns) {
        return function() {
            var lock, active;
            if ((lock = this[ns]) && (active = lock[lock.active])) {
                if (--lock.count) delete lock[lock.active]; else delete this[ns];
                lock.active += .5;
                active.event && active.event.interrupt.call(this, this.__data__, active.index);
            }
        };
    }
    function d3_transition(groups, ns, id) {
        d3_subclass(groups, d3_transitionPrototype);
        groups.namespace = ns;
        groups.id = id;
        return groups;
    }
    var d3_transitionPrototype = [], d3_transitionId = 0, d3_transitionInheritId, d3_transitionInherit;
    d3_transitionPrototype.call = d3_selectionPrototype.call;
    d3_transitionPrototype.empty = d3_selectionPrototype.empty;
    d3_transitionPrototype.node = d3_selectionPrototype.node;
    d3_transitionPrototype.size = d3_selectionPrototype.size;
    d3.transition = function(selection, name) {
        return selection && selection.transition ? d3_transitionInheritId ? selection.transition(name) : selection : d3.selection().transition(selection);
    };
    d3.transition.prototype = d3_transitionPrototype;
    d3_transitionPrototype.select = function(selector) {
        var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnode, node;
        selector = d3_selection_selector(selector);
        for (var j = -1, m = this.length; ++j < m; ) {
            subgroups.push(subgroup = []);
            for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
                if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i, j))) {
                    if ("__data__" in node) subnode.__data__ = node.__data__;
                    d3_transitionNode(subnode, i, ns, id, node[ns][id]);
                    subgroup.push(subnode);
                } else {
                    subgroup.push(null);
                }
            }
        }
        return d3_transition(subgroups, ns, id);
    };
    d3_transitionPrototype.selectAll = function(selector) {
        var id = this.id, ns = this.namespace, subgroups = [], subgroup, subnodes, node, subnode, transition;
        selector = d3_selection_selectorAll(selector);
        for (var j = -1, m = this.length; ++j < m; ) {
            for (var group = this[j], i = -1, n = group.length; ++i < n; ) {
                if (node = group[i]) {
                    transition = node[ns][id];
                    subnodes = selector.call(node, node.__data__, i, j);
                    subgroups.push(subgroup = []);
                    for (var k = -1, o = subnodes.length; ++k < o; ) {
                        if (subnode = subnodes[k]) d3_transitionNode(subnode, k, ns, id, transition);
                        subgroup.push(subnode);
                    }
                }
            }
        }
        return d3_transition(subgroups, ns, id);
    };
    d3_transitionPrototype.filter = function(filter) {
        var subgroups = [], subgroup, group, node;
        if (typeof filter !== "function") filter = d3_selection_filter(filter);
        for (var j = 0, m = this.length; j < m; j++) {
            subgroups.push(subgroup = []);
            for (var group = this[j], i = 0, n = group.length; i < n; i++) {
                if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {
                    subgroup.push(node);
                }
            }
        }
        return d3_transition(subgroups, this.namespace, this.id);
    };
    d3_transitionPrototype.tween = function(name, tween) {
        var id = this.id, ns = this.namespace;
        if (arguments.length < 2) return this.node()[ns][id].tween.get(name);
        return d3_selection_each(this, tween == null ? function(node) {
            node[ns][id].tween.remove(name);
        } : function(node) {
            node[ns][id].tween.set(name, tween);
        });
    };
    function d3_transition_tween(groups, name, value, tween) {
        var id = groups.id, ns = groups.namespace;
        return d3_selection_each(groups, typeof value === "function" ? function(node, i, j) {
            node[ns][id].tween.set(name, tween(value.call(node, node.__data__, i, j)));
        } : (value = tween(value), function(node) {
            node[ns][id].tween.set(name, value);
        }));
    }
    d3_transitionPrototype.attr = function(nameNS, value) {
        if (arguments.length < 2) {
            for (value in nameNS) this.attr(value, nameNS[value]);
            return this;
        }
        var interpolate = nameNS == "transform" ? d3_interpolateTransform : d3_interpolate, name = d3.ns.qualify(nameNS);
        function attrNull() {
            this.removeAttribute(name);
        }
        function attrNullNS() {
            this.removeAttributeNS(name.space, name.local);
        }
        function attrTween(b) {
            return b == null ? attrNull : (b += "", function() {
                var a = this.getAttribute(name), i;
                return a !== b && (i = interpolate(a, b), function(t) {
                    this.setAttribute(name, i(t));
                });
            });
        }
        function attrTweenNS(b) {
            return b == null ? attrNullNS : (b += "", function() {
                var a = this.getAttributeNS(name.space, name.local), i;
                return a !== b && (i = interpolate(a, b), function(t) {
                    this.setAttributeNS(name.space, name.local, i(t));
                });
            });
        }
        return d3_transition_tween(this, "attr." + nameNS, value, name.local ? attrTweenNS : attrTween);
    };
    d3_transitionPrototype.attrTween = function(nameNS, tween) {
        var name = d3.ns.qualify(nameNS);
        function attrTween(d, i) {
            var f = tween.call(this, d, i, this.getAttribute(name));
            return f && function(t) {
                this.setAttribute(name, f(t));
            };
        }
        function attrTweenNS(d, i) {
            var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local));
            return f && function(t) {
                this.setAttributeNS(name.space, name.local, f(t));
            };
        }
        return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween);
    };
    d3_transitionPrototype.style = function(name, value, priority) {
        var n = arguments.length;
        if (n < 3) {
            if (typeof name !== "string") {
                if (n < 2) value = "";
                for (priority in name) this.style(priority, name[priority], value);
                return this;
            }
            priority = "";
        }
        function styleNull() {
            this.style.removeProperty(name);
        }
        function styleString(b) {
            return b == null ? styleNull : (b += "", function() {
                var a = d3_window(this).getComputedStyle(this, null).getPropertyValue(name), i;
                return a !== b && (i = d3_interpolate(a, b), function(t) {
                    this.style.setProperty(name, i(t), priority);
                });
            });
        }
        return d3_transition_tween(this, "style." + name, value, styleString);
    };
    d3_transitionPrototype.styleTween = function(name, tween, priority) {
        if (arguments.length < 3) priority = "";
        function styleTween(d, i) {
            var f = tween.call(this, d, i, d3_window(this).getComputedStyle(this, null).getPropertyValue(name));
            return f && function(t) {
                this.style.setProperty(name, f(t), priority);
            };
        }
        return this.tween("style." + name, styleTween);
    };
    d3_transitionPrototype.text = function(value) {
        return d3_transition_tween(this, "text", value, d3_transition_text);
    };
    function d3_transition_text(b) {
        if (b == null) b = "";
        return function() {
            this.textContent = b;
        };
    }
    d3_transitionPrototype.remove = function() {
        var ns = this.namespace;
        return this.each("end.transition", function() {
            var p;
            if (this[ns].count < 2 && (p = this.parentNode)) p.removeChild(this);
        });
    };
    d3_transitionPrototype.ease = function(value) {
        var id = this.id, ns = this.namespace;
        if (arguments.length < 1) return this.node()[ns][id].ease;
        if (typeof value !== "function") value = d3.ease.apply(d3, arguments);
        return d3_selection_each(this, function(node) {
            node[ns][id].ease = value;
        });
    };
    d3_transitionPrototype.delay = function(value) {
        var id = this.id, ns = this.namespace;
        if (arguments.length < 1) return this.node()[ns][id].delay;
        return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
            node[ns][id].delay = +value.call(node, node.__data__, i, j);
        } : (value = +value, function(node) {
            node[ns][id].delay = value;
        }));
    };
    d3_transitionPrototype.duration = function(value) {
        var id = this.id, ns = this.namespace;
        if (arguments.length < 1) return this.node()[ns][id].duration;
        return d3_selection_each(this, typeof value === "function" ? function(node, i, j) {
            node[ns][id].duration = Math.max(1, value.call(node, node.__data__, i, j));
        } : (value = Math.max(1, value), function(node) {
            node[ns][id].duration = value;
        }));
    };
    d3_transitionPrototype.each = function(type, listener) {
        var id = this.id, ns = this.namespace;
        if (arguments.length < 2) {
            var inherit = d3_transitionInherit, inheritId = d3_transitionInheritId;
            try {
                d3_transitionInheritId = id;
                d3_selection_each(this, function(node, i, j) {
                    d3_transitionInherit = node[ns][id];
                    type.call(node, node.__data__, i, j);
                });
            } finally {
                d3_transitionInherit = inherit;
                d3_transitionInheritId = inheritId;
            }
        } else {
            d3_selection_each(this, function(node) {
                var transition = node[ns][id];
                (transition.event || (transition.event = d3.dispatch("start", "end", "interrupt"))).on(type, listener);
            });
        }
        return this;
    };
    d3_transitionPrototype.transition = function() {
        var id0 = this.id, id1 = ++d3_transitionId, ns = this.namespace, subgroups = [], subgroup, group, node, transition;
        for (var j = 0, m = this.length; j < m; j++) {
            subgroups.push(subgroup = []);
            for (var group = this[j], i = 0, n = group.length; i < n; i++) {
                if (node = group[i]) {
                    transition = node[ns][id0];
                    d3_transitionNode(node, i, ns, id1, {
                        time: transition.time,
                        ease: transition.ease,
                        delay: transition.delay + transition.duration,
                        duration: transition.duration
                    });
                }
                subgroup.push(node);
            }
        }
        return d3_transition(subgroups, ns, id1);
    };
    function d3_transitionNamespace(name) {
        return name == null ? "__transition__" : "__transition_" + name + "__";
    }
    function d3_transitionNode(node, i, ns, id, inherit) {
        var lock = node[ns] || (node[ns] = {
            active: 0,
            count: 0
        }), transition = lock[id];
        if (!transition) {
            var time = inherit.time;
            transition = lock[id] = {
                tween: new d3_Map(),
                time: time,
                delay: inherit.delay,
                duration: inherit.duration,
                ease: inherit.ease,
                index: i
            };
            inherit = null;
            ++lock.count;
            d3.timer(function(elapsed) {
                var delay = transition.delay, duration, ease, timer = d3_timer_active, tweened = [];
                timer.t = delay + time;
                if (delay <= elapsed) return start(elapsed - delay);
                timer.c = start;
                function start(elapsed) {
                    if (lock.active > id) return stop();
                    var active = lock[lock.active];
                    if (active) {
                        --lock.count;
                        delete lock[lock.active];
                        active.event && active.event.interrupt.call(node, node.__data__, active.index);
                    }
                    lock.active = id;
                    transition.event && transition.event.start.call(node, node.__data__, i);
                    transition.tween.forEach(function(key, value) {
                        if (value = value.call(node, node.__data__, i)) {
                            tweened.push(value);
                        }
                    });
                    ease = transition.ease;
                    duration = transition.duration;
                    d3.timer(function() {
                        timer.c = tick(elapsed || 1) ? d3_true : tick;
                        return 1;
                    }, 0, time);
                }
                function tick(elapsed) {
                    if (lock.active !== id) return 1;
                    var t = elapsed / duration, e = ease(t), n = tweened.length;
                    while (n > 0) {
                        tweened[--n].call(node, e);
                    }
                    if (t >= 1) {
                        transition.event && transition.event.end.call(node, node.__data__, i);
                        return stop();
                    }
                }
                function stop() {
                    if (--lock.count) delete lock[id]; else delete node[ns];
                    return 1;
                }
            }, 0, time);
        }
    }
    d3.svg.axis = function() {
        var scale = d3.scale.linear(), orient = d3_svg_axisDefaultOrient, innerTickSize = 6, outerTickSize = 6, tickPadding = 3, tickArguments_ = [ 10 ], tickValues = null, tickFormat_;
        function axis(g) {
            g.each(function() {
                var g = d3.select(this);
                var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = scale.copy();
                var ticks = tickValues == null ? scale1.ticks ? scale1.ticks.apply(scale1, tickArguments_) : scale1.domain() : tickValues, tickFormat = tickFormat_ == null ? scale1.tickFormat ? scale1.tickFormat.apply(scale1, tickArguments_) : d3_identity : tickFormat_, tick = g.selectAll(".tick").data(ticks, scale1), tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", ε), tickExit = d3.transition(tick.exit()).style("opacity", ε).remove(), tickUpdate = d3.transition(tick.order()).style("opacity", 1), tickSpacing = Math.max(innerTickSize, 0) + tickPadding, tickTransform;
                var range = d3_scaleRange(scale1), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"), 
                d3.transition(path));
                tickEnter.append("line");
                tickEnter.append("text");
                var lineEnter = tickEnter.select("line"), lineUpdate = tickUpdate.select("line"), text = tick.select("text").text(tickFormat), textEnter = tickEnter.select("text"), textUpdate = tickUpdate.select("text"), sign = orient === "top" || orient === "left" ? -1 : 1, x1, x2, y1, y2;
                if (orient === "bottom" || orient === "top") {
                    tickTransform = d3_svg_axisX, x1 = "x", y1 = "y", x2 = "x2", 
                    y2 = "y2";
                    text.attr("dy", sign < 0 ? "0em" : ".71em").style("text-anchor", "middle");
                    pathUpdate.attr("d", "M" + range[0] + "," + sign * outerTickSize + "V0H" + range[1] + "V" + sign * outerTickSize);
                } else {
                    tickTransform = d3_svg_axisY, x1 = "y", y1 = "x", x2 = "y2", 
                    y2 = "x2";
                    text.attr("dy", ".32em").style("text-anchor", sign < 0 ? "end" : "start");
                    pathUpdate.attr("d", "M" + sign * outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + sign * outerTickSize);
                }
                lineEnter.attr(y2, sign * innerTickSize);
                textEnter.attr(y1, sign * tickSpacing);
                lineUpdate.attr(x2, 0).attr(y2, sign * innerTickSize);
                textUpdate.attr(x1, 0).attr(y1, sign * tickSpacing);
                if (scale1.rangeBand) {
                    var x = scale1, dx = x.rangeBand() / 2;
                    scale0 = scale1 = function(d) {
                        return x(d) + dx;
                    };
                } else if (scale0.rangeBand) {
                    scale0 = scale1;
                } else {
                    tickExit.call(tickTransform, scale1, scale0);
                }
                tickEnter.call(tickTransform, scale0, scale1);
                tickUpdate.call(tickTransform, scale1, scale1);
            });
        }
        axis.scale = function(x) {
            if (!arguments.length) return scale;
            scale = x;
            return axis;
        };
        axis.orient = function(x) {
            if (!arguments.length) return orient;
            orient = x in d3_svg_axisOrients ? x + "" : d3_svg_axisDefaultOrient;
            return axis;
        };
        axis.ticks = function() {
            if (!arguments.length) return tickArguments_;
            tickArguments_ = arguments;
            return axis;
        };
        axis.tickValues = function(x) {
            if (!arguments.length) return tickValues;
            tickValues = x;
            return axis;
        };
        axis.tickFormat = function(x) {
            if (!arguments.length) return tickFormat_;
            tickFormat_ = x;
            return axis;
        };
        axis.tickSize = function(x) {
            var n = arguments.length;
            if (!n) return innerTickSize;
            innerTickSize = +x;
            outerTickSize = +arguments[n - 1];
            return axis;
        };
        axis.innerTickSize = function(x) {
            if (!arguments.length) return innerTickSize;
            innerTickSize = +x;
            return axis;
        };
        axis.outerTickSize = function(x) {
            if (!arguments.length) return outerTickSize;
            outerTickSize = +x;
            return axis;
        };
        axis.tickPadding = function(x) {
            if (!arguments.length) return tickPadding;
            tickPadding = +x;
            return axis;
        };
        axis.tickSubdivide = function() {
            return arguments.length && axis;
        };
        return axis;
    };
    var d3_svg_axisDefaultOrient = "bottom", d3_svg_axisOrients = {
        top: 1,
        right: 1,
        bottom: 1,
        left: 1
    };
    function d3_svg_axisX(selection, x0, x1) {
        selection.attr("transform", function(d) {
            var v0 = x0(d);
            return "translate(" + (isFinite(v0) ? v0 : x1(d)) + ",0)";
        });
    }
    function d3_svg_axisY(selection, y0, y1) {
        selection.attr("transform", function(d) {
            var v0 = y0(d);
            return "translate(0," + (isFinite(v0) ? v0 : y1(d)) + ")";
        });
    }
    d3.svg.brush = function() {
        var event = d3_eventDispatch(brush, "brushstart", "brush", "brushend"), x = null, y = null, xExtent = [ 0, 0 ], yExtent = [ 0, 0 ], xExtentDomain, yExtentDomain, xClamp = true, yClamp = true, resizes = d3_svg_brushResizes[0];
        function brush(g) {
            g.each(function() {
                var g = d3.select(this).style("pointer-events", "all").style("-webkit-tap-highlight-color", "rgba(0,0,0,0)").on("mousedown.brush", brushstart).on("touchstart.brush", brushstart);
                var background = g.selectAll(".background").data([ 0 ]);
                background.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("cursor", "crosshair");
                g.selectAll(".extent").data([ 0 ]).enter().append("rect").attr("class", "extent").style("cursor", "move");
                var resize = g.selectAll(".resize").data(resizes, d3_identity);
                resize.exit().remove();
                resize.enter().append("g").attr("class", function(d) {
                    return "resize " + d;
                }).style("cursor", function(d) {
                    return d3_svg_brushCursor[d];
                }).append("rect").attr("x", function(d) {
                    return /[ew]$/.test(d) ? -3 : null;
                }).attr("y", function(d) {
                    return /^[ns]/.test(d) ? -3 : null;
                }).attr("width", 6).attr("height", 6).style("visibility", "hidden");
                resize.style("display", brush.empty() ? "none" : null);
                var gUpdate = d3.transition(g), backgroundUpdate = d3.transition(background), range;
                if (x) {
                    range = d3_scaleRange(x);
                    backgroundUpdate.attr("x", range[0]).attr("width", range[1] - range[0]);
                    redrawX(gUpdate);
                }
                if (y) {
                    range = d3_scaleRange(y);
                    backgroundUpdate.attr("y", range[0]).attr("height", range[1] - range[0]);
                    redrawY(gUpdate);
                }
                redraw(gUpdate);
            });
        }
        brush.event = function(g) {
            g.each(function() {
                var event_ = event.of(this, arguments), extent1 = {
                    x: xExtent,
                    y: yExtent,
                    i: xExtentDomain,
                    j: yExtentDomain
                }, extent0 = this.__chart__ || extent1;
                this.__chart__ = extent1;
                if (d3_transitionInheritId) {
                    d3.select(this).transition().each("start.brush", function() {
                        xExtentDomain = extent0.i;
                        yExtentDomain = extent0.j;
                        xExtent = extent0.x;
                        yExtent = extent0.y;
                        event_({
                            type: "brushstart"
                        });
                    }).tween("brush:brush", function() {
                        var xi = d3_interpolateArray(xExtent, extent1.x), yi = d3_interpolateArray(yExtent, extent1.y);
                        xExtentDomain = yExtentDomain = null;
                        return function(t) {
                            xExtent = extent1.x = xi(t);
                            yExtent = extent1.y = yi(t);
                            event_({
                                type: "brush",
                                mode: "resize"
                            });
                        };
                    }).each("end.brush", function() {
                        xExtentDomain = extent1.i;
                        yExtentDomain = extent1.j;
                        event_({
                            type: "brush",
                            mode: "resize"
                        });
                        event_({
                            type: "brushend"
                        });
                    });
                } else {
                    event_({
                        type: "brushstart"
                    });
                    event_({
                        type: "brush",
                        mode: "resize"
                    });
                    event_({
                        type: "brushend"
                    });
                }
            });
        };
        function redraw(g) {
            g.selectAll(".resize").attr("transform", function(d) {
                return "translate(" + xExtent[+/e$/.test(d)] + "," + yExtent[+/^s/.test(d)] + ")";
            });
        }
        function redrawX(g) {
            g.select(".extent").attr("x", xExtent[0]);
            g.selectAll(".extent,.n>rect,.s>rect").attr("width", xExtent[1] - xExtent[0]);
        }
        function redrawY(g) {
            g.select(".extent").attr("y", yExtent[0]);
            g.selectAll(".extent,.e>rect,.w>rect").attr("height", yExtent[1] - yExtent[0]);
        }
        function brushstart() {
            var target = this, eventTarget = d3.select(d3.event.target), event_ = event.of(target, arguments), g = d3.select(target), resizing = eventTarget.datum(), resizingX = !/^(n|s)$/.test(resizing) && x, resizingY = !/^(e|w)$/.test(resizing) && y, dragging = eventTarget.classed("extent"), dragRestore = d3_event_dragSuppress(target), center, origin = d3.mouse(target), offset;
            var w = d3.select(d3_window(target)).on("keydown.brush", keydown).on("keyup.brush", keyup);
            if (d3.event.changedTouches) {
                w.on("touchmove.brush", brushmove).on("touchend.brush", brushend);
            } else {
                w.on("mousemove.brush", brushmove).on("mouseup.brush", brushend);
            }
            g.interrupt().selectAll("*").interrupt();
            if (dragging) {
                origin[0] = xExtent[0] - origin[0];
                origin[1] = yExtent[0] - origin[1];
            } else if (resizing) {
                var ex = +/w$/.test(resizing), ey = +/^n/.test(resizing);
                offset = [ xExtent[1 - ex] - origin[0], yExtent[1 - ey] - origin[1] ];
                origin[0] = xExtent[ex];
                origin[1] = yExtent[ey];
            } else if (d3.event.altKey) center = origin.slice();
            g.style("pointer-events", "none").selectAll(".resize").style("display", null);
            d3.select("body").style("cursor", eventTarget.style("cursor"));
            event_({
                type: "brushstart"
            });
            brushmove();
            function keydown() {
                if (d3.event.keyCode == 32) {
                    if (!dragging) {
                        center = null;
                        origin[0] -= xExtent[1];
                        origin[1] -= yExtent[1];
                        dragging = 2;
                    }
                    d3_eventPreventDefault();
                }
            }
            function keyup() {
                if (d3.event.keyCode == 32 && dragging == 2) {
                    origin[0] += xExtent[1];
                    origin[1] += yExtent[1];
                    dragging = 0;
                    d3_eventPreventDefault();
                }
            }
            function brushmove() {
                var point = d3.mouse(target), moved = false;
                if (offset) {
                    point[0] += offset[0];
                    point[1] += offset[1];
                }
                if (!dragging) {
                    if (d3.event.altKey) {
                        if (!center) center = [ (xExtent[0] + xExtent[1]) / 2, (yExtent[0] + yExtent[1]) / 2 ];
                        origin[0] = xExtent[+(point[0] < center[0])];
                        origin[1] = yExtent[+(point[1] < center[1])];
                    } else center = null;
                }
                if (resizingX && move1(point, x, 0)) {
                    redrawX(g);
                    moved = true;
                }
                if (resizingY && move1(point, y, 1)) {
                    redrawY(g);
                    moved = true;
                }
                if (moved) {
                    redraw(g);
                    event_({
                        type: "brush",
                        mode: dragging ? "move" : "resize"
                    });
                }
            }
            function move1(point, scale, i) {
                var range = d3_scaleRange(scale), r0 = range[0], r1 = range[1], position = origin[i], extent = i ? yExtent : xExtent, size = extent[1] - extent[0], min, max;
                if (dragging) {
                    r0 -= position;
                    r1 -= size + position;
                }
                min = (i ? yClamp : xClamp) ? Math.max(r0, Math.min(r1, point[i])) : point[i];
                if (dragging) {
                    max = (min += position) + size;
                } else {
                    if (center) position = Math.max(r0, Math.min(r1, 2 * center[i] - min));
                    if (position < min) {
                        max = min;
                        min = position;
                    } else {
                        max = position;
                    }
                }
                if (extent[0] != min || extent[1] != max) {
                    if (i) yExtentDomain = null; else xExtentDomain = null;
                    extent[0] = min;
                    extent[1] = max;
                    return true;
                }
            }
            function brushend() {
                brushmove();
                g.style("pointer-events", "all").selectAll(".resize").style("display", brush.empty() ? "none" : null);
                d3.select("body").style("cursor", null);
                w.on("mousemove.brush", null).on("mouseup.brush", null).on("touchmove.brush", null).on("touchend.brush", null).on("keydown.brush", null).on("keyup.brush", null);
                dragRestore();
                event_({
                    type: "brushend"
                });
            }
        }
        brush.x = function(z) {
            if (!arguments.length) return x;
            x = z;
            resizes = d3_svg_brushResizes[!x << 1 | !y];
            return brush;
        };
        brush.y = function(z) {
            if (!arguments.length) return y;
            y = z;
            resizes = d3_svg_brushResizes[!x << 1 | !y];
            return brush;
        };
        brush.clamp = function(z) {
            if (!arguments.length) return x && y ? [ xClamp, yClamp ] : x ? xClamp : y ? yClamp : null;
            if (x && y) xClamp = !!z[0], yClamp = !!z[1]; else if (x) xClamp = !!z; else if (y) yClamp = !!z;
            return brush;
        };
        brush.extent = function(z) {
            var x0, x1, y0, y1, t;
            if (!arguments.length) {
                if (x) {
                    if (xExtentDomain) {
                        x0 = xExtentDomain[0], x1 = xExtentDomain[1];
                    } else {
                        x0 = xExtent[0], x1 = xExtent[1];
                        if (x.invert) x0 = x.invert(x0), x1 = x.invert(x1);
                        if (x1 < x0) t = x0, x0 = x1, x1 = t;
                    }
                }
                if (y) {
                    if (yExtentDomain) {
                        y0 = yExtentDomain[0], y1 = yExtentDomain[1];
                    } else {
                        y0 = yExtent[0], y1 = yExtent[1];
                        if (y.invert) y0 = y.invert(y0), y1 = y.invert(y1);
                        if (y1 < y0) t = y0, y0 = y1, y1 = t;
                    }
                }
                return x && y ? [ [ x0, y0 ], [ x1, y1 ] ] : x ? [ x0, x1 ] : y && [ y0, y1 ];
            }
            if (x) {
                x0 = z[0], x1 = z[1];
                if (y) x0 = x0[0], x1 = x1[0];
                xExtentDomain = [ x0, x1 ];
                if (x.invert) x0 = x(x0), x1 = x(x1);
                if (x1 < x0) t = x0, x0 = x1, x1 = t;
                if (x0 != xExtent[0] || x1 != xExtent[1]) xExtent = [ x0, x1 ];
            }
            if (y) {
                y0 = z[0], y1 = z[1];
                if (x) y0 = y0[1], y1 = y1[1];
                yExtentDomain = [ y0, y1 ];
                if (y.invert) y0 = y(y0), y1 = y(y1);
                if (y1 < y0) t = y0, y0 = y1, y1 = t;
                if (y0 != yExtent[0] || y1 != yExtent[1]) yExtent = [ y0, y1 ];
            }
            return brush;
        };
        brush.clear = function() {
            if (!brush.empty()) {
                xExtent = [ 0, 0 ], yExtent = [ 0, 0 ];
                xExtentDomain = yExtentDomain = null;
            }
            return brush;
        };
        brush.empty = function() {
            return !!x && xExtent[0] == xExtent[1] || !!y && yExtent[0] == yExtent[1];
        };
        return d3.rebind(brush, event, "on");
    };
    var d3_svg_brushCursor = {
        n: "ns-resize",
        e: "ew-resize",
        s: "ns-resize",
        w: "ew-resize",
        nw: "nwse-resize",
        ne: "nesw-resize",
        se: "nwse-resize",
        sw: "nesw-resize"
    };
    var d3_svg_brushResizes = [ [ "n", "e", "s", "w", "nw", "ne", "se", "sw" ], [ "e", "w" ], [ "n", "s" ], [] ];
    var d3_time_format = d3_time.format = d3_locale_enUS.timeFormat;
    var d3_time_formatUtc = d3_time_format.utc;
    var d3_time_formatIso = d3_time_formatUtc("%Y-%m-%dT%H:%M:%S.%LZ");
    d3_time_format.iso = Date.prototype.toISOString && +new Date("2000-01-01T00:00:00.000Z") ? d3_time_formatIsoNative : d3_time_formatIso;
    function d3_time_formatIsoNative(date) {
        return date.toISOString();
    }
    d3_time_formatIsoNative.parse = function(string) {
        var date = new Date(string);
        return isNaN(date) ? null : date;
    };
    d3_time_formatIsoNative.toString = d3_time_formatIso.toString;
    d3_time.second = d3_time_interval(function(date) {
        return new d3_date(Math.floor(date / 1e3) * 1e3);
    }, function(date, offset) {
        date.setTime(date.getTime() + Math.floor(offset) * 1e3);
    }, function(date) {
        return date.getSeconds();
    });
    d3_time.seconds = d3_time.second.range;
    d3_time.seconds.utc = d3_time.second.utc.range;
    d3_time.minute = d3_time_interval(function(date) {
        return new d3_date(Math.floor(date / 6e4) * 6e4);
    }, function(date, offset) {
        date.setTime(date.getTime() + Math.floor(offset) * 6e4);
    }, function(date) {
        return date.getMinutes();
    });
    d3_time.minutes = d3_time.minute.range;
    d3_time.minutes.utc = d3_time.minute.utc.range;
    d3_time.hour = d3_time_interval(function(date) {
        var timezone = date.getTimezoneOffset() / 60;
        return new d3_date((Math.floor(date / 36e5 - timezone) + timezone) * 36e5);
    }, function(date, offset) {
        date.setTime(date.getTime() + Math.floor(offset) * 36e5);
    }, function(date) {
        return date.getHours();
    });
    d3_time.hours = d3_time.hour.range;
    d3_time.hours.utc = d3_time.hour.utc.range;
    d3_time.month = d3_time_interval(function(date) {
        date = d3_time.day(date);
        date.setDate(1);
        return date;
    }, function(date, offset) {
        date.setMonth(date.getMonth() + offset);
    }, function(date) {
        return date.getMonth();
    });
    d3_time.months = d3_time.month.range;
    d3_time.months.utc = d3_time.month.utc.range;
    function d3_time_scale(linear, methods, format) {
        function scale(x) {
            return linear(x);
        }
        scale.invert = function(x) {
            return d3_time_scaleDate(linear.invert(x));
        };
        scale.domain = function(x) {
            if (!arguments.length) return linear.domain().map(d3_time_scaleDate);
            linear.domain(x);
            return scale;
        };
        function tickMethod(extent, count) {
            var span = extent[1] - extent[0], target = span / count, i = d3.bisect(d3_time_scaleSteps, target);
            return i == d3_time_scaleSteps.length ? [ methods.year, d3_scale_linearTickRange(extent.map(function(d) {
                return d / 31536e6;
            }), count)[2] ] : !i ? [ d3_time_scaleMilliseconds, d3_scale_linearTickRange(extent, count)[2] ] : methods[target / d3_time_scaleSteps[i - 1] < d3_time_scaleSteps[i] / target ? i - 1 : i];
        }
        scale.nice = function(interval, skip) {
            var domain = scale.domain(), extent = d3_scaleExtent(domain), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" && tickMethod(extent, interval);
            if (method) interval = method[0], skip = method[1];
            function skipped(date) {
                return !isNaN(date) && !interval.range(date, d3_time_scaleDate(+date + 1), skip).length;
            }
            return scale.domain(d3_scale_nice(domain, skip > 1 ? {
                floor: function(date) {
                    while (skipped(date = interval.floor(date))) date = d3_time_scaleDate(date - 1);
                    return date;
                },
                ceil: function(date) {
                    while (skipped(date = interval.ceil(date))) date = d3_time_scaleDate(+date + 1);
                    return date;
                }
            } : interval));
        };
        scale.ticks = function(interval, skip) {
            var extent = d3_scaleExtent(scale.domain()), method = interval == null ? tickMethod(extent, 10) : typeof interval === "number" ? tickMethod(extent, interval) : !interval.range && [ {
                range: interval
            }, skip ];
            if (method) interval = method[0], skip = method[1];
            return interval.range(extent[0], d3_time_scaleDate(+extent[1] + 1), skip < 1 ? 1 : skip);
        };
        scale.tickFormat = function() {
            return format;
        };
        scale.copy = function() {
            return d3_time_scale(linear.copy(), methods, format);
        };
        return d3_scale_linearRebind(scale, linear);
    }
    function d3_time_scaleDate(t) {
        return new Date(t);
    }
    var d3_time_scaleSteps = [ 1e3, 5e3, 15e3, 3e4, 6e4, 3e5, 9e5, 18e5, 36e5, 108e5, 216e5, 432e5, 864e5, 1728e5, 6048e5, 2592e6, 7776e6, 31536e6 ];
    var d3_time_scaleLocalMethods = [ [ d3_time.second, 1 ], [ d3_time.second, 5 ], [ d3_time.second, 15 ], [ d3_time.second, 30 ], [ d3_time.minute, 1 ], [ d3_time.minute, 5 ], [ d3_time.minute, 15 ], [ d3_time.minute, 30 ], [ d3_time.hour, 1 ], [ d3_time.hour, 3 ], [ d3_time.hour, 6 ], [ d3_time.hour, 12 ], [ d3_time.day, 1 ], [ d3_time.day, 2 ], [ d3_time.week, 1 ], [ d3_time.month, 1 ], [ d3_time.month, 3 ], [ d3_time.year, 1 ] ];
    var d3_time_scaleLocalFormat = d3_time_format.multi([ [ ".%L", function(d) {
        return d.getMilliseconds();
    } ], [ ":%S", function(d) {
        return d.getSeconds();
    } ], [ "%I:%M", function(d) {
        return d.getMinutes();
    } ], [ "%I %p", function(d) {
        return d.getHours();
    } ], [ "%a %d", function(d) {
        return d.getDay() && d.getDate() != 1;
    } ], [ "%b %d", function(d) {
        return d.getDate() != 1;
    } ], [ "%B", function(d) {
        return d.getMonth();
    } ], [ "%Y", d3_true ] ]);
    var d3_time_scaleMilliseconds = {
        range: function(start, stop, step) {
            return d3.range(Math.ceil(start / step) * step, +stop, step).map(d3_time_scaleDate);
        },
        floor: d3_identity,
        ceil: d3_identity
    };
    d3_time_scaleLocalMethods.year = d3_time.year;
    d3_time.scale = function() {
        return d3_time_scale(d3.scale.linear(), d3_time_scaleLocalMethods, d3_time_scaleLocalFormat);
    };
    var d3_time_scaleUtcMethods = d3_time_scaleLocalMethods.map(function(m) {
        return [ m[0].utc, m[1] ];
    });
    var d3_time_scaleUtcFormat = d3_time_formatUtc.multi([ [ ".%L", function(d) {
        return d.getUTCMilliseconds();
    } ], [ ":%S", function(d) {
        return d.getUTCSeconds();
    } ], [ "%I:%M", function(d) {
        return d.getUTCMinutes();
    } ], [ "%I %p", function(d) {
        return d.getUTCHours();
    } ], [ "%a %d", function(d) {
        return d.getUTCDay() && d.getUTCDate() != 1;
    } ], [ "%b %d", function(d) {
        return d.getUTCDate() != 1;
    } ], [ "%B", function(d) {
        return d.getUTCMonth();
    } ], [ "%Y", d3_true ] ]);
    d3_time_scaleUtcMethods.year = d3_time.year.utc;
    d3_time.scale.utc = function() {
        return d3_time_scale(d3.scale.linear(), d3_time_scaleUtcMethods, d3_time_scaleUtcFormat);
    };
    d3.text = d3_xhrType(function(request) {
        return request.responseText;
    });
    d3.json = function(url, callback) {
        return d3_xhr(url, "application/json", d3_json, callback);
    };
    function d3_json(request) {
        return JSON.parse(request.responseText);
    }
    d3.html = function(url, callback) {
        return d3_xhr(url, "text/html", d3_html, callback);
    };
    function d3_html(request) {
        var range = d3_document.createRange();
        range.selectNode(d3_document.body);
        return range.createContextualFragment(request.responseText);
    }
    d3.xml = d3_xhrType(function(request) {
        return request.responseXML;
    });
    if (typeof define === "function" && define.amd) define(d3); else if (typeof module === "object" && module.exports) module.exports = d3;
    this.d3 = d3;
}();

(function(window) {
    "use strict";
    var c3 = {
        version: "0.4.10"
    };
    var c3_chart_fn, c3_chart_internal_fn, c3_chart_internal_axis_fn;
    function API(owner) {
        this.owner = owner;
    }
    function inherit(base, derived) {
        if (Object.create) {
            derived.prototype = Object.create(base.prototype);
        } else {
            var f = function f() {};
            f.prototype = base.prototype;
            derived.prototype = new f();
        }
        derived.prototype.constructor = derived;
        return derived;
    }
    function Chart(config) {
        var $$ = this.internal = new ChartInternal(this);
        $$.loadConfig(config);
        $$.init();
        (function bindThis(fn, target, argThis) {
            Object.keys(fn).forEach(function(key) {
                target[key] = fn[key].bind(argThis);
                if (Object.keys(fn[key]).length > 0) {
                    bindThis(fn[key], target[key], argThis);
                }
            });
        })(c3_chart_fn, this, this);
    }
    function ChartInternal(api) {
        var $$ = this;
        $$.d3 = window.d3 ? window.d3 : typeof require !== "undefined" ? require("d3") : undefined;
        $$.api = api;
        $$.config = $$.getDefaultConfig();
        $$.data = {};
        $$.cache = {};
        $$.axes = {};
    }
    c3.generate = function(config) {
        return new Chart(config);
    };
    c3.chart = {
        fn: Chart.prototype,
        internal: {
            fn: ChartInternal.prototype,
            axis: {
                fn: Axis.prototype
            }
        }
    };
    c3_chart_fn = c3.chart.fn;
    c3_chart_internal_fn = c3.chart.internal.fn;
    c3_chart_internal_axis_fn = c3.chart.internal.axis.fn;
    c3_chart_internal_fn.init = function() {
        var $$ = this, config = $$.config;
        $$.initParams();
        if (config.data_url) {
            $$.convertUrlToData(config.data_url, config.data_mimeType, config.data_keys, $$.initWithData);
        } else if (config.data_json) {
            $$.initWithData($$.convertJsonToData(config.data_json, config.data_keys));
        } else if (config.data_rows) {
            $$.initWithData($$.convertRowsToData(config.data_rows));
        } else if (config.data_columns) {
            $$.initWithData($$.convertColumnsToData(config.data_columns));
        } else {
            throw Error("url or json or rows or columns is required.");
        }
    };
    c3_chart_internal_fn.initParams = function() {
        var $$ = this, d3 = $$.d3, config = $$.config;
        $$.clipId = "c3-" + +new Date() + "-clip", $$.clipIdForXAxis = $$.clipId + "-xaxis", 
        $$.clipIdForYAxis = $$.clipId + "-yaxis", $$.clipIdForGrid = $$.clipId + "-grid", 
        $$.clipIdForSubchart = $$.clipId + "-subchart", $$.clipPath = $$.getClipPath($$.clipId), 
        $$.clipPathForXAxis = $$.getClipPath($$.clipIdForXAxis), $$.clipPathForYAxis = $$.getClipPath($$.clipIdForYAxis);
        $$.clipPathForGrid = $$.getClipPath($$.clipIdForGrid), $$.clipPathForSubchart = $$.getClipPath($$.clipIdForSubchart), 
        $$.dragStart = null;
        $$.dragging = false;
        $$.flowing = false;
        $$.cancelClick = false;
        $$.mouseover = false;
        $$.transiting = false;
        $$.color = $$.generateColor();
        $$.levelColor = $$.generateLevelColor();
        $$.dataTimeFormat = config.data_xLocaltime ? d3.time.format : d3.time.format.utc;
        $$.axisTimeFormat = config.axis_x_localtime ? d3.time.format : d3.time.format.utc;
        $$.defaultAxisTimeFormat = $$.axisTimeFormat.multi([ [ ".%L", function(d) {
            return d.getMilliseconds();
        } ], [ ":%S", function(d) {
            return d.getSeconds();
        } ], [ "%I:%M", function(d) {
            return d.getMinutes();
        } ], [ "%I %p", function(d) {
            return d.getHours();
        } ], [ "%-m/%-d", function(d) {
            return d.getDay() && d.getDate() !== 1;
        } ], [ "%-m/%-d", function(d) {
            return d.getDate() !== 1;
        } ], [ "%-m/%-d", function(d) {
            return d.getMonth();
        } ], [ "%Y/%-m/%-d", function() {
            return true;
        } ] ]);
        $$.hiddenTargetIds = [];
        $$.hiddenLegendIds = [];
        $$.focusedTargetIds = [];
        $$.defocusedTargetIds = [];
        $$.xOrient = config.axis_rotated ? "left" : "bottom";
        $$.yOrient = config.axis_rotated ? config.axis_y_inner ? "top" : "bottom" : config.axis_y_inner ? "right" : "left";
        $$.y2Orient = config.axis_rotated ? config.axis_y2_inner ? "bottom" : "top" : config.axis_y2_inner ? "left" : "right";
        $$.subXOrient = config.axis_rotated ? "left" : "bottom";
        $$.isLegendRight = config.legend_position === "right";
        $$.isLegendInset = config.legend_position === "inset";
        $$.isLegendTop = config.legend_inset_anchor === "top-left" || config.legend_inset_anchor === "top-right";
        $$.isLegendLeft = config.legend_inset_anchor === "top-left" || config.legend_inset_anchor === "bottom-left";
        $$.legendStep = 0;
        $$.legendItemWidth = 0;
        $$.legendItemHeight = 0;
        $$.currentMaxTickWidths = {
            x: 0,
            y: 0,
            y2: 0
        };
        $$.rotated_padding_left = 30;
        $$.rotated_padding_right = config.axis_rotated && !config.axis_x_show ? 0 : 30;
        $$.rotated_padding_top = 5;
        $$.withoutFadeIn = {};
        $$.intervalForObserveInserted = undefined;
        $$.axes.subx = d3.selectAll([]);
    };
    c3_chart_internal_fn.initChartElements = function() {
        if (this.initBar) {
            this.initBar();
        }
        if (this.initLine) {
            this.initLine();
        }
        if (this.initArc) {
            this.initArc();
        }
        if (this.initGauge) {
            this.initGauge();
        }
        if (this.initText) {
            this.initText();
        }
    };
    c3_chart_internal_fn.initWithData = function(data) {
        var $$ = this, d3 = $$.d3, config = $$.config;
        var defs, main, binding = true;
        $$.axis = new Axis($$);
        if ($$.initPie) {
            $$.initPie();
        }
        if ($$.initBrush) {
            $$.initBrush();
        }
        if ($$.initZoom) {
            $$.initZoom();
        }
        if (!config.bindto) {
            $$.selectChart = d3.selectAll([]);
        } else if (typeof config.bindto.node === "function") {
            $$.selectChart = config.bindto;
        } else {
            $$.selectChart = d3.select(config.bindto);
        }
        if ($$.selectChart.empty()) {
            $$.selectChart = d3.select(document.createElement("div")).style("opacity", 0);
            $$.observeInserted($$.selectChart);
            binding = false;
        }
        $$.selectChart.html("").classed("c3", true);
        $$.data.xs = {};
        $$.data.targets = $$.convertDataToTargets(data);
        if (config.data_filter) {
            $$.data.targets = $$.data.targets.filter(config.data_filter);
        }
        if (config.data_hide) {
            $$.addHiddenTargetIds(config.data_hide === true ? $$.mapToIds($$.data.targets) : config.data_hide);
        }
        if (config.legend_hide) {
            $$.addHiddenLegendIds(config.legend_hide === true ? $$.mapToIds($$.data.targets) : config.legend_hide);
        }
        if ($$.hasType("gauge")) {
            config.legend_show = false;
        }
        $$.updateSizes();
        $$.updateScales();
        $$.x.domain(d3.extent($$.getXDomain($$.data.targets)));
        $$.y.domain($$.getYDomain($$.data.targets, "y"));
        $$.y2.domain($$.getYDomain($$.data.targets, "y2"));
        $$.subX.domain($$.x.domain());
        $$.subY.domain($$.y.domain());
        $$.subY2.domain($$.y2.domain());
        $$.orgXDomain = $$.x.domain();
        if ($$.brush) {
            $$.brush.scale($$.subX);
        }
        if (config.zoom_enabled) {
            $$.zoom.scale($$.x);
        }
        $$.svg = $$.selectChart.append("svg").style("overflow", "hidden").on("mouseenter", function() {
            return config.onmouseover.call($$);
        }).on("mouseleave", function() {
            return config.onmouseout.call($$);
        });
        defs = $$.svg.append("defs");
        $$.clipChart = $$.appendClip(defs, $$.clipId);
        $$.clipXAxis = $$.appendClip(defs, $$.clipIdForXAxis);
        $$.clipYAxis = $$.appendClip(defs, $$.clipIdForYAxis);
        $$.clipGrid = $$.appendClip(defs, $$.clipIdForGrid);
        $$.clipSubchart = $$.appendClip(defs, $$.clipIdForSubchart);
        $$.updateSvgSize();
        main = $$.main = $$.svg.append("g").attr("transform", $$.getTranslate("main"));
        if ($$.initSubchart) {
            $$.initSubchart();
        }
        if ($$.initTooltip) {
            $$.initTooltip();
        }
        if ($$.initLegend) {
            $$.initLegend();
        }
        main.append("text").attr("class", CLASS.text + " " + CLASS.empty).attr("text-anchor", "middle").attr("dominant-baseline", "middle");
        $$.initRegion();
        $$.initGrid();
        main.append("g").attr("clip-path", $$.clipPath).attr("class", CLASS.chart);
        if (config.grid_lines_front) {
            $$.initGridLines();
        }
        $$.initEventRect();
        $$.initChartElements();
        main.insert("rect", config.zoom_privileged ? null : "g." + CLASS.regions).attr("class", CLASS.zoomRect).attr("width", $$.width).attr("height", $$.height).style("opacity", 0).on("dblclick.zoom", null);
        if (config.axis_x_extent) {
            $$.brush.extent($$.getDefaultExtent());
        }
        $$.axis.init();
        $$.updateTargets($$.data.targets);
        if (binding) {
            $$.updateDimension();
            $$.config.oninit.call($$);
            $$.redraw({
                withTransition: false,
                withTransform: true,
                withUpdateXDomain: true,
                withUpdateOrgXDomain: true,
                withTransitionForAxis: false
            });
        }
        if (window.onresize == null) {
            window.onresize = $$.generateResize();
        }
        if (window.onresize.add) {
            window.onresize.add(function() {
                config.onresize.call($$);
            });
            window.onresize.add(function() {
                $$.api.flush();
            });
            window.onresize.add(function() {
                config.onresized.call($$);
            });
        }
        $$.api.element = $$.selectChart.node();
    };
    c3_chart_internal_fn.smoothLines = function(el, type) {
        var $$ = this;
        if (type === "grid") {
            el.each(function() {
                var g = $$.d3.select(this), x1 = g.attr("x1"), x2 = g.attr("x2"), y1 = g.attr("y1"), y2 = g.attr("y2");
                g.attr({
                    x1: Math.ceil(x1),
                    x2: Math.ceil(x2),
                    y1: Math.ceil(y1),
                    y2: Math.ceil(y2)
                });
            });
        }
    };
    c3_chart_internal_fn.updateSizes = function() {
        var $$ = this, config = $$.config;
        var legendHeight = $$.legend ? $$.getLegendHeight() : 0, legendWidth = $$.legend ? $$.getLegendWidth() : 0, legendHeightForBottom = $$.isLegendRight || $$.isLegendInset ? 0 : legendHeight, hasArc = $$.hasArcType(), xAxisHeight = config.axis_rotated || hasArc ? 0 : $$.getHorizontalAxisHeight("x"), subchartHeight = config.subchart_show && !hasArc ? config.subchart_size_height + xAxisHeight : 0;
        $$.currentWidth = $$.getCurrentWidth();
        $$.currentHeight = $$.getCurrentHeight();
        $$.margin = config.axis_rotated ? {
            top: $$.getHorizontalAxisHeight("y2") + $$.getCurrentPaddingTop(),
            right: hasArc ? 0 : $$.getCurrentPaddingRight(),
            bottom: $$.getHorizontalAxisHeight("y") + legendHeightForBottom + $$.getCurrentPaddingBottom(),
            left: subchartHeight + (hasArc ? 0 : $$.getCurrentPaddingLeft())
        } : {
            top: 4 + $$.getCurrentPaddingTop(),
            right: hasArc ? 0 : $$.getCurrentPaddingRight(),
            bottom: xAxisHeight + subchartHeight + legendHeightForBottom + $$.getCurrentPaddingBottom(),
            left: hasArc ? 0 : $$.getCurrentPaddingLeft()
        };
        $$.margin2 = config.axis_rotated ? {
            top: $$.margin.top,
            right: NaN,
            bottom: 20 + legendHeightForBottom,
            left: $$.rotated_padding_left
        } : {
            top: $$.currentHeight - subchartHeight - legendHeightForBottom,
            right: NaN,
            bottom: xAxisHeight + legendHeightForBottom,
            left: $$.margin.left
        };
        $$.margin3 = {
            top: 0,
            right: NaN,
            bottom: 0,
            left: 0
        };
        if ($$.updateSizeForLegend) {
            $$.updateSizeForLegend(legendHeight, legendWidth);
        }
        $$.width = $$.currentWidth - $$.margin.left - $$.margin.right;
        $$.height = $$.currentHeight - $$.margin.top - $$.margin.bottom;
        if ($$.width < 0) {
            $$.width = 0;
        }
        if ($$.height < 0) {
            $$.height = 0;
        }
        $$.width2 = config.axis_rotated ? $$.margin.left - $$.rotated_padding_left - $$.rotated_padding_right : $$.width;
        $$.height2 = config.axis_rotated ? $$.height : $$.currentHeight - $$.margin2.top - $$.margin2.bottom;
        if ($$.width2 < 0) {
            $$.width2 = 0;
        }
        if ($$.height2 < 0) {
            $$.height2 = 0;
        }
        $$.arcWidth = $$.width - ($$.isLegendRight ? legendWidth + 10 : 0);
        $$.arcHeight = $$.height - ($$.isLegendRight ? 0 : 10);
        if ($$.hasType("gauge")) {
            $$.arcHeight += $$.height - $$.getGaugeLabelHeight();
        }
        if ($$.updateRadius) {
            $$.updateRadius();
        }
        if ($$.isLegendRight && hasArc) {
            $$.margin3.left = $$.arcWidth / 2 + $$.radiusExpanded * 1.1;
        }
    };
    c3_chart_internal_fn.updateTargets = function(targets) {
        var $$ = this;
        $$.updateTargetsForText(targets);
        $$.updateTargetsForBar(targets);
        $$.updateTargetsForLine(targets);
        if ($$.hasArcType() && $$.updateTargetsForArc) {
            $$.updateTargetsForArc(targets);
        }
        if ($$.updateTargetsForSubchart) {
            $$.updateTargetsForSubchart(targets);
        }
        $$.showTargets();
    };
    c3_chart_internal_fn.showTargets = function() {
        var $$ = this;
        $$.svg.selectAll("." + CLASS.target).filter(function(d) {
            return $$.isTargetToShow(d.id);
        }).transition().duration($$.config.transition_duration).style("opacity", 1);
    };
    c3_chart_internal_fn.redraw = function(options, transitions) {
        var $$ = this, main = $$.main, d3 = $$.d3, config = $$.config;
        var areaIndices = $$.getShapeIndices($$.isAreaType), barIndices = $$.getShapeIndices($$.isBarType), lineIndices = $$.getShapeIndices($$.isLineType);
        var withY, withSubchart, withTransition, withTransitionForExit, withTransitionForAxis, withTransform, withUpdateXDomain, withUpdateOrgXDomain, withTrimXDomain, withLegend, withEventRect, withDimension, withUpdateXAxis;
        var hideAxis = $$.hasArcType();
        var drawArea, drawBar, drawLine, xForText, yForText;
        var duration, durationForExit, durationForAxis;
        var waitForDraw, flow;
        var targetsToShow = $$.filterTargetsToShow($$.data.targets), tickValues, xDomainForZoom;
        var xv = $$.xv.bind($$), cx, cy;
        options = options || {};
        withY = getOption(options, "withY", true);
        withSubchart = getOption(options, "withSubchart", true);
        withTransition = getOption(options, "withTransition", true);
        withTransform = getOption(options, "withTransform", false);
        withUpdateXDomain = getOption(options, "withUpdateXDomain", false);
        withUpdateOrgXDomain = getOption(options, "withUpdateOrgXDomain", false);
        withTrimXDomain = getOption(options, "withTrimXDomain", true);
        withUpdateXAxis = getOption(options, "withUpdateXAxis", withUpdateXDomain);
        withLegend = getOption(options, "withLegend", false);
        withEventRect = getOption(options, "withEventRect", true);
        withDimension = getOption(options, "withDimension", true);
        withTransitionForExit = getOption(options, "withTransitionForExit", withTransition);
        withTransitionForAxis = getOption(options, "withTransitionForAxis", withTransition);
        duration = withTransition ? config.transition_duration : 0;
        durationForExit = withTransitionForExit ? duration : 0;
        durationForAxis = withTransitionForAxis ? duration : 0;
        transitions = transitions || $$.axis.generateTransitions(durationForAxis);
        if (withLegend && config.legend_show) {
            $$.updateLegend($$.mapToIds($$.data.targets), options, transitions);
        } else if (withDimension) {
            $$.updateDimension(true);
        }
        if ($$.isCategorized() && targetsToShow.length === 0) {
            $$.x.domain([ 0, $$.axes.x.selectAll(".tick").size() ]);
        }
        if (targetsToShow.length) {
            $$.updateXDomain(targetsToShow, withUpdateXDomain, withUpdateOrgXDomain, withTrimXDomain);
            if (!config.axis_x_tick_values) {
                tickValues = $$.axis.updateXAxisTickValues(targetsToShow);
            }
        } else {
            $$.xAxis.tickValues([]);
            $$.subXAxis.tickValues([]);
        }
        if (config.zoom_rescale && !options.flow) {
            xDomainForZoom = $$.x.orgDomain();
        }
        $$.y.domain($$.getYDomain(targetsToShow, "y", xDomainForZoom));
        $$.y2.domain($$.getYDomain(targetsToShow, "y2", xDomainForZoom));
        if (!config.axis_y_tick_values && config.axis_y_tick_count) {
            $$.yAxis.tickValues($$.axis.generateTickValues($$.y.domain(), config.axis_y_tick_count));
        }
        if (!config.axis_y2_tick_values && config.axis_y2_tick_count) {
            $$.y2Axis.tickValues($$.axis.generateTickValues($$.y2.domain(), config.axis_y2_tick_count));
        }
        $$.axis.redraw(transitions, hideAxis);
        $$.axis.updateLabels(withTransition);
        if ((withUpdateXDomain || withUpdateXAxis) && targetsToShow.length) {
            if (config.axis_x_tick_culling && tickValues) {
                $$.svg.selectAll("." + CLASS.axisX).each(function() {
                    var $axis = d3.select(this);
                    var axisWidth = $axis.select("path.domain").node().getTotalLength() - (config.axis_x_tick_outer ? 12 : 0);
                    var ticks = [];
                    $axis.selectAll(".tick text").each(function(idx) {
                        var index = tickValues.indexOf(idx);
                        if (index >= 0) {
                            ticks.push({
                                e: this,
                                index: index
                            });
                        }
                    });
                    ticks.sort(function(a, b) {
                        return a.index - b.index;
                    });
                    if (!config.axis_x_tick_rotate) {
                        ticks.forEach(function(tick) {
                            var width2 = tick.e.getBoundingClientRect().width / 2;
                            var transform = d3.transform(d3.select(tick.e.parentNode).attr("transform"));
                            d3.select(tick.e).style("text-anchor", function() {
                                if (transform.translate[0] < width2) {
                                    return "start";
                                }
                                if (transform.translate[0] + width2 > axisWidth) {
                                    return "end";
                                }
                                return "middle";
                            });
                        });
                    }
                    if (ticks.length > config.axis_x_tick_culling_max) {
                        if (config.axis_x_tick_culling_max > 1) {
                            var ticksMax = config.axis_x_tick_culling_max;
                            var step = Math.floor(ticks.length / ticksMax);
                            while (ticks.length / step >= ticksMax + 1) {
                                ticksMax--;
                                step = Math.floor(ticks.length / ticksMax);
                            }
                            var offset = Math.floor((ticks.length - step * (ticksMax - 1) - 1) / 2);
                            ticks.forEach(function(tick, index) {
                                d3.select(tick.e).style("display", (index + step - offset) % step ? "none" : "block");
                            });
                        } else {
                            var middle = Math.round(ticks.length / 2);
                            ticks.forEach(function(tick, index) {
                                d3.select(tick.e).style("display", index == middle ? "block" : "none");
                            });
                        }
                    } else {
                        ticks.forEach(function(tick) {
                            d3.select(tick.e).style("display", "block");
                        });
                    }
                });
            } else {
                $$.svg.selectAll("." + CLASS.axisX + " .tick text").style("display", "block");
            }
        }
        drawArea = $$.generateDrawArea ? $$.generateDrawArea(areaIndices, false) : undefined;
        drawBar = $$.generateDrawBar ? $$.generateDrawBar(barIndices) : undefined;
        drawLine = $$.generateDrawLine ? $$.generateDrawLine(lineIndices, false) : undefined;
        xForText = $$.generateXYForText(areaIndices, barIndices, lineIndices, true);
        yForText = $$.generateXYForText(areaIndices, barIndices, lineIndices, false);
        if (withY) {
            $$.subY.domain($$.getYDomain(targetsToShow, "y"));
            $$.subY2.domain($$.getYDomain(targetsToShow, "y2"));
        }
        $$.tooltip.style("display", "none");
        $$.updateXgridFocus();
        main.select("text." + CLASS.text + "." + CLASS.empty).attr("x", $$.width / 2).attr("y", $$.height / 2).text(config.data_empty_label_text).transition().style("opacity", targetsToShow.length ? 0 : 1);
        $$.updateGrid(duration);
        $$.updateRegion(duration);
        $$.updateBar(durationForExit);
        $$.updateLine(durationForExit);
        $$.updateArea(durationForExit);
        $$.updateCircle();
        if ($$.hasDataLabel()) {
            $$.updateText(durationForExit);
        }
        if ($$.redrawArc) {
            $$.redrawArc(duration, durationForExit, withTransform);
        }
        if ($$.redrawSubchart) {
            $$.redrawSubchart(withSubchart, transitions, duration, durationForExit, areaIndices, barIndices, lineIndices);
        }
        main.selectAll("." + CLASS.selectedCircles).filter($$.isBarType.bind($$)).selectAll("circle").remove();
        if (config.interaction_enabled && !options.flow && withEventRect) {
            $$.redrawEventRect();
            if ($$.updateZoom) {
                $$.updateZoom();
            }
        }
        $$.updateCircleY();
        cx = ($$.config.axis_rotated ? $$.circleY : $$.circleX).bind($$);
        cy = ($$.config.axis_rotated ? $$.circleX : $$.circleY).bind($$);
        if (options.flow) {
            flow = $$.generateFlow({
                targets: targetsToShow,
                flow: options.flow,
                duration: options.flow.duration,
                drawBar: drawBar,
                drawLine: drawLine,
                drawArea: drawArea,
                cx: cx,
                cy: cy,
                xv: xv,
                xForText: xForText,
                yForText: yForText
            });
        }
        if ((duration || flow) && $$.isTabVisible()) {
            d3.transition().duration(duration).each(function() {
                var transitionsToWait = [];
                [ $$.redrawBar(drawBar, true), $$.redrawLine(drawLine, true), $$.redrawArea(drawArea, true), $$.redrawCircle(cx, cy, true), $$.redrawText(xForText, yForText, options.flow, true), $$.redrawRegion(true), $$.redrawGrid(true) ].forEach(function(transitions) {
                    transitions.forEach(function(transition) {
                        transitionsToWait.push(transition);
                    });
                });
                waitForDraw = $$.generateWait();
                transitionsToWait.forEach(function(t) {
                    waitForDraw.add(t);
                });
            }).call(waitForDraw, function() {
                if (flow) {
                    flow();
                }
                if (config.onrendered) {
                    config.onrendered.call($$);
                }
            });
        } else {
            $$.redrawBar(drawBar);
            $$.redrawLine(drawLine);
            $$.redrawArea(drawArea);
            $$.redrawCircle(cx, cy);
            $$.redrawText(xForText, yForText, options.flow);
            $$.redrawRegion();
            $$.redrawGrid();
            if (config.onrendered) {
                config.onrendered.call($$);
            }
        }
        $$.mapToIds($$.data.targets).forEach(function(id) {
            $$.withoutFadeIn[id] = true;
        });
    };
    c3_chart_internal_fn.updateAndRedraw = function(options) {
        var $$ = this, config = $$.config, transitions;
        options = options || {};
        options.withTransition = getOption(options, "withTransition", true);
        options.withTransform = getOption(options, "withTransform", false);
        options.withLegend = getOption(options, "withLegend", false);
        options.withUpdateXDomain = true;
        options.withUpdateOrgXDomain = true;
        options.withTransitionForExit = false;
        options.withTransitionForTransform = getOption(options, "withTransitionForTransform", options.withTransition);
        $$.updateSizes();
        if (!(options.withLegend && config.legend_show)) {
            transitions = $$.axis.generateTransitions(options.withTransitionForAxis ? config.transition_duration : 0);
            $$.updateScales();
            $$.updateSvgSize();
            $$.transformAll(options.withTransitionForTransform, transitions);
        }
        $$.redraw(options, transitions);
    };
    c3_chart_internal_fn.redrawWithoutRescale = function() {
        this.redraw({
            withY: false,
            withSubchart: false,
            withEventRect: false,
            withTransitionForAxis: false
        });
    };
    c3_chart_internal_fn.isTimeSeries = function() {
        return this.config.axis_x_type === "timeseries";
    };
    c3_chart_internal_fn.isCategorized = function() {
        return this.config.axis_x_type.indexOf("categor") >= 0;
    };
    c3_chart_internal_fn.isCustomX = function() {
        var $$ = this, config = $$.config;
        return !$$.isTimeSeries() && (config.data_x || notEmpty(config.data_xs));
    };
    c3_chart_internal_fn.isTimeSeriesY = function() {
        return this.config.axis_y_type === "timeseries";
    };
    c3_chart_internal_fn.getTranslate = function(target) {
        var $$ = this, config = $$.config, x, y;
        if (target === "main") {
            x = asHalfPixel($$.margin.left);
            y = asHalfPixel($$.margin.top);
        } else if (target === "context") {
            x = asHalfPixel($$.margin2.left);
            y = asHalfPixel($$.margin2.top);
        } else if (target === "legend") {
            x = $$.margin3.left;
            y = $$.margin3.top;
        } else if (target === "x") {
            x = 0;
            y = config.axis_rotated ? 0 : $$.height;
        } else if (target === "y") {
            x = 0;
            y = config.axis_rotated ? $$.height : 0;
        } else if (target === "y2") {
            x = config.axis_rotated ? 0 : $$.width;
            y = config.axis_rotated ? 1 : 0;
        } else if (target === "subx") {
            x = 0;
            y = config.axis_rotated ? 0 : $$.height2;
        } else if (target === "arc") {
            x = $$.arcWidth / 2;
            y = $$.arcHeight / 2;
        }
        return "translate(" + x + "," + y + ")";
    };
    c3_chart_internal_fn.initialOpacity = function(d) {
        return d.value !== null && this.withoutFadeIn[d.id] ? 1 : 0;
    };
    c3_chart_internal_fn.initialOpacityForCircle = function(d) {
        return d.value !== null && this.withoutFadeIn[d.id] ? this.opacityForCircle(d) : 0;
    };
    c3_chart_internal_fn.opacityForCircle = function(d) {
        var opacity = this.config.point_show ? 1 : 0;
        return isValue(d.value) ? this.isScatterType(d) ? .5 : opacity : 0;
    };
    c3_chart_internal_fn.opacityForText = function() {
        return this.hasDataLabel() ? 1 : 0;
    };
    c3_chart_internal_fn.xx = function(d) {
        return d ? this.x(d.x) : null;
    };
    c3_chart_internal_fn.xv = function(d) {
        var $$ = this, value = d.value;
        if ($$.isTimeSeries()) {
            value = $$.parseDate(d.value);
        } else if ($$.isCategorized() && typeof d.value === "string") {
            value = $$.config.axis_x_categories.indexOf(d.value);
        }
        return Math.ceil($$.x(value));
    };
    c3_chart_internal_fn.yv = function(d) {
        var $$ = this, yScale = d.axis && d.axis === "y2" ? $$.y2 : $$.y;
        return Math.ceil(yScale(d.value));
    };
    c3_chart_internal_fn.subxx = function(d) {
        return d ? this.subX(d.x) : null;
    };
    c3_chart_internal_fn.transformMain = function(withTransition, transitions) {
        var $$ = this, xAxis, yAxis, y2Axis;
        if (transitions && transitions.axisX) {
            xAxis = transitions.axisX;
        } else {
            xAxis = $$.main.select("." + CLASS.axisX);
            if (withTransition) {
                xAxis = xAxis.transition();
            }
        }
        if (transitions && transitions.axisY) {
            yAxis = transitions.axisY;
        } else {
            yAxis = $$.main.select("." + CLASS.axisY);
            if (withTransition) {
                yAxis = yAxis.transition();
            }
        }
        if (transitions && transitions.axisY2) {
            y2Axis = transitions.axisY2;
        } else {
            y2Axis = $$.main.select("." + CLASS.axisY2);
            if (withTransition) {
                y2Axis = y2Axis.transition();
            }
        }
        (withTransition ? $$.main.transition() : $$.main).attr("transform", $$.getTranslate("main"));
        xAxis.attr("transform", $$.getTranslate("x"));
        yAxis.attr("transform", $$.getTranslate("y"));
        y2Axis.attr("transform", $$.getTranslate("y2"));
        $$.main.select("." + CLASS.chartArcs).attr("transform", $$.getTranslate("arc"));
    };
    c3_chart_internal_fn.transformAll = function(withTransition, transitions) {
        var $$ = this;
        $$.transformMain(withTransition, transitions);
        if ($$.config.subchart_show) {
            $$.transformContext(withTransition, transitions);
        }
        if ($$.legend) {
            $$.transformLegend(withTransition);
        }
    };
    c3_chart_internal_fn.updateSvgSize = function() {
        var $$ = this, brush = $$.svg.select(".c3-brush .background");
        $$.svg.attr("width", $$.currentWidth).attr("height", $$.currentHeight);
        $$.svg.selectAll([ "#" + $$.clipId, "#" + $$.clipIdForGrid ]).select("rect").attr("width", $$.width).attr("height", $$.height);
        $$.svg.select("#" + $$.clipIdForXAxis).select("rect").attr("x", $$.getXAxisClipX.bind($$)).attr("y", $$.getXAxisClipY.bind($$)).attr("width", $$.getXAxisClipWidth.bind($$)).attr("height", $$.getXAxisClipHeight.bind($$));
        $$.svg.select("#" + $$.clipIdForYAxis).select("rect").attr("x", $$.getYAxisClipX.bind($$)).attr("y", $$.getYAxisClipY.bind($$)).attr("width", $$.getYAxisClipWidth.bind($$)).attr("height", $$.getYAxisClipHeight.bind($$));
        $$.svg.select("#" + $$.clipIdForSubchart).select("rect").attr("width", $$.width).attr("height", brush.size() ? brush.attr("height") : 0);
        $$.svg.select("." + CLASS.zoomRect).attr("width", $$.width).attr("height", $$.height);
        $$.selectChart.style("max-height", $$.currentHeight + "px");
    };
    c3_chart_internal_fn.updateDimension = function(withoutAxis) {
        var $$ = this;
        if (!withoutAxis) {
            if ($$.config.axis_rotated) {
                $$.axes.x.call($$.xAxis);
                $$.axes.subx.call($$.subXAxis);
            } else {
                $$.axes.y.call($$.yAxis);
                $$.axes.y2.call($$.y2Axis);
            }
        }
        $$.updateSizes();
        $$.updateScales();
        $$.updateSvgSize();
        $$.transformAll(false);
    };
    c3_chart_internal_fn.observeInserted = function(selection) {
        var $$ = this, observer;
        if (typeof MutationObserver === "undefined") {
            window.console.error("MutationObserver not defined.");
            return;
        }
        observer = new MutationObserver(function(mutations) {
            mutations.forEach(function(mutation) {
                if (mutation.type === "childList" && mutation.previousSibling) {
                    observer.disconnect();
                    $$.intervalForObserveInserted = window.setInterval(function() {
                        if (selection.node().parentNode) {
                            window.clearInterval($$.intervalForObserveInserted);
                            $$.updateDimension();
                            $$.config.oninit.call($$);
                            $$.redraw({
                                withTransform: true,
                                withUpdateXDomain: true,
                                withUpdateOrgXDomain: true,
                                withTransition: false,
                                withTransitionForTransform: false,
                                withLegend: true
                            });
                            selection.transition().style("opacity", 1);
                        }
                    }, 10);
                }
            });
        });
        observer.observe(selection.node(), {
            attributes: true,
            childList: true,
            characterData: true
        });
    };
    c3_chart_internal_fn.generateResize = function() {
        var resizeFunctions = [];
        function callResizeFunctions() {
            resizeFunctions.forEach(function(f) {
                f();
            });
        }
        callResizeFunctions.add = function(f) {
            resizeFunctions.push(f);
        };
        return callResizeFunctions;
    };
    c3_chart_internal_fn.endall = function(transition, callback) {
        var n = 0;
        transition.each(function() {
            ++n;
        }).each("end", function() {
            if (!--n) {
                callback.apply(this, arguments);
            }
        });
    };
    c3_chart_internal_fn.generateWait = function() {
        var transitionsToWait = [], f = function(transition, callback) {
            var timer = setInterval(function() {
                var done = 0;
                transitionsToWait.forEach(function(t) {
                    if (t.empty()) {
                        done += 1;
                        return;
                    }
                    try {
                        t.transition();
                    } catch (e) {
                        done += 1;
                    }
                });
                if (done === transitionsToWait.length) {
                    clearInterval(timer);
                    if (callback) {
                        callback();
                    }
                }
            }, 10);
        };
        f.add = function(transition) {
            transitionsToWait.push(transition);
        };
        return f;
    };
    c3_chart_internal_fn.parseDate = function(date) {
        var $$ = this, parsedDate;
        if (date instanceof Date) {
            parsedDate = date;
        } else if (typeof date === "string") {
            parsedDate = $$.dataTimeFormat($$.config.data_xFormat).parse(date);
        } else if (typeof date === "number" || !isNaN(date)) {
            parsedDate = new Date(+date);
        }
        if (!parsedDate || isNaN(+parsedDate)) {
            window.console.error("Failed to parse x '" + date + "' to Date object");
        }
        return parsedDate;
    };
    c3_chart_internal_fn.isTabVisible = function() {
        var hidden;
        if (typeof document.hidden !== "undefined") {
            hidden = "hidden";
        } else if (typeof document.mozHidden !== "undefined") {
            hidden = "mozHidden";
        } else if (typeof document.msHidden !== "undefined") {
            hidden = "msHidden";
        } else if (typeof document.webkitHidden !== "undefined") {
            hidden = "webkitHidden";
        }
        return document[hidden] ? false : true;
    };
    c3_chart_internal_fn.getDefaultConfig = function() {
        var config = {
            bindto: "#chart",
            size_width: undefined,
            size_height: undefined,
            padding_left: undefined,
            padding_right: undefined,
            padding_top: undefined,
            padding_bottom: undefined,
            zoom_enabled: false,
            zoom_extent: undefined,
            zoom_privileged: false,
            zoom_rescale: false,
            zoom_onzoom: function() {},
            zoom_onzoomstart: function() {},
            zoom_onzoomend: function() {},
            interaction_enabled: true,
            onmouseover: function() {},
            onmouseout: function() {},
            onresize: function() {},
            onresized: function() {},
            oninit: function() {},
            onrendered: function() {},
            transition_duration: 350,
            data_x: undefined,
            data_xs: {},
            data_xFormat: "%Y-%m-%d",
            data_xLocaltime: true,
            data_xSort: true,
            data_idConverter: function(id) {
                return id;
            },
            data_names: {},
            data_classes: {},
            data_groups: [],
            data_axes: {},
            data_type: undefined,
            data_types: {},
            data_labels: {},
            data_order: "desc",
            data_regions: {},
            data_color: undefined,
            data_colors: {},
            data_hide: false,
            data_filter: undefined,
            data_selection_enabled: false,
            data_selection_grouped: false,
            data_selection_isselectable: function() {
                return true;
            },
            data_selection_multiple: true,
            data_selection_draggable: false,
            data_onclick: function() {},
            data_onmouseover: function() {},
            data_onmouseout: function() {},
            data_onselected: function() {},
            data_onunselected: function() {},
            data_url: undefined,
            data_json: undefined,
            data_rows: undefined,
            data_columns: undefined,
            data_mimeType: undefined,
            data_keys: undefined,
            data_empty_label_text: "",
            subchart_show: false,
            subchart_size_height: 60,
            subchart_onbrush: function() {},
            color_pattern: [],
            color_threshold: {},
            legend_show: true,
            legend_hide: false,
            legend_position: "bottom",
            legend_inset_anchor: "top-left",
            legend_inset_x: 10,
            legend_inset_y: 0,
            legend_inset_step: undefined,
            legend_item_onclick: undefined,
            legend_item_onmouseover: undefined,
            legend_item_onmouseout: undefined,
            legend_equally: false,
            axis_rotated: false,
            axis_x_show: true,
            axis_x_type: "indexed",
            axis_x_localtime: true,
            axis_x_categories: [],
            axis_x_tick_centered: false,
            axis_x_tick_format: undefined,
            axis_x_tick_culling: {},
            axis_x_tick_culling_max: 10,
            axis_x_tick_count: undefined,
            axis_x_tick_fit: true,
            axis_x_tick_values: null,
            axis_x_tick_rotate: 0,
            axis_x_tick_outer: true,
            axis_x_tick_multiline: true,
            axis_x_tick_width: null,
            axis_x_max: undefined,
            axis_x_min: undefined,
            axis_x_padding: {},
            axis_x_height: undefined,
            axis_x_extent: undefined,
            axis_x_label: {},
            axis_y_show: true,
            axis_y_type: undefined,
            axis_y_max: undefined,
            axis_y_min: undefined,
            axis_y_inverted: false,
            axis_y_center: undefined,
            axis_y_inner: undefined,
            axis_y_label: {},
            axis_y_tick_format: undefined,
            axis_y_tick_outer: true,
            axis_y_tick_values: null,
            axis_y_tick_count: undefined,
            axis_y_tick_time_value: undefined,
            axis_y_tick_time_interval: undefined,
            axis_y_padding: {},
            axis_y_default: undefined,
            axis_y2_show: false,
            axis_y2_max: undefined,
            axis_y2_min: undefined,
            axis_y2_inverted: false,
            axis_y2_center: undefined,
            axis_y2_inner: undefined,
            axis_y2_label: {},
            axis_y2_tick_format: undefined,
            axis_y2_tick_outer: true,
            axis_y2_tick_values: null,
            axis_y2_tick_count: undefined,
            axis_y2_padding: {},
            axis_y2_default: undefined,
            grid_x_show: false,
            grid_x_type: "tick",
            grid_x_lines: [],
            grid_y_show: false,
            grid_y_lines: [],
            grid_y_ticks: 10,
            grid_focus_show: true,
            grid_lines_front: true,
            point_show: true,
            point_r: 2.5,
            point_focus_expand_enabled: true,
            point_focus_expand_r: undefined,
            point_select_r: undefined,
            line_connectNull: false,
            line_step_type: "step",
            bar_width: undefined,
            bar_width_ratio: .6,
            bar_width_max: undefined,
            bar_zerobased: true,
            area_zerobased: true,
            pie_label_show: true,
            pie_label_format: undefined,
            pie_label_threshold: .05,
            pie_expand: true,
            gauge_label_show: true,
            gauge_label_format: undefined,
            gauge_expand: true,
            gauge_min: 0,
            gauge_max: 100,
            gauge_units: undefined,
            gauge_width: undefined,
            donut_label_show: true,
            donut_label_format: undefined,
            donut_label_threshold: .05,
            donut_width: undefined,
            donut_expand: true,
            donut_title: "",
            regions: [],
            tooltip_show: true,
            tooltip_grouped: true,
            tooltip_format_title: undefined,
            tooltip_format_name: undefined,
            tooltip_format_value: undefined,
            tooltip_position: undefined,
            tooltip_contents: function(d, defaultTitleFormat, defaultValueFormat, color) {
                return this.getTooltipContent ? this.getTooltipContent(d, defaultTitleFormat, defaultValueFormat, color) : "";
            },
            tooltip_init_show: false,
            tooltip_init_x: 0,
            tooltip_init_position: {
                top: "0px",
                left: "50px"
            }
        };
        Object.keys(this.additionalConfig).forEach(function(key) {
            config[key] = this.additionalConfig[key];
        }, this);
        return config;
    };
    c3_chart_internal_fn.additionalConfig = {};
    c3_chart_internal_fn.loadConfig = function(config) {
        var this_config = this.config, target, keys, read;
        function find() {
            var key = keys.shift();
            if (key && target && typeof target === "object" && key in target) {
                target = target[key];
                return find();
            } else if (!key) {
                return target;
            } else {
                return undefined;
            }
        }
        Object.keys(this_config).forEach(function(key) {
            target = config;
            keys = key.split("_");
            read = find();
            if (isDefined(read)) {
                this_config[key] = read;
            }
        });
    };
    c3_chart_internal_fn.getScale = function(min, max, forTimeseries) {
        return (forTimeseries ? this.d3.time.scale() : this.d3.scale.linear()).range([ min, max ]);
    };
    c3_chart_internal_fn.getX = function(min, max, domain, offset) {
        var $$ = this, scale = $$.getScale(min, max, $$.isTimeSeries()), _scale = domain ? scale.domain(domain) : scale, key;
        if ($$.isCategorized()) {
            offset = offset || function() {
                return 0;
            };
            scale = function(d, raw) {
                var v = _scale(d) + offset(d);
                return raw ? v : Math.ceil(v);
            };
        } else {
            scale = function(d, raw) {
                var v = _scale(d);
                return raw ? v : Math.ceil(v);
            };
        }
        for (key in _scale) {
            scale[key] = _scale[key];
        }
        scale.orgDomain = function() {
            return _scale.domain();
        };
        if ($$.isCategorized()) {
            scale.domain = function(domain) {
                if (!arguments.length) {
                    domain = this.orgDomain();
                    return [ domain[0], domain[1] + 1 ];
                }
                _scale.domain(domain);
                return scale;
            };
        }
        return scale;
    };
    c3_chart_internal_fn.getY = function(min, max, domain) {
        var scale = this.getScale(min, max, this.isTimeSeriesY());
        if (domain) {
            scale.domain(domain);
        }
        return scale;
    };
    c3_chart_internal_fn.getYScale = function(id) {
        return this.axis.getId(id) === "y2" ? this.y2 : this.y;
    };
    c3_chart_internal_fn.getSubYScale = function(id) {
        return this.axis.getId(id) === "y2" ? this.subY2 : this.subY;
    };
    c3_chart_internal_fn.updateScales = function() {
        var $$ = this, config = $$.config, forInit = !$$.x;
        $$.xMin = config.axis_rotated ? 1 : 0;
        $$.xMax = config.axis_rotated ? $$.height : $$.width;
        $$.yMin = config.axis_rotated ? 0 : $$.height;
        $$.yMax = config.axis_rotated ? $$.width : 1;
        $$.subXMin = $$.xMin;
        $$.subXMax = $$.xMax;
        $$.subYMin = config.axis_rotated ? 0 : $$.height2;
        $$.subYMax = config.axis_rotated ? $$.width2 : 1;
        $$.x = $$.getX($$.xMin, $$.xMax, forInit ? undefined : $$.x.orgDomain(), function() {
            return $$.xAxis.tickOffset();
        });
        $$.y = $$.getY($$.yMin, $$.yMax, forInit ? config.axis_y_default : $$.y.domain());
        $$.y2 = $$.getY($$.yMin, $$.yMax, forInit ? config.axis_y2_default : $$.y2.domain());
        $$.subX = $$.getX($$.xMin, $$.xMax, $$.orgXDomain, function(d) {
            return d % 1 ? 0 : $$.subXAxis.tickOffset();
        });
        $$.subY = $$.getY($$.subYMin, $$.subYMax, forInit ? config.axis_y_default : $$.subY.domain());
        $$.subY2 = $$.getY($$.subYMin, $$.subYMax, forInit ? config.axis_y2_default : $$.subY2.domain());
        $$.xAxisTickFormat = $$.axis.getXAxisTickFormat();
        $$.xAxisTickValues = $$.axis.getXAxisTickValues();
        $$.yAxisTickValues = $$.axis.getYAxisTickValues();
        $$.y2AxisTickValues = $$.axis.getY2AxisTickValues();
        $$.xAxis = $$.axis.getXAxis($$.x, $$.xOrient, $$.xAxisTickFormat, $$.xAxisTickValues, config.axis_x_tick_outer);
        $$.subXAxis = $$.axis.getXAxis($$.subX, $$.subXOrient, $$.xAxisTickFormat, $$.xAxisTickValues, config.axis_x_tick_outer);
        $$.yAxis = $$.axis.getYAxis($$.y, $$.yOrient, config.axis_y_tick_format, $$.yAxisTickValues, config.axis_y_tick_outer);
        $$.y2Axis = $$.axis.getYAxis($$.y2, $$.y2Orient, config.axis_y2_tick_format, $$.y2AxisTickValues, config.axis_y2_tick_outer);
        if (!forInit) {
            if ($$.brush) {
                $$.brush.scale($$.subX);
            }
            if (config.zoom_enabled) {
                $$.zoom.scale($$.x);
            }
        }
        if ($$.updateArc) {
            $$.updateArc();
        }
    };
    c3_chart_internal_fn.getYDomainMin = function(targets) {
        var $$ = this, config = $$.config, ids = $$.mapToIds(targets), ys = $$.getValuesAsIdKeyed(targets), j, k, baseId, idsInGroup, id, hasNegativeValue;
        if (config.data_groups.length > 0) {
            hasNegativeValue = $$.hasNegativeValueInTargets(targets);
            for (j = 0; j < config.data_groups.length; j++) {
                idsInGroup = config.data_groups[j].filter(function(id) {
                    return ids.indexOf(id) >= 0;
                });
                if (idsInGroup.length === 0) {
                    continue;
                }
                baseId = idsInGroup[0];
                if (hasNegativeValue && ys[baseId]) {
                    ys[baseId].forEach(function(v, i) {
                        ys[baseId][i] = v < 0 ? v : 0;
                    });
                }
                for (k = 1; k < idsInGroup.length; k++) {
                    id = idsInGroup[k];
                    if (!ys[id]) {
                        continue;
                    }
                    ys[id].forEach(function(v, i) {
                        if ($$.axis.getId(id) === $$.axis.getId(baseId) && ys[baseId] && !(hasNegativeValue && +v > 0)) {
                            ys[baseId][i] += +v;
                        }
                    });
                }
            }
        }
        return $$.d3.min(Object.keys(ys).map(function(key) {
            return $$.d3.min(ys[key]);
        }));
    };
    c3_chart_internal_fn.getYDomainMax = function(targets) {
        var $$ = this, config = $$.config, ids = $$.mapToIds(targets), ys = $$.getValuesAsIdKeyed(targets), j, k, baseId, idsInGroup, id, hasPositiveValue;
        if (config.data_groups.length > 0) {
            hasPositiveValue = $$.hasPositiveValueInTargets(targets);
            for (j = 0; j < config.data_groups.length; j++) {
                idsInGroup = config.data_groups[j].filter(function(id) {
                    return ids.indexOf(id) >= 0;
                });
                if (idsInGroup.length === 0) {
                    continue;
                }
                baseId = idsInGroup[0];
                if (hasPositiveValue && ys[baseId]) {
                    ys[baseId].forEach(function(v, i) {
                        ys[baseId][i] = v > 0 ? v : 0;
                    });
                }
                for (k = 1; k < idsInGroup.length; k++) {
                    id = idsInGroup[k];
                    if (!ys[id]) {
                        continue;
                    }
                    ys[id].forEach(function(v, i) {
                        if ($$.axis.getId(id) === $$.axis.getId(baseId) && ys[baseId] && !(hasPositiveValue && +v < 0)) {
                            ys[baseId][i] += +v;
                        }
                    });
                }
            }
        }
        return $$.d3.max(Object.keys(ys).map(function(key) {
            return $$.d3.max(ys[key]);
        }));
    };
    c3_chart_internal_fn.getYDomain = function(targets, axisId, xDomain) {
        var $$ = this, config = $$.config, targetsByAxisId = targets.filter(function(t) {
            return $$.axis.getId(t.id) === axisId;
        }), yTargets = xDomain ? $$.filterByXDomain(targetsByAxisId, xDomain) : targetsByAxisId, yMin = axisId === "y2" ? config.axis_y2_min : config.axis_y_min, yMax = axisId === "y2" ? config.axis_y2_max : config.axis_y_max, yDomainMin = $$.getYDomainMin(yTargets), yDomainMax = $$.getYDomainMax(yTargets), domain, domainLength, padding, padding_top, padding_bottom, center = axisId === "y2" ? config.axis_y2_center : config.axis_y_center, yDomainAbs, lengths, diff, ratio, isAllPositive, isAllNegative, isZeroBased = $$.hasType("bar", yTargets) && config.bar_zerobased || $$.hasType("area", yTargets) && config.area_zerobased, isInverted = axisId === "y2" ? config.axis_y2_inverted : config.axis_y_inverted, showHorizontalDataLabel = $$.hasDataLabel() && config.axis_rotated, showVerticalDataLabel = $$.hasDataLabel() && !config.axis_rotated;
        yDomainMin = isValue(yMin) ? yMin : isValue(yMax) ? yDomainMin < yMax ? yDomainMin : yMax - 10 : yDomainMin;
        yDomainMax = isValue(yMax) ? yMax : isValue(yMin) ? yMin < yDomainMax ? yDomainMax : yMin + 10 : yDomainMax;
        if (yTargets.length === 0) {
            return axisId === "y2" ? $$.y2.domain() : $$.y.domain();
        }
        if (isNaN(yDomainMin)) {
            yDomainMin = 0;
        }
        if (isNaN(yDomainMax)) {
            yDomainMax = yDomainMin;
        }
        if (yDomainMin === yDomainMax) {
            yDomainMin < 0 ? yDomainMax = 0 : yDomainMin = 0;
        }
        isAllPositive = yDomainMin >= 0 && yDomainMax >= 0;
        isAllNegative = yDomainMin <= 0 && yDomainMax <= 0;
        if (isValue(yMin) && isAllPositive || isValue(yMax) && isAllNegative) {
            isZeroBased = false;
        }
        if (isZeroBased) {
            if (isAllPositive) {
                yDomainMin = 0;
            }
            if (isAllNegative) {
                yDomainMax = 0;
            }
        }
        domainLength = Math.abs(yDomainMax - yDomainMin);
        padding = padding_top = padding_bottom = domainLength * .1;
        if (typeof center !== "undefined") {
            yDomainAbs = Math.max(Math.abs(yDomainMin), Math.abs(yDomainMax));
            yDomainMax = center + yDomainAbs;
            yDomainMin = center - yDomainAbs;
        }
        if (showHorizontalDataLabel) {
            lengths = $$.getDataLabelLength(yDomainMin, yDomainMax, "width");
            diff = diffDomain($$.y.range());
            ratio = [ lengths[0] / diff, lengths[1] / diff ];
            padding_top += domainLength * (ratio[1] / (1 - ratio[0] - ratio[1]));
            padding_bottom += domainLength * (ratio[0] / (1 - ratio[0] - ratio[1]));
        } else if (showVerticalDataLabel) {
            lengths = $$.getDataLabelLength(yDomainMin, yDomainMax, "height");
            padding_top += $$.axis.convertPixelsToAxisPadding(lengths[1], domainLength);
            padding_bottom += $$.axis.convertPixelsToAxisPadding(lengths[0], domainLength);
        }
        if (axisId === "y" && notEmpty(config.axis_y_padding)) {
            padding_top = $$.axis.getPadding(config.axis_y_padding, "top", padding_top, domainLength);
            padding_bottom = $$.axis.getPadding(config.axis_y_padding, "bottom", padding_bottom, domainLength);
        }
        if (axisId === "y2" && notEmpty(config.axis_y2_padding)) {
            padding_top = $$.axis.getPadding(config.axis_y2_padding, "top", padding_top, domainLength);
            padding_bottom = $$.axis.getPadding(config.axis_y2_padding, "bottom", padding_bottom, domainLength);
        }
        if (isZeroBased) {
            if (isAllPositive) {
                padding_bottom = yDomainMin;
            }
            if (isAllNegative) {
                padding_top = -yDomainMax;
            }
        }
        domain = $$.config.axis_rotated ? [ yDomainMin, yDomainMax ] : [ yDomainMin - padding_bottom, yDomainMax + padding_top ];
        return isInverted ? domain.reverse() : domain;
    };
    c3_chart_internal_fn.getXDomainMin = function(targets) {
        var $$ = this, config = $$.config;
        return isDefined(config.axis_x_min) ? $$.isTimeSeries() ? this.parseDate(config.axis_x_min) : config.axis_x_min : $$.d3.min(targets, function(t) {
            return $$.d3.min(t.values, function(v) {
                return v.x;
            });
        });
    };
    c3_chart_internal_fn.getXDomainMax = function(targets) {
        var $$ = this, config = $$.config;
        return isDefined(config.axis_x_max) ? $$.isTimeSeries() ? this.parseDate(config.axis_x_max) : config.axis_x_max : $$.d3.max(targets, function(t) {
            return $$.d3.max(t.values, function(v) {
                return v.x;
            });
        });
    };
    c3_chart_internal_fn.getXDomainPadding = function(domain) {
        var $$ = this, config = $$.config, diff = domain[1] - domain[0], maxDataCount, padding, paddingLeft, paddingRight;
        if ($$.isCategorized()) {
            padding = 0;
        } else if ($$.hasType("bar")) {
            maxDataCount = $$.getMaxDataCount();
            padding = maxDataCount > 1 ? diff / (maxDataCount - 1) / 2 : .5;
        } else {
            padding = diff * .01;
        }
        if (typeof config.axis_x_padding === "object" && notEmpty(config.axis_x_padding)) {
            paddingLeft = isValue(config.axis_x_padding.left) ? config.axis_x_padding.left : padding;
            paddingRight = isValue(config.axis_x_padding.right) ? config.axis_x_padding.right : padding;
        } else if (typeof config.axis_x_padding === "number") {
            paddingLeft = paddingRight = config.axis_x_padding;
        } else {
            paddingLeft = paddingRight = padding;
        }
        return {
            left: paddingLeft,
            right: paddingRight
        };
    };
    c3_chart_internal_fn.getXDomain = function(targets) {
        var $$ = this, xDomain = [ $$.getXDomainMin(targets), $$.getXDomainMax(targets) ], firstX = xDomain[0], lastX = xDomain[1], padding = $$.getXDomainPadding(xDomain), min = 0, max = 0;
        if (firstX - lastX === 0 && !$$.isCategorized()) {
            if ($$.isTimeSeries()) {
                firstX = new Date(firstX.getTime() * .5);
                lastX = new Date(lastX.getTime() * 1.5);
            } else {
                firstX = firstX === 0 ? 1 : firstX * .5;
                lastX = lastX === 0 ? -1 : lastX * 1.5;
            }
        }
        if (firstX || firstX === 0) {
            min = $$.isTimeSeries() ? new Date(firstX.getTime() - padding.left) : firstX - padding.left;
        }
        if (lastX || lastX === 0) {
            max = $$.isTimeSeries() ? new Date(lastX.getTime() + padding.right) : lastX + padding.right;
        }
        return [ min, max ];
    };
    c3_chart_internal_fn.updateXDomain = function(targets, withUpdateXDomain, withUpdateOrgXDomain, withTrim, domain) {
        var $$ = this, config = $$.config;
        if (withUpdateOrgXDomain) {
            $$.x.domain(domain ? domain : $$.d3.extent($$.getXDomain(targets)));
            $$.orgXDomain = $$.x.domain();
            if (config.zoom_enabled) {
                $$.zoom.scale($$.x).updateScaleExtent();
            }
            $$.subX.domain($$.x.domain());
            if ($$.brush) {
                $$.brush.scale($$.subX);
            }
        }
        if (withUpdateXDomain) {
            $$.x.domain(domain ? domain : !$$.brush || $$.brush.empty() ? $$.orgXDomain : $$.brush.extent());
            if (config.zoom_enabled) {
                $$.zoom.scale($$.x).updateScaleExtent();
            }
        }
        if (withTrim) {
            $$.x.domain($$.trimXDomain($$.x.orgDomain()));
        }
        return $$.x.domain();
    };
    c3_chart_internal_fn.trimXDomain = function(domain) {
        var $$ = this;
        if (domain[0] <= $$.orgXDomain[0]) {
            domain[1] = +domain[1] + ($$.orgXDomain[0] - domain[0]);
            domain[0] = $$.orgXDomain[0];
        }
        if ($$.orgXDomain[1] <= domain[1]) {
            domain[0] = +domain[0] - (domain[1] - $$.orgXDomain[1]);
            domain[1] = $$.orgXDomain[1];
        }
        return domain;
    };
    c3_chart_internal_fn.isX = function(key) {
        var $$ = this, config = $$.config;
        return config.data_x && key === config.data_x || notEmpty(config.data_xs) && hasValue(config.data_xs, key);
    };
    c3_chart_internal_fn.isNotX = function(key) {
        return !this.isX(key);
    };
    c3_chart_internal_fn.getXKey = function(id) {
        var $$ = this, config = $$.config;
        return config.data_x ? config.data_x : notEmpty(config.data_xs) ? config.data_xs[id] : null;
    };
    c3_chart_internal_fn.getXValuesOfXKey = function(key, targets) {
        var $$ = this, xValues, ids = targets && notEmpty(targets) ? $$.mapToIds(targets) : [];
        ids.forEach(function(id) {
            if ($$.getXKey(id) === key) {
                xValues = $$.data.xs[id];
            }
        });
        return xValues;
    };
    c3_chart_internal_fn.getIndexByX = function(x) {
        var $$ = this, data = $$.filterByX($$.data.targets, x);
        return data.length ? data[0].index : null;
    };
    c3_chart_internal_fn.getXValue = function(id, i) {
        var $$ = this;
        return id in $$.data.xs && $$.data.xs[id] && isValue($$.data.xs[id][i]) ? $$.data.xs[id][i] : i;
    };
    c3_chart_internal_fn.getOtherTargetXs = function() {
        var $$ = this, idsForX = Object.keys($$.data.xs);
        return idsForX.length ? $$.data.xs[idsForX[0]] : null;
    };
    c3_chart_internal_fn.getOtherTargetX = function(index) {
        var xs = this.getOtherTargetXs();
        return xs && index < xs.length ? xs[index] : null;
    };
    c3_chart_internal_fn.addXs = function(xs) {
        var $$ = this;
        Object.keys(xs).forEach(function(id) {
            $$.config.data_xs[id] = xs[id];
        });
    };
    c3_chart_internal_fn.hasMultipleX = function(xs) {
        return this.d3.set(Object.keys(xs).map(function(id) {
            return xs[id];
        })).size() > 1;
    };
    c3_chart_internal_fn.isMultipleX = function() {
        return notEmpty(this.config.data_xs) || !this.config.data_xSort || this.hasType("scatter");
    };
    c3_chart_internal_fn.addName = function(data) {
        var $$ = this, name;
        if (data) {
            name = $$.config.data_names[data.id];
            data.name = name ? name : data.id;
        }
        return data;
    };
    c3_chart_internal_fn.getValueOnIndex = function(values, index) {
        var valueOnIndex = values.filter(function(v) {
            return v.index === index;
        });
        return valueOnIndex.length ? valueOnIndex[0] : null;
    };
    c3_chart_internal_fn.updateTargetX = function(targets, x) {
        var $$ = this;
        targets.forEach(function(t) {
            t.values.forEach(function(v, i) {
                v.x = $$.generateTargetX(x[i], t.id, i);
            });
            $$.data.xs[t.id] = x;
        });
    };
    c3_chart_internal_fn.updateTargetXs = function(targets, xs) {
        var $$ = this;
        targets.forEach(function(t) {
            if (xs[t.id]) {
                $$.updateTargetX([ t ], xs[t.id]);
            }
        });
    };
    c3_chart_internal_fn.generateTargetX = function(rawX, id, index) {
        var $$ = this, x;
        if ($$.isTimeSeries()) {
            x = rawX ? $$.parseDate(rawX) : $$.parseDate($$.getXValue(id, index));
        } else if ($$.isCustomX() && !$$.isCategorized()) {
            x = isValue(rawX) ? +rawX : $$.getXValue(id, index);
        } else {
            x = index;
        }
        return x;
    };
    c3_chart_internal_fn.cloneTarget = function(target) {
        return {
            id: target.id,
            id_org: target.id_org,
            values: target.values.map(function(d) {
                return {
                    x: d.x,
                    value: d.value,
                    id: d.id
                };
            })
        };
    };
    c3_chart_internal_fn.updateXs = function() {
        var $$ = this;
        if ($$.data.targets.length) {
            $$.xs = [];
            $$.data.targets[0].values.forEach(function(v) {
                $$.xs[v.index] = v.x;
            });
        }
    };
    c3_chart_internal_fn.getPrevX = function(i) {
        var x = this.xs[i - 1];
        return typeof x !== "undefined" ? x : null;
    };
    c3_chart_internal_fn.getNextX = function(i) {
        var x = this.xs[i + 1];
        return typeof x !== "undefined" ? x : null;
    };
    c3_chart_internal_fn.getMaxDataCount = function() {
        var $$ = this;
        return $$.d3.max($$.data.targets, function(t) {
            return t.values.length;
        });
    };
    c3_chart_internal_fn.getMaxDataCountTarget = function(targets) {
        var length = targets.length, max = 0, maxTarget;
        if (length > 1) {
            targets.forEach(function(t) {
                if (t.values.length > max) {
                    maxTarget = t;
                    max = t.values.length;
                }
            });
        } else {
            maxTarget = length ? targets[0] : null;
        }
        return maxTarget;
    };
    c3_chart_internal_fn.getEdgeX = function(targets) {
        var $$ = this;
        return !targets.length ? [ 0, 0 ] : [ $$.d3.min(targets, function(t) {
            return t.values[0].x;
        }), $$.d3.max(targets, function(t) {
            return t.values[t.values.length - 1].x;
        }) ];
    };
    c3_chart_internal_fn.mapToIds = function(targets) {
        return targets.map(function(d) {
            return d.id;
        });
    };
    c3_chart_internal_fn.mapToTargetIds = function(ids) {
        var $$ = this;
        return ids ? isString(ids) ? [ ids ] : ids : $$.mapToIds($$.data.targets);
    };
    c3_chart_internal_fn.hasTarget = function(targets, id) {
        var ids = this.mapToIds(targets), i;
        for (i = 0; i < ids.length; i++) {
            if (ids[i] === id) {
                return true;
            }
        }
        return false;
    };
    c3_chart_internal_fn.isTargetToShow = function(targetId) {
        return this.hiddenTargetIds.indexOf(targetId) < 0;
    };
    c3_chart_internal_fn.isLegendToShow = function(targetId) {
        return this.hiddenLegendIds.indexOf(targetId) < 0;
    };
    c3_chart_internal_fn.filterTargetsToShow = function(targets) {
        var $$ = this;
        return targets.filter(function(t) {
            return $$.isTargetToShow(t.id);
        });
    };
    c3_chart_internal_fn.mapTargetsToUniqueXs = function(targets) {
        var $$ = this;
        var xs = $$.d3.set($$.d3.merge(targets.map(function(t) {
            return t.values.map(function(v) {
                return +v.x;
            });
        }))).values();
        return $$.isTimeSeries() ? xs.map(function(x) {
            return new Date(+x);
        }) : xs.map(function(x) {
            return +x;
        });
    };
    c3_chart_internal_fn.addHiddenTargetIds = function(targetIds) {
        this.hiddenTargetIds = this.hiddenTargetIds.concat(targetIds);
    };
    c3_chart_internal_fn.removeHiddenTargetIds = function(targetIds) {
        this.hiddenTargetIds = this.hiddenTargetIds.filter(function(id) {
            return targetIds.indexOf(id) < 0;
        });
    };
    c3_chart_internal_fn.addHiddenLegendIds = function(targetIds) {
        this.hiddenLegendIds = this.hiddenLegendIds.concat(targetIds);
    };
    c3_chart_internal_fn.removeHiddenLegendIds = function(targetIds) {
        this.hiddenLegendIds = this.hiddenLegendIds.filter(function(id) {
            return targetIds.indexOf(id) < 0;
        });
    };
    c3_chart_internal_fn.getValuesAsIdKeyed = function(targets) {
        var ys = {};
        targets.forEach(function(t) {
            ys[t.id] = [];
            t.values.forEach(function(v) {
                ys[t.id].push(v.value);
            });
        });
        return ys;
    };
    c3_chart_internal_fn.checkValueInTargets = function(targets, checker) {
        var ids = Object.keys(targets), i, j, values;
        for (i = 0; i < ids.length; i++) {
            values = targets[ids[i]].values;
            for (j = 0; j < values.length; j++) {
                if (checker(values[j].value)) {
                    return true;
                }
            }
        }
        return false;
    };
    c3_chart_internal_fn.hasNegativeValueInTargets = function(targets) {
        return this.checkValueInTargets(targets, function(v) {
            return v < 0;
        });
    };
    c3_chart_internal_fn.hasPositiveValueInTargets = function(targets) {
        return this.checkValueInTargets(targets, function(v) {
            return v > 0;
        });
    };
    c3_chart_internal_fn.isOrderDesc = function() {
        var config = this.config;
        return typeof config.data_order === "string" && config.data_order.toLowerCase() === "desc";
    };
    c3_chart_internal_fn.isOrderAsc = function() {
        var config = this.config;
        return typeof config.data_order === "string" && config.data_order.toLowerCase() === "asc";
    };
    c3_chart_internal_fn.orderTargets = function(targets) {
        var $$ = this, config = $$.config, orderAsc = $$.isOrderAsc(), orderDesc = $$.isOrderDesc();
        if (orderAsc || orderDesc) {
            targets.sort(function(t1, t2) {
                var reducer = function(p, c) {
                    return p + Math.abs(c.value);
                };
                var t1Sum = t1.values.reduce(reducer, 0), t2Sum = t2.values.reduce(reducer, 0);
                return orderAsc ? t2Sum - t1Sum : t1Sum - t2Sum;
            });
        } else if (isFunction(config.data_order)) {
            targets.sort(config.data_order);
        }
        return targets;
    };
    c3_chart_internal_fn.filterByX = function(targets, x) {
        return this.d3.merge(targets.map(function(t) {
            return t.values;
        })).filter(function(v) {
            return v.x - x === 0;
        });
    };
    c3_chart_internal_fn.filterRemoveNull = function(data) {
        return data.filter(function(d) {
            return isValue(d.value);
        });
    };
    c3_chart_internal_fn.filterByXDomain = function(targets, xDomain) {
        return targets.map(function(t) {
            return {
                id: t.id,
                id_org: t.id_org,
                values: t.values.filter(function(v) {
                    return xDomain[0] <= v.x && v.x <= xDomain[1];
                })
            };
        });
    };
    c3_chart_internal_fn.hasDataLabel = function() {
        var config = this.config;
        if (typeof config.data_labels === "boolean" && config.data_labels) {
            return true;
        } else if (typeof config.data_labels === "object" && notEmpty(config.data_labels)) {
            return true;
        }
        return false;
    };
    c3_chart_internal_fn.getDataLabelLength = function(min, max, key) {
        var $$ = this, lengths = [ 0, 0 ], paddingCoef = 1.3;
        $$.selectChart.select("svg").selectAll(".dummy").data([ min, max ]).enter().append("text").text(function(d) {
            return $$.dataLabelFormat(d.id)(d);
        }).each(function(d, i) {
            lengths[i] = this.getBoundingClientRect()[key] * paddingCoef;
        }).remove();
        return lengths;
    };
    c3_chart_internal_fn.isNoneArc = function(d) {
        return this.hasTarget(this.data.targets, d.id);
    }, c3_chart_internal_fn.isArc = function(d) {
        return "data" in d && this.hasTarget(this.data.targets, d.data.id);
    };
    c3_chart_internal_fn.findSameXOfValues = function(values, index) {
        var i, targetX = values[index].x, sames = [];
        for (i = index - 1; i >= 0; i--) {
            if (targetX !== values[i].x) {
                break;
            }
            sames.push(values[i]);
        }
        for (i = index; i < values.length; i++) {
            if (targetX !== values[i].x) {
                break;
            }
            sames.push(values[i]);
        }
        return sames;
    };
    c3_chart_internal_fn.findClosestFromTargets = function(targets, pos) {
        var $$ = this, candidates;
        candidates = targets.map(function(target) {
            return $$.findClosest(target.values, pos);
        });
        return $$.findClosest(candidates, pos);
    };
    c3_chart_internal_fn.findClosest = function(values, pos) {
        var $$ = this, minDist = 100, closest;
        values.filter(function(v) {
            return v && $$.isBarType(v.id);
        }).forEach(function(v) {
            var shape = $$.main.select("." + CLASS.bars + $$.getTargetSelectorSuffix(v.id) + " ." + CLASS.bar + "-" + v.index).node();
            if (!closest && $$.isWithinBar(shape)) {
                closest = v;
            }
        });
        values.filter(function(v) {
            return v && !$$.isBarType(v.id);
        }).forEach(function(v) {
            var d = $$.dist(v, pos);
            if (d < minDist) {
                minDist = d;
                closest = v;
            }
        });
        return closest;
    };
    c3_chart_internal_fn.dist = function(data, pos) {
        var $$ = this, config = $$.config, xIndex = config.axis_rotated ? 1 : 0, yIndex = config.axis_rotated ? 0 : 1, y = $$.circleY(data, data.index), x = $$.x(data.x);
        return Math.pow(x - pos[xIndex], 2) + Math.pow(y - pos[yIndex], 2);
    };
    c3_chart_internal_fn.convertValuesToStep = function(values) {
        var converted = [].concat(values), i;
        if (!this.isCategorized()) {
            return values;
        }
        for (i = values.length + 1; 0 < i; i--) {
            converted[i] = converted[i - 1];
        }
        converted[0] = {
            x: converted[0].x - 1,
            value: converted[0].value,
            id: converted[0].id
        };
        converted[values.length + 1] = {
            x: converted[values.length].x + 1,
            value: converted[values.length].value,
            id: converted[values.length].id
        };
        return converted;
    };
    c3_chart_internal_fn.updateDataAttributes = function(name, attrs) {
        var $$ = this, config = $$.config, current = config["data_" + name];
        if (typeof attrs === "undefined") {
            return current;
        }
        Object.keys(attrs).forEach(function(id) {
            current[id] = attrs[id];
        });
        $$.redraw({
            withLegend: true
        });
        return current;
    };
    c3_chart_internal_fn.convertUrlToData = function(url, mimeType, keys, done) {
        var $$ = this, type = mimeType ? mimeType : "csv";
        $$.d3.xhr(url, function(error, data) {
            var d;
            if (!data) {
                throw new Error(error.responseURL + " " + error.status + " (" + error.statusText + ")");
            }
            if (type === "json") {
                d = $$.convertJsonToData(JSON.parse(data.response), keys);
            } else if (type === "tsv") {
                d = $$.convertTsvToData(data.response);
            } else {
                d = $$.convertCsvToData(data.response);
            }
            done.call($$, d);
        });
    };
    c3_chart_internal_fn.convertXsvToData = function(xsv, parser) {
        var rows = parser.parseRows(xsv), d;
        if (rows.length === 1) {
            d = [ {} ];
            rows[0].forEach(function(id) {
                d[0][id] = null;
            });
        } else {
            d = parser.parse(xsv);
        }
        return d;
    };
    c3_chart_internal_fn.convertCsvToData = function(csv) {
        return this.convertXsvToData(csv, this.d3.csv);
    };
    c3_chart_internal_fn.convertTsvToData = function(tsv) {
        return this.convertXsvToData(tsv, this.d3.tsv);
    };
    c3_chart_internal_fn.convertJsonToData = function(json, keys) {
        var $$ = this, new_rows = [], targetKeys, data;
        if (keys) {
            if (keys.x) {
                targetKeys = keys.value.concat(keys.x);
                $$.config.data_x = keys.x;
            } else {
                targetKeys = keys.value;
            }
            new_rows.push(targetKeys);
            json.forEach(function(o) {
                var new_row = [];
                targetKeys.forEach(function(key) {
                    var v = isUndefined(o[key]) ? null : o[key];
                    new_row.push(v);
                });
                new_rows.push(new_row);
            });
            data = $$.convertRowsToData(new_rows);
        } else {
            Object.keys(json).forEach(function(key) {
                new_rows.push([ key ].concat(json[key]));
            });
            data = $$.convertColumnsToData(new_rows);
        }
        return data;
    };
    c3_chart_internal_fn.convertRowsToData = function(rows) {
        var keys = rows[0], new_row = {}, new_rows = [], i, j;
        for (i = 1; i < rows.length; i++) {
            new_row = {};
            for (j = 0; j < rows[i].length; j++) {
                if (isUndefined(rows[i][j])) {
                    throw new Error("Source data is missing a component at (" + i + "," + j + ")!");
                }
                new_row[keys[j]] = rows[i][j];
            }
            new_rows.push(new_row);
        }
        return new_rows;
    };
    c3_chart_internal_fn.convertColumnsToData = function(columns) {
        var new_rows = [], i, j, key;
        for (i = 0; i < columns.length; i++) {
            key = columns[i][0];
            for (j = 1; j < columns[i].length; j++) {
                if (isUndefined(new_rows[j - 1])) {
                    new_rows[j - 1] = {};
                }
                if (isUndefined(columns[i][j])) {
                    throw new Error("Source data is missing a component at (" + i + "," + j + ")!");
                }
                new_rows[j - 1][key] = columns[i][j];
            }
        }
        return new_rows;
    };
    c3_chart_internal_fn.convertDataToTargets = function(data, appendXs) {
        var $$ = this, config = $$.config, ids = $$.d3.keys(data[0]).filter($$.isNotX, $$), xs = $$.d3.keys(data[0]).filter($$.isX, $$), targets;
        ids.forEach(function(id) {
            var xKey = $$.getXKey(id);
            if ($$.isCustomX() || $$.isTimeSeries()) {
                if (xs.indexOf(xKey) >= 0) {
                    $$.data.xs[id] = (appendXs && $$.data.xs[id] ? $$.data.xs[id] : []).concat(data.map(function(d) {
                        return d[xKey];
                    }).filter(isValue).map(function(rawX, i) {
                        return $$.generateTargetX(rawX, id, i);
                    }));
                } else if (config.data_x) {
                    $$.data.xs[id] = $$.getOtherTargetXs();
                } else if (notEmpty(config.data_xs)) {
                    $$.data.xs[id] = $$.getXValuesOfXKey(xKey, $$.data.targets);
                }
            } else {
                $$.data.xs[id] = data.map(function(d, i) {
                    return i;
                });
            }
        });
        ids.forEach(function(id) {
            if (!$$.data.xs[id]) {
                throw new Error('x is not defined for id = "' + id + '".');
            }
        });
        targets = ids.map(function(id, index) {
            var convertedId = config.data_idConverter(id);
            return {
                id: convertedId,
                id_org: id,
                values: data.map(function(d, i) {
                    var xKey = $$.getXKey(id), rawX = d[xKey], x = $$.generateTargetX(rawX, id, i);
                    if ($$.isCustomX() && $$.isCategorized() && index === 0 && rawX) {
                        if (i === 0) {
                            config.axis_x_categories = [];
                        }
                        config.axis_x_categories.push(rawX);
                    }
                    if (isUndefined(d[id]) || $$.data.xs[id].length <= i) {
                        x = undefined;
                    }
                    return {
                        x: x,
                        value: d[id] !== null && !isNaN(d[id]) ? +d[id] : null,
                        id: convertedId
                    };
                }).filter(function(v) {
                    return isDefined(v.x);
                })
            };
        });
        targets.forEach(function(t) {
            var i;
            if (config.data_xSort) {
                t.values = t.values.sort(function(v1, v2) {
                    var x1 = v1.x || v1.x === 0 ? v1.x : Infinity, x2 = v2.x || v2.x === 0 ? v2.x : Infinity;
                    return x1 - x2;
                });
            }
            i = 0;
            t.values.forEach(function(v) {
                v.index = i++;
            });
            $$.data.xs[t.id].sort(function(v1, v2) {
                return v1 - v2;
            });
        });
        if (config.data_type) {
            $$.setTargetType($$.mapToIds(targets).filter(function(id) {
                return !(id in config.data_types);
            }), config.data_type);
        }
        targets.forEach(function(d) {
            $$.addCache(d.id_org, d);
        });
        return targets;
    };
    c3_chart_internal_fn.load = function(targets, args) {
        var $$ = this;
        if (targets) {
            if (args.filter) {
                targets = targets.filter(args.filter);
            }
            if (args.type || args.types) {
                targets.forEach(function(t) {
                    var type = args.types && args.types[t.id] ? args.types[t.id] : args.type;
                    $$.setTargetType(t.id, type);
                });
            }
            $$.data.targets.forEach(function(d) {
                for (var i = 0; i < targets.length; i++) {
                    if (d.id === targets[i].id) {
                        d.values = targets[i].values;
                        targets.splice(i, 1);
                        break;
                    }
                }
            });
            $$.data.targets = $$.data.targets.concat(targets);
        }
        $$.updateTargets($$.data.targets);
        $$.redraw({
            withUpdateOrgXDomain: true,
            withUpdateXDomain: true,
            withLegend: true
        });
        if (args.done) {
            args.done();
        }
    };
    c3_chart_internal_fn.loadFromArgs = function(args) {
        var $$ = this;
        if (args.data) {
            $$.load($$.convertDataToTargets(args.data), args);
        } else if (args.url) {
            $$.convertUrlToData(args.url, args.mimeType, args.keys, function(data) {
                $$.load($$.convertDataToTargets(data), args);
            });
        } else if (args.json) {
            $$.load($$.convertDataToTargets($$.convertJsonToData(args.json, args.keys)), args);
        } else if (args.rows) {
            $$.load($$.convertDataToTargets($$.convertRowsToData(args.rows)), args);
        } else if (args.columns) {
            $$.load($$.convertDataToTargets($$.convertColumnsToData(args.columns)), args);
        } else {
            $$.load(null, args);
        }
    };
    c3_chart_internal_fn.unload = function(targetIds, done) {
        var $$ = this;
        if (!done) {
            done = function() {};
        }
        targetIds = targetIds.filter(function(id) {
            return $$.hasTarget($$.data.targets, id);
        });
        if (!targetIds || targetIds.length === 0) {
            done();
            return;
        }
        $$.svg.selectAll(targetIds.map(function(id) {
            return $$.selectorTarget(id);
        })).transition().style("opacity", 0).remove().call($$.endall, done);
        targetIds.forEach(function(id) {
            $$.withoutFadeIn[id] = false;
            if ($$.legend) {
                $$.legend.selectAll("." + CLASS.legendItem + $$.getTargetSelectorSuffix(id)).remove();
            }
            $$.data.targets = $$.data.targets.filter(function(t) {
                return t.id !== id;
            });
        });
    };
    c3_chart_internal_fn.categoryName = function(i) {
        var config = this.config;
        return i < config.axis_x_categories.length ? config.axis_x_categories[i] : i;
    };
    c3_chart_internal_fn.initEventRect = function() {
        var $$ = this;
        $$.main.select("." + CLASS.chart).append("g").attr("class", CLASS.eventRects).style("fill-opacity", 0);
    };
    c3_chart_internal_fn.redrawEventRect = function() {
        var $$ = this, config = $$.config, eventRectUpdate, maxDataCountTarget, isMultipleX = $$.isMultipleX();
        var eventRects = $$.main.select("." + CLASS.eventRects).style("cursor", config.zoom_enabled ? config.axis_rotated ? "ns-resize" : "ew-resize" : null).classed(CLASS.eventRectsMultiple, isMultipleX).classed(CLASS.eventRectsSingle, !isMultipleX);
        eventRects.selectAll("." + CLASS.eventRect).remove();
        $$.eventRect = eventRects.selectAll("." + CLASS.eventRect);
        if (isMultipleX) {
            eventRectUpdate = $$.eventRect.data([ 0 ]);
            $$.generateEventRectsForMultipleXs(eventRectUpdate.enter());
            $$.updateEventRect(eventRectUpdate);
        } else {
            maxDataCountTarget = $$.getMaxDataCountTarget($$.data.targets);
            eventRects.datum(maxDataCountTarget ? maxDataCountTarget.values : []);
            $$.eventRect = eventRects.selectAll("." + CLASS.eventRect);
            eventRectUpdate = $$.eventRect.data(function(d) {
                return d;
            });
            $$.generateEventRectsForSingleX(eventRectUpdate.enter());
            $$.updateEventRect(eventRectUpdate);
            eventRectUpdate.exit().remove();
        }
    };
    c3_chart_internal_fn.updateEventRect = function(eventRectUpdate) {
        var $$ = this, config = $$.config, x, y, w, h, rectW, rectX;
        eventRectUpdate = eventRectUpdate || $$.eventRect.data(function(d) {
            return d;
        });
        if ($$.isMultipleX()) {
            x = 0;
            y = 0;
            w = $$.width;
            h = $$.height;
        } else {
            if (($$.isCustomX() || $$.isTimeSeries()) && !$$.isCategorized()) {
                $$.updateXs();
                rectW = function(d) {
                    var prevX = $$.getPrevX(d.index), nextX = $$.getNextX(d.index);
                    if (prevX === null && nextX === null) {
                        return config.axis_rotated ? $$.height : $$.width;
                    }
                    if (prevX === null) {
                        prevX = $$.x.domain()[0];
                    }
                    if (nextX === null) {
                        nextX = $$.x.domain()[1];
                    }
                    return Math.max(0, ($$.x(nextX) - $$.x(prevX)) / 2);
                };
                rectX = function(d) {
                    var prevX = $$.getPrevX(d.index), nextX = $$.getNextX(d.index), thisX = $$.data.xs[d.id][d.index];
                    if (prevX === null && nextX === null) {
                        return 0;
                    }
                    if (prevX === null) {
                        prevX = $$.x.domain()[0];
                    }
                    return ($$.x(thisX) + $$.x(prevX)) / 2;
                };
            } else {
                rectW = $$.getEventRectWidth();
                rectX = function(d) {
                    return $$.x(d.x) - rectW / 2;
                };
            }
            x = config.axis_rotated ? 0 : rectX;
            y = config.axis_rotated ? rectX : 0;
            w = config.axis_rotated ? $$.width : rectW;
            h = config.axis_rotated ? rectW : $$.height;
        }
        eventRectUpdate.attr("class", $$.classEvent.bind($$)).attr("x", x).attr("y", y).attr("width", w).attr("height", h);
    };
    c3_chart_internal_fn.generateEventRectsForSingleX = function(eventRectEnter) {
        var $$ = this, d3 = $$.d3, config = $$.config;
        eventRectEnter.append("rect").attr("class", $$.classEvent.bind($$)).style("cursor", config.data_selection_enabled && config.data_selection_grouped ? "pointer" : null).on("mouseover", function(d) {
            var index = d.index;
            if ($$.dragging || $$.flowing) {
                return;
            }
            if ($$.hasArcType()) {
                return;
            }
            if (config.point_focus_expand_enabled) {
                $$.expandCircles(index, null, true);
            }
            $$.expandBars(index, null, true);
            $$.main.selectAll("." + CLASS.shape + "-" + index).each(function(d) {
                config.data_onmouseover.call($$.api, d);
            });
        }).on("mouseout", function(d) {
            var index = d.index;
            if (!$$.config) {
                return;
            }
            if ($$.hasArcType()) {
                return;
            }
            $$.hideXGridFocus();
            $$.hideTooltip();
            $$.unexpandCircles();
            $$.unexpandBars();
            $$.main.selectAll("." + CLASS.shape + "-" + index).each(function(d) {
                config.data_onmouseout.call($$.api, d);
            });
        }).on("mousemove", function(d) {
            var selectedData, index = d.index, eventRect = $$.svg.select("." + CLASS.eventRect + "-" + index);
            if ($$.dragging || $$.flowing) {
                return;
            }
            if ($$.hasArcType()) {
                return;
            }
            if ($$.isStepType(d) && $$.config.line_step_type === "step-after" && d3.mouse(this)[0] < $$.x($$.getXValue(d.id, index))) {
                index -= 1;
            }
            selectedData = $$.filterTargetsToShow($$.data.targets).map(function(t) {
                return $$.addName($$.getValueOnIndex(t.values, index));
            });
            if (config.tooltip_grouped) {
                $$.showTooltip(selectedData, this);
                $$.showXGridFocus(selectedData);
            }
            if (config.tooltip_grouped && (!config.data_selection_enabled || config.data_selection_grouped)) {
                return;
            }
            $$.main.selectAll("." + CLASS.shape + "-" + index).each(function() {
                d3.select(this).classed(CLASS.EXPANDED, true);
                if (config.data_selection_enabled) {
                    eventRect.style("cursor", config.data_selection_grouped ? "pointer" : null);
                }
                if (!config.tooltip_grouped) {
                    $$.hideXGridFocus();
                    $$.hideTooltip();
                    if (!config.data_selection_grouped) {
                        $$.unexpandCircles(index);
                        $$.unexpandBars(index);
                    }
                }
            }).filter(function(d) {
                return $$.isWithinShape(this, d);
            }).each(function(d) {
                if (config.data_selection_enabled && (config.data_selection_grouped || config.data_selection_isselectable(d))) {
                    eventRect.style("cursor", "pointer");
                }
                if (!config.tooltip_grouped) {
                    $$.showTooltip([ d ], this);
                    $$.showXGridFocus([ d ]);
                    if (config.point_focus_expand_enabled) {
                        $$.expandCircles(index, d.id, true);
                    }
                    $$.expandBars(index, d.id, true);
                }
            });
        }).on("click", function(d) {
            var index = d.index;
            if ($$.hasArcType() || !$$.toggleShape) {
                return;
            }
            if ($$.cancelClick) {
                $$.cancelClick = false;
                return;
            }
            if ($$.isStepType(d) && config.line_step_type === "step-after" && d3.mouse(this)[0] < $$.x($$.getXValue(d.id, index))) {
                index -= 1;
            }
            $$.main.selectAll("." + CLASS.shape + "-" + index).each(function(d) {
                if (config.data_selection_grouped || $$.isWithinShape(this, d)) {
                    $$.toggleShape(this, d, index);
                    $$.config.data_onclick.call($$.api, d, this);
                }
            });
        }).call(config.data_selection_draggable && $$.drag ? d3.behavior.drag().origin(Object).on("drag", function() {
            $$.drag(d3.mouse(this));
        }).on("dragstart", function() {
            $$.dragstart(d3.mouse(this));
        }).on("dragend", function() {
            $$.dragend();
        }) : function() {});
    };
    c3_chart_internal_fn.generateEventRectsForMultipleXs = function(eventRectEnter) {
        var $$ = this, d3 = $$.d3, config = $$.config;
        function mouseout() {
            $$.svg.select("." + CLASS.eventRect).style("cursor", null);
            $$.hideXGridFocus();
            $$.hideTooltip();
            $$.unexpandCircles();
            $$.unexpandBars();
        }
        eventRectEnter.append("rect").attr("x", 0).attr("y", 0).attr("width", $$.width).attr("height", $$.height).attr("class", CLASS.eventRect).on("mouseout", function() {
            if (!$$.config) {
                return;
            }
            if ($$.hasArcType()) {
                return;
            }
            mouseout();
        }).on("mousemove", function() {
            var targetsToShow = $$.filterTargetsToShow($$.data.targets);
            var mouse, closest, sameXData, selectedData;
            if ($$.dragging) {
                return;
            }
            if ($$.hasArcType(targetsToShow)) {
                return;
            }
            mouse = d3.mouse(this);
            closest = $$.findClosestFromTargets(targetsToShow, mouse);
            if ($$.mouseover && (!closest || closest.id !== $$.mouseover.id)) {
                config.data_onmouseout.call($$.api, $$.mouseover);
                $$.mouseover = undefined;
            }
            if (!closest) {
                mouseout();
                return;
            }
            if ($$.isScatterType(closest) || !config.tooltip_grouped) {
                sameXData = [ closest ];
            } else {
                sameXData = $$.filterByX(targetsToShow, closest.x);
            }
            selectedData = sameXData.map(function(d) {
                return $$.addName(d);
            });
            $$.showTooltip(selectedData, this);
            if (config.point_focus_expand_enabled) {
                $$.expandCircles(closest.index, closest.id, true);
            }
            $$.expandBars(closest.index, closest.id, true);
            $$.showXGridFocus(selectedData);
            if ($$.isBarType(closest.id) || $$.dist(closest, mouse) < 100) {
                $$.svg.select("." + CLASS.eventRect).style("cursor", "pointer");
                if (!$$.mouseover) {
                    config.data_onmouseover.call($$.api, closest);
                    $$.mouseover = closest;
                }
            }
        }).on("click", function() {
            var targetsToShow = $$.filterTargetsToShow($$.data.targets);
            var mouse, closest;
            if ($$.hasArcType(targetsToShow)) {
                return;
            }
            mouse = d3.mouse(this);
            closest = $$.findClosestFromTargets(targetsToShow, mouse);
            if (!closest) {
                return;
            }
            if ($$.isBarType(closest.id) || $$.dist(closest, mouse) < 100) {
                $$.main.selectAll("." + CLASS.shapes + $$.getTargetSelectorSuffix(closest.id)).selectAll("." + CLASS.shape + "-" + closest.index).each(function() {
                    if (config.data_selection_grouped || $$.isWithinShape(this, closest)) {
                        $$.toggleShape(this, closest, closest.index);
                        $$.config.data_onclick.call($$.api, closest, this);
                    }
                });
            }
        }).call(config.data_selection_draggable && $$.drag ? d3.behavior.drag().origin(Object).on("drag", function() {
            $$.drag(d3.mouse(this));
        }).on("dragstart", function() {
            $$.dragstart(d3.mouse(this));
        }).on("dragend", function() {
            $$.dragend();
        }) : function() {});
    };
    c3_chart_internal_fn.dispatchEvent = function(type, index, mouse) {
        var $$ = this, selector = "." + CLASS.eventRect + (!$$.isMultipleX() ? "-" + index : ""), eventRect = $$.main.select(selector).node(), box = eventRect.getBoundingClientRect(), x = box.left + (mouse ? mouse[0] : 0), y = box.top + (mouse ? mouse[1] : 0), event = document.createEvent("MouseEvents");
        event.initMouseEvent(type, true, true, window, 0, x, y, x, y, false, false, false, false, 0, null);
        eventRect.dispatchEvent(event);
    };
    c3_chart_internal_fn.getCurrentWidth = function() {
        var $$ = this, config = $$.config;
        return config.size_width ? config.size_width : $$.getParentWidth();
    };
    c3_chart_internal_fn.getCurrentHeight = function() {
        var $$ = this, config = $$.config, h = config.size_height ? config.size_height : $$.getParentHeight();
        return h > 0 ? h : 320 / ($$.hasType("gauge") ? 2 : 1);
    };
    c3_chart_internal_fn.getCurrentPaddingTop = function() {
        var config = this.config;
        return isValue(config.padding_top) ? config.padding_top : 0;
    };
    c3_chart_internal_fn.getCurrentPaddingBottom = function() {
        var config = this.config;
        return isValue(config.padding_bottom) ? config.padding_bottom : 0;
    };
    c3_chart_internal_fn.getCurrentPaddingLeft = function(withoutRecompute) {
        var $$ = this, config = $$.config;
        if (isValue(config.padding_left)) {
            return config.padding_left;
        } else if (config.axis_rotated) {
            return !config.axis_x_show ? 1 : Math.max(ceil10($$.getAxisWidthByAxisId("x", withoutRecompute)), 40);
        } else if (!config.axis_y_show || config.axis_y_inner) {
            return $$.axis.getYAxisLabelPosition().isOuter ? 30 : 1;
        } else {
            return ceil10($$.getAxisWidthByAxisId("y", withoutRecompute));
        }
    };
    c3_chart_internal_fn.getCurrentPaddingRight = function() {
        var $$ = this, config = $$.config, defaultPadding = 10, legendWidthOnRight = $$.isLegendRight ? $$.getLegendWidth() + 20 : 0;
        if (isValue(config.padding_right)) {
            return config.padding_right + 1;
        } else if (config.axis_rotated) {
            return defaultPadding + legendWidthOnRight;
        } else if (!config.axis_y2_show || config.axis_y2_inner) {
            return 2 + legendWidthOnRight + ($$.axis.getY2AxisLabelPosition().isOuter ? 20 : 0);
        } else {
            return ceil10($$.getAxisWidthByAxisId("y2")) + legendWidthOnRight;
        }
    };
    c3_chart_internal_fn.getParentRectValue = function(key) {
        var parent = this.selectChart.node(), v;
        while (parent && parent.tagName !== "BODY") {
            try {
                v = parent.getBoundingClientRect()[key];
            } catch (e) {
                if (key === "width") {
                    v = parent.offsetWidth;
                }
            }
            if (v) {
                break;
            }
            parent = parent.parentNode;
        }
        return v;
    };
    c3_chart_internal_fn.getParentWidth = function() {
        return this.getParentRectValue("width");
    };
    c3_chart_internal_fn.getParentHeight = function() {
        var h = this.selectChart.style("height");
        return h.indexOf("px") > 0 ? +h.replace("px", "") : 0;
    };
    c3_chart_internal_fn.getSvgLeft = function(withoutRecompute) {
        var $$ = this, config = $$.config, hasLeftAxisRect = config.axis_rotated || !config.axis_rotated && !config.axis_y_inner, leftAxisClass = config.axis_rotated ? CLASS.axisX : CLASS.axisY, leftAxis = $$.main.select("." + leftAxisClass).node(), svgRect = leftAxis && hasLeftAxisRect ? leftAxis.getBoundingClientRect() : {
            right: 0
        }, chartRect = $$.selectChart.node().getBoundingClientRect(), hasArc = $$.hasArcType(), svgLeft = svgRect.right - chartRect.left - (hasArc ? 0 : $$.getCurrentPaddingLeft(withoutRecompute));
        return svgLeft > 0 ? svgLeft : 0;
    };
    c3_chart_internal_fn.getAxisWidthByAxisId = function(id, withoutRecompute) {
        var $$ = this, position = $$.axis.getLabelPositionById(id);
        return $$.axis.getMaxTickWidth(id, withoutRecompute) + (position.isInner ? 20 : 40);
    };
    c3_chart_internal_fn.getHorizontalAxisHeight = function(axisId) {
        var $$ = this, config = $$.config, h = 30;
        if (axisId === "x" && !config.axis_x_show) {
            return 8;
        }
        if (axisId === "x" && config.axis_x_height) {
            return config.axis_x_height;
        }
        if (axisId === "y" && !config.axis_y_show) {
            return config.legend_show && !$$.isLegendRight && !$$.isLegendInset ? 10 : 1;
        }
        if (axisId === "y2" && !config.axis_y2_show) {
            return $$.rotated_padding_top;
        }
        if (axisId === "x" && !config.axis_rotated && config.axis_x_tick_rotate) {
            h = 30 + $$.axis.getMaxTickWidth(axisId) * Math.cos(Math.PI * (90 - config.axis_x_tick_rotate) / 180);
        }
        return h + ($$.axis.getLabelPositionById(axisId).isInner ? 0 : 10) + (axisId === "y2" ? -10 : 0);
    };
    c3_chart_internal_fn.getEventRectWidth = function() {
        return Math.max(0, this.xAxis.tickInterval());
    };
    c3_chart_internal_fn.getShapeIndices = function(typeFilter) {
        var $$ = this, config = $$.config, indices = {}, i = 0, j, k;
        $$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$)).forEach(function(d) {
            for (j = 0; j < config.data_groups.length; j++) {
                if (config.data_groups[j].indexOf(d.id) < 0) {
                    continue;
                }
                for (k = 0; k < config.data_groups[j].length; k++) {
                    if (config.data_groups[j][k] in indices) {
                        indices[d.id] = indices[config.data_groups[j][k]];
                        break;
                    }
                }
            }
            if (isUndefined(indices[d.id])) {
                indices[d.id] = i++;
            }
        });
        indices.__max__ = i - 1;
        return indices;
    };
    c3_chart_internal_fn.getShapeX = function(offset, targetsNum, indices, isSub) {
        var $$ = this, scale = isSub ? $$.subX : $$.x;
        return function(d) {
            var index = d.id in indices ? indices[d.id] : 0;
            return d.x || d.x === 0 ? scale(d.x) - offset * (targetsNum / 2 - index) : 0;
        };
    };
    c3_chart_internal_fn.getShapeY = function(isSub) {
        var $$ = this;
        return function(d) {
            var scale = isSub ? $$.getSubYScale(d.id) : $$.getYScale(d.id);
            return scale(d.value);
        };
    };
    c3_chart_internal_fn.getShapeOffset = function(typeFilter, indices, isSub) {
        var $$ = this, targets = $$.orderTargets($$.filterTargetsToShow($$.data.targets.filter(typeFilter, $$))), targetIds = targets.map(function(t) {
            return t.id;
        });
        return function(d, i) {
            var scale = isSub ? $$.getSubYScale(d.id) : $$.getYScale(d.id), y0 = scale(0), offset = y0;
            targets.forEach(function(t) {
                var values = $$.isStepType(d) ? $$.convertValuesToStep(t.values) : t.values;
                if (t.id === d.id || indices[t.id] !== indices[d.id]) {
                    return;
                }
                if (targetIds.indexOf(t.id) < targetIds.indexOf(d.id)) {
                    if (values[i].value * d.value >= 0) {
                        offset += scale(values[i].value) - y0;
                    }
                }
            });
            return offset;
        };
    };
    c3_chart_internal_fn.isWithinShape = function(that, d) {
        var $$ = this, shape = $$.d3.select(that), isWithin;
        if (!$$.isTargetToShow(d.id)) {
            isWithin = false;
        } else if (that.nodeName === "circle") {
            isWithin = $$.isStepType(d) ? $$.isWithinStep(that, $$.getYScale(d.id)(d.value)) : $$.isWithinCircle(that, $$.pointSelectR(d) * 1.5);
        } else if (that.nodeName === "path") {
            isWithin = shape.classed(CLASS.bar) ? $$.isWithinBar(that) : true;
        }
        return isWithin;
    };
    c3_chart_internal_fn.getInterpolate = function(d) {
        var $$ = this;
        return $$.isSplineType(d) ? "cardinal" : $$.isStepType(d) ? $$.config.line_step_type : "linear";
    };
    c3_chart_internal_fn.initLine = function() {
        var $$ = this;
        $$.main.select("." + CLASS.chart).append("g").attr("class", CLASS.chartLines);
    };
    c3_chart_internal_fn.updateTargetsForLine = function(targets) {
        var $$ = this, config = $$.config, mainLineUpdate, mainLineEnter, classChartLine = $$.classChartLine.bind($$), classLines = $$.classLines.bind($$), classAreas = $$.classAreas.bind($$), classCircles = $$.classCircles.bind($$), classFocus = $$.classFocus.bind($$);
        mainLineUpdate = $$.main.select("." + CLASS.chartLines).selectAll("." + CLASS.chartLine).data(targets).attr("class", function(d) {
            return classChartLine(d) + classFocus(d);
        });
        mainLineEnter = mainLineUpdate.enter().append("g").attr("class", classChartLine).style("opacity", 0).style("pointer-events", "none");
        mainLineEnter.append("g").attr("class", classLines);
        mainLineEnter.append("g").attr("class", classAreas);
        mainLineEnter.append("g").attr("class", function(d) {
            return $$.generateClass(CLASS.selectedCircles, d.id);
        });
        mainLineEnter.append("g").attr("class", classCircles).style("cursor", function(d) {
            return config.data_selection_isselectable(d) ? "pointer" : null;
        });
        targets.forEach(function(t) {
            $$.main.selectAll("." + CLASS.selectedCircles + $$.getTargetSelectorSuffix(t.id)).selectAll("." + CLASS.selectedCircle).each(function(d) {
                d.value = t.values[d.index].value;
            });
        });
    };
    c3_chart_internal_fn.updateLine = function(durationForExit) {
        var $$ = this;
        $$.mainLine = $$.main.selectAll("." + CLASS.lines).selectAll("." + CLASS.line).data($$.lineData.bind($$));
        $$.mainLine.enter().append("path").attr("class", $$.classLine.bind($$)).style("stroke", $$.color);
        $$.mainLine.style("opacity", $$.initialOpacity.bind($$)).style("shape-rendering", function(d) {
            return $$.isStepType(d) ? "crispEdges" : "";
        }).attr("transform", null);
        $$.mainLine.exit().transition().duration(durationForExit).style("opacity", 0).remove();
    };
    c3_chart_internal_fn.redrawLine = function(drawLine, withTransition) {
        return [ (withTransition ? this.mainLine.transition() : this.mainLine).attr("d", drawLine).style("stroke", this.color).style("opacity", 1) ];
    };
    c3_chart_internal_fn.generateDrawLine = function(lineIndices, isSub) {
        var $$ = this, config = $$.config, line = $$.d3.svg.line(), getPoints = $$.generateGetLinePoints(lineIndices, isSub), yScaleGetter = isSub ? $$.getSubYScale : $$.getYScale, xValue = function(d) {
            return (isSub ? $$.subxx : $$.xx).call($$, d);
        }, yValue = function(d, i) {
            return config.data_groups.length > 0 ? getPoints(d, i)[0][1] : yScaleGetter.call($$, d.id)(d.value);
        };
        line = config.axis_rotated ? line.x(yValue).y(xValue) : line.x(xValue).y(yValue);
        if (!config.line_connectNull) {
            line = line.defined(function(d) {
                return d.value != null;
            });
        }
        return function(d) {
            var values = config.line_connectNull ? $$.filterRemoveNull(d.values) : d.values, x = isSub ? $$.x : $$.subX, y = yScaleGetter.call($$, d.id), x0 = 0, y0 = 0, path;
            if ($$.isLineType(d)) {
                if (config.data_regions[d.id]) {
                    path = $$.lineWithRegions(values, x, y, config.data_regions[d.id]);
                } else {
                    if ($$.isStepType(d)) {
                        values = $$.convertValuesToStep(values);
                    }
                    path = line.interpolate($$.getInterpolate(d))(values);
                }
            } else {
                if (values[0]) {
                    x0 = x(values[0].x);
                    y0 = y(values[0].value);
                }
                path = config.axis_rotated ? "M " + y0 + " " + x0 : "M " + x0 + " " + y0;
            }
            return path ? path : "M 0 0";
        };
    };
    c3_chart_internal_fn.generateGetLinePoints = function(lineIndices, isSub) {
        var $$ = this, config = $$.config, lineTargetsNum = lineIndices.__max__ + 1, x = $$.getShapeX(0, lineTargetsNum, lineIndices, !!isSub), y = $$.getShapeY(!!isSub), lineOffset = $$.getShapeOffset($$.isLineType, lineIndices, !!isSub), yScale = isSub ? $$.getSubYScale : $$.getYScale;
        return function(d, i) {
            var y0 = yScale.call($$, d.id)(0), offset = lineOffset(d, i) || y0, posX = x(d), posY = y(d);
            if (config.axis_rotated) {
                if (0 < d.value && posY < y0 || d.value < 0 && y0 < posY) {
                    posY = y0;
                }
            }
            return [ [ posX, posY - (y0 - offset) ], [ posX, posY - (y0 - offset) ], [ posX, posY - (y0 - offset) ], [ posX, posY - (y0 - offset) ] ];
        };
    };
    c3_chart_internal_fn.lineWithRegions = function(d, x, y, _regions) {
        var $$ = this, config = $$.config, prev = -1, i, j, s = "M", sWithRegion, xp, yp, dx, dy, dd, diff, diffx2, xOffset = $$.isCategorized() ? .5 : 0, xValue, yValue, regions = [];
        function isWithinRegions(x, regions) {
            var i;
            for (i = 0; i < regions.length; i++) {
                if (regions[i].start < x && x <= regions[i].end) {
                    return true;
                }
            }
            return false;
        }
        if (isDefined(_regions)) {
            for (i = 0; i < _regions.length; i++) {
                regions[i] = {};
                if (isUndefined(_regions[i].start)) {
                    regions[i].start = d[0].x;
                } else {
                    regions[i].start = $$.isTimeSeries() ? $$.parseDate(_regions[i].start) : _regions[i].start;
                }
                if (isUndefined(_regions[i].end)) {
                    regions[i].end = d[d.length - 1].x;
                } else {
                    regions[i].end = $$.isTimeSeries() ? $$.parseDate(_regions[i].end) : _regions[i].end;
                }
            }
        }
        xValue = config.axis_rotated ? function(d) {
            return y(d.value);
        } : function(d) {
            return x(d.x);
        };
        yValue = config.axis_rotated ? function(d) {
            return x(d.x);
        } : function(d) {
            return y(d.value);
        };
        function generateM(points) {
            return "M" + points[0][0] + " " + points[0][1] + " " + points[1][0] + " " + points[1][1];
        }
        if ($$.isTimeSeries()) {
            sWithRegion = function(d0, d1, j, diff) {
                var x0 = d0.x.getTime(), x_diff = d1.x - d0.x, xv0 = new Date(x0 + x_diff * j), xv1 = new Date(x0 + x_diff * (j + diff)), points;
                if (config.axis_rotated) {
                    points = [ [ y(yp(j)), x(xv0) ], [ y(yp(j + diff)), x(xv1) ] ];
                } else {
                    points = [ [ x(xv0), y(yp(j)) ], [ x(xv1), y(yp(j + diff)) ] ];
                }
                return generateM(points);
            };
        } else {
            sWithRegion = function(d0, d1, j, diff) {
                var points;
                if (config.axis_rotated) {
                    points = [ [ y(yp(j), true), x(xp(j)) ], [ y(yp(j + diff), true), x(xp(j + diff)) ] ];
                } else {
                    points = [ [ x(xp(j), true), y(yp(j)) ], [ x(xp(j + diff), true), y(yp(j + diff)) ] ];
                }
                return generateM(points);
            };
        }
        for (i = 0; i < d.length; i++) {
            if (isUndefined(regions) || !isWithinRegions(d[i].x, regions)) {
                s += " " + xValue(d[i]) + " " + yValue(d[i]);
            } else {
                xp = $$.getScale(d[i - 1].x + xOffset, d[i].x + xOffset, $$.isTimeSeries());
                yp = $$.getScale(d[i - 1].value, d[i].value);
                dx = x(d[i].x) - x(d[i - 1].x);
                dy = y(d[i].value) - y(d[i - 1].value);
                dd = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
                diff = 2 / dd;
                diffx2 = diff * 2;
                for (j = diff; j <= 1; j += diffx2) {
                    s += sWithRegion(d[i - 1], d[i], j, diff);
                }
            }
            prev = d[i].x;
        }
        return s;
    };
    c3_chart_internal_fn.updateArea = function(durationForExit) {
        var $$ = this, d3 = $$.d3;
        $$.mainArea = $$.main.selectAll("." + CLASS.areas).selectAll("." + CLASS.area).data($$.lineData.bind($$));
        $$.mainArea.enter().append("path").attr("class", $$.classArea.bind($$)).style("fill", $$.color).style("opacity", function() {
            $$.orgAreaOpacity = +d3.select(this).style("opacity");
            return 0;
        });
        $$.mainArea.style("opacity", $$.orgAreaOpacity);
        $$.mainArea.exit().transition().duration(durationForExit).style("opacity", 0).remove();
    };
    c3_chart_internal_fn.redrawArea = function(drawArea, withTransition) {
        return [ (withTransition ? this.mainArea.transition() : this.mainArea).attr("d", drawArea).style("fill", this.color).style("opacity", this.orgAreaOpacity) ];
    };
    c3_chart_internal_fn.generateDrawArea = function(areaIndices, isSub) {
        var $$ = this, config = $$.config, area = $$.d3.svg.area(), getPoints = $$.generateGetAreaPoints(areaIndices, isSub), yScaleGetter = isSub ? $$.getSubYScale : $$.getYScale, xValue = function(d) {
            return (isSub ? $$.subxx : $$.xx).call($$, d);
        }, value0 = function(d, i) {
            return config.data_groups.length > 0 ? getPoints(d, i)[0][1] : yScaleGetter.call($$, d.id)($$.getAreaBaseValue(d.id));
        }, value1 = function(d, i) {
            return config.data_groups.length > 0 ? getPoints(d, i)[1][1] : yScaleGetter.call($$, d.id)(d.value);
        };
        area = config.axis_rotated ? area.x0(value0).x1(value1).y(xValue) : area.x(xValue).y0(value0).y1(value1);
        if (!config.line_connectNull) {
            area = area.defined(function(d) {
                return d.value !== null;
            });
        }
        return function(d) {
            var values = config.line_connectNull ? $$.filterRemoveNull(d.values) : d.values, x0 = 0, y0 = 0, path;
            if ($$.isAreaType(d)) {
                if ($$.isStepType(d)) {
                    values = $$.convertValuesToStep(values);
                }
                path = area.interpolate($$.getInterpolate(d))(values);
            } else {
                if (values[0]) {
                    x0 = $$.x(values[0].x);
                    y0 = $$.getYScale(d.id)(values[0].value);
                }
                path = config.axis_rotated ? "M " + y0 + " " + x0 : "M " + x0 + " " + y0;
            }
            return path ? path : "M 0 0";
        };
    };
    c3_chart_internal_fn.getAreaBaseValue = function() {
        return 0;
    };
    c3_chart_internal_fn.generateGetAreaPoints = function(areaIndices, isSub) {
        var $$ = this, config = $$.config, areaTargetsNum = areaIndices.__max__ + 1, x = $$.getShapeX(0, areaTargetsNum, areaIndices, !!isSub), y = $$.getShapeY(!!isSub), areaOffset = $$.getShapeOffset($$.isAreaType, areaIndices, !!isSub), yScale = isSub ? $$.getSubYScale : $$.getYScale;
        return function(d, i) {
            var y0 = yScale.call($$, d.id)(0), offset = areaOffset(d, i) || y0, posX = x(d), posY = y(d);
            if (config.axis_rotated) {
                if (0 < d.value && posY < y0 || d.value < 0 && y0 < posY) {
                    posY = y0;
                }
            }
            return [ [ posX, offset ], [ posX, posY - (y0 - offset) ], [ posX, posY - (y0 - offset) ], [ posX, offset ] ];
        };
    };
    c3_chart_internal_fn.updateCircle = function() {
        var $$ = this;
        $$.mainCircle = $$.main.selectAll("." + CLASS.circles).selectAll("." + CLASS.circle).data($$.lineOrScatterData.bind($$));
        $$.mainCircle.enter().append("circle").attr("class", $$.classCircle.bind($$)).attr("r", $$.pointR.bind($$)).style("fill", $$.color);
        $$.mainCircle.style("opacity", $$.initialOpacityForCircle.bind($$));
        $$.mainCircle.exit().remove();
    };
    c3_chart_internal_fn.redrawCircle = function(cx, cy, withTransition) {
        var selectedCircles = this.main.selectAll("." + CLASS.selectedCircle);
        return [ (withTransition ? this.mainCircle.transition() : this.mainCircle).style("opacity", this.opacityForCircle.bind(this)).style("fill", this.color).attr("cx", cx).attr("cy", cy), (withTransition ? selectedCircles.transition() : selectedCircles).attr("cx", cx).attr("cy", cy) ];
    };
    c3_chart_internal_fn.circleX = function(d) {
        return d.x || d.x === 0 ? this.x(d.x) : null;
    };
    c3_chart_internal_fn.updateCircleY = function() {
        var $$ = this, lineIndices, getPoints;
        if ($$.config.data_groups.length > 0) {
            lineIndices = $$.getShapeIndices($$.isLineType), getPoints = $$.generateGetLinePoints(lineIndices);
            $$.circleY = function(d, i) {
                return getPoints(d, i)[0][1];
            };
        } else {
            $$.circleY = function(d) {
                return $$.getYScale(d.id)(d.value);
            };
        }
    };
    c3_chart_internal_fn.getCircles = function(i, id) {
        var $$ = this;
        return (id ? $$.main.selectAll("." + CLASS.circles + $$.getTargetSelectorSuffix(id)) : $$.main).selectAll("." + CLASS.circle + (isValue(i) ? "-" + i : ""));
    };
    c3_chart_internal_fn.expandCircles = function(i, id, reset) {
        var $$ = this, r = $$.pointExpandedR.bind($$);
        if (reset) {
            $$.unexpandCircles();
        }
        $$.getCircles(i, id).classed(CLASS.EXPANDED, true).attr("r", r);
    };
    c3_chart_internal_fn.unexpandCircles = function(i) {
        var $$ = this, r = $$.pointR.bind($$);
        $$.getCircles(i).filter(function() {
            return $$.d3.select(this).classed(CLASS.EXPANDED);
        }).classed(CLASS.EXPANDED, false).attr("r", r);
    };
    c3_chart_internal_fn.pointR = function(d) {
        var $$ = this, config = $$.config;
        return $$.isStepType(d) ? 0 : isFunction(config.point_r) ? config.point_r(d) : config.point_r;
    };
    c3_chart_internal_fn.pointExpandedR = function(d) {
        var $$ = this, config = $$.config;
        return config.point_focus_expand_enabled ? config.point_focus_expand_r ? config.point_focus_expand_r : $$.pointR(d) * 1.75 : $$.pointR(d);
    };
    c3_chart_internal_fn.pointSelectR = function(d) {
        var $$ = this, config = $$.config;
        return config.point_select_r ? config.point_select_r : $$.pointR(d) * 4;
    };
    c3_chart_internal_fn.isWithinCircle = function(that, r) {
        var d3 = this.d3, mouse = d3.mouse(that), d3_this = d3.select(that), cx = +d3_this.attr("cx"), cy = +d3_this.attr("cy");
        return Math.sqrt(Math.pow(cx - mouse[0], 2) + Math.pow(cy - mouse[1], 2)) < r;
    };
    c3_chart_internal_fn.isWithinStep = function(that, y) {
        return Math.abs(y - this.d3.mouse(that)[1]) < 30;
    };
    c3_chart_internal_fn.initBar = function() {
        var $$ = this;
        $$.main.select("." + CLASS.chart).append("g").attr("class", CLASS.chartBars);
    };
    c3_chart_internal_fn.updateTargetsForBar = function(targets) {
        var $$ = this, config = $$.config, mainBarUpdate, mainBarEnter, classChartBar = $$.classChartBar.bind($$), classBars = $$.classBars.bind($$), classFocus = $$.classFocus.bind($$);
        mainBarUpdate = $$.main.select("." + CLASS.chartBars).selectAll("." + CLASS.chartBar).data(targets).attr("class", function(d) {
            return classChartBar(d) + classFocus(d);
        });
        mainBarEnter = mainBarUpdate.enter().append("g").attr("class", classChartBar).style("opacity", 0).style("pointer-events", "none");
        mainBarEnter.append("g").attr("class", classBars).style("cursor", function(d) {
            return config.data_selection_isselectable(d) ? "pointer" : null;
        });
    };
    c3_chart_internal_fn.updateBar = function(durationForExit) {
        var $$ = this, barData = $$.barData.bind($$), classBar = $$.classBar.bind($$), initialOpacity = $$.initialOpacity.bind($$), color = function(d) {
            return $$.color(d.id);
        };
        $$.mainBar = $$.main.selectAll("." + CLASS.bars).selectAll("." + CLASS.bar).data(barData);
        $$.mainBar.enter().append("path").attr("class", classBar).style("stroke", color).style("fill", color);
        $$.mainBar.style("opacity", initialOpacity);
        $$.mainBar.exit().transition().duration(durationForExit).style("opacity", 0).remove();
    };
    c3_chart_internal_fn.redrawBar = function(drawBar, withTransition) {
        return [ (withTransition ? this.mainBar.transition() : this.mainBar).attr("d", drawBar).style("fill", this.color).style("opacity", 1) ];
    };
    c3_chart_internal_fn.getBarW = function(axis, barTargetsNum) {
        var $$ = this, config = $$.config, w = typeof config.bar_width === "number" ? config.bar_width : barTargetsNum ? axis.tickInterval() * config.bar_width_ratio / barTargetsNum : 0;
        return config.bar_width_max && w > config.bar_width_max ? config.bar_width_max : w;
    };
    c3_chart_internal_fn.getBars = function(i, id) {
        var $$ = this;
        return (id ? $$.main.selectAll("." + CLASS.bars + $$.getTargetSelectorSuffix(id)) : $$.main).selectAll("." + CLASS.bar + (isValue(i) ? "-" + i : ""));
    };
    c3_chart_internal_fn.expandBars = function(i, id, reset) {
        var $$ = this;
        if (reset) {
            $$.unexpandBars();
        }
        $$.getBars(i, id).classed(CLASS.EXPANDED, true);
    };
    c3_chart_internal_fn.unexpandBars = function(i) {
        var $$ = this;
        $$.getBars(i).classed(CLASS.EXPANDED, false);
    };
    c3_chart_internal_fn.generateDrawBar = function(barIndices, isSub) {
        var $$ = this, config = $$.config, getPoints = $$.generateGetBarPoints(barIndices, isSub);
        return function(d, i) {
            var points = getPoints(d, i);
            var indexX = config.axis_rotated ? 1 : 0;
            var indexY = config.axis_rotated ? 0 : 1;
            var path = "M " + points[0][indexX] + "," + points[0][indexY] + " " + "L" + points[1][indexX] + "," + points[1][indexY] + " " + "L" + points[2][indexX] + "," + points[2][indexY] + " " + "L" + points[3][indexX] + "," + points[3][indexY] + " " + "z";
            return path;
        };
    };
    c3_chart_internal_fn.generateGetBarPoints = function(barIndices, isSub) {
        var $$ = this, axis = isSub ? $$.subXAxis : $$.xAxis, barTargetsNum = barIndices.__max__ + 1, barW = $$.getBarW(axis, barTargetsNum), barX = $$.getShapeX(barW, barTargetsNum, barIndices, !!isSub), barY = $$.getShapeY(!!isSub), barOffset = $$.getShapeOffset($$.isBarType, barIndices, !!isSub), yScale = isSub ? $$.getSubYScale : $$.getYScale;
        return function(d, i) {
            var y0 = yScale.call($$, d.id)(0), offset = barOffset(d, i) || y0, posX = barX(d), posY = barY(d);
            if ($$.config.axis_rotated) {
                if (0 < d.value && posY < y0 || d.value < 0 && y0 < posY) {
                    posY = y0;
                }
            }
            return [ [ posX, offset ], [ posX, posY - (y0 - offset) ], [ posX + barW, posY - (y0 - offset) ], [ posX + barW, offset ] ];
        };
    };
    c3_chart_internal_fn.isWithinBar = function(that) {
        var mouse = this.d3.mouse(that), box = that.getBoundingClientRect(), seg0 = that.pathSegList.getItem(0), seg1 = that.pathSegList.getItem(1), x = Math.min(seg0.x, seg1.x), y = Math.min(seg0.y, seg1.y), w = box.width, h = box.height, offset = 2, sx = x - offset, ex = x + w + offset, sy = y + h + offset, ey = y - offset;
        return sx < mouse[0] && mouse[0] < ex && ey < mouse[1] && mouse[1] < sy;
    };
    c3_chart_internal_fn.initText = function() {
        var $$ = this;
        $$.main.select("." + CLASS.chart).append("g").attr("class", CLASS.chartTexts);
        $$.mainText = $$.d3.selectAll([]);
    };
    c3_chart_internal_fn.updateTargetsForText = function(targets) {
        var $$ = this, mainTextUpdate, mainTextEnter, classChartText = $$.classChartText.bind($$), classTexts = $$.classTexts.bind($$), classFocus = $$.classFocus.bind($$);
        mainTextUpdate = $$.main.select("." + CLASS.chartTexts).selectAll("." + CLASS.chartText).data(targets).attr("class", function(d) {
            return classChartText(d) + classFocus(d);
        });
        mainTextEnter = mainTextUpdate.enter().append("g").attr("class", classChartText).style("opacity", 0).style("pointer-events", "none");
        mainTextEnter.append("g").attr("class", classTexts);
    };
    c3_chart_internal_fn.updateText = function(durationForExit) {
        var $$ = this, config = $$.config, barOrLineData = $$.barOrLineData.bind($$), classText = $$.classText.bind($$);
        $$.mainText = $$.main.selectAll("." + CLASS.texts).selectAll("." + CLASS.text).data(barOrLineData);
        $$.mainText.enter().append("text").attr("class", classText).attr("text-anchor", function(d) {
            return config.axis_rotated ? d.value < 0 ? "end" : "start" : "middle";
        }).style("stroke", "none").style("fill", function(d) {
            return $$.color(d);
        }).style("fill-opacity", 0);
        $$.mainText.text(function(d, i, j) {
            return $$.dataLabelFormat(d.id)(d.value, d.id, i, j);
        });
        $$.mainText.exit().transition().duration(durationForExit).style("fill-opacity", 0).remove();
    };
    c3_chart_internal_fn.redrawText = function(xForText, yForText, forFlow, withTransition) {
        return [ (withTransition ? this.mainText.transition() : this.mainText).attr("x", xForText).attr("y", yForText).style("fill", this.color).style("fill-opacity", forFlow ? 0 : this.opacityForText.bind(this)) ];
    };
    c3_chart_internal_fn.getTextRect = function(text, cls) {
        var dummy = this.d3.select("body").append("div").classed("c3", true), svg = dummy.append("svg").style("visibility", "hidden").style("position", "fixed").style("top", 0).style("left", 0), rect;
        svg.selectAll(".dummy").data([ text ]).enter().append("text").classed(cls ? cls : "", true).text(text).each(function() {
            rect = this.getBoundingClientRect();
        });
        dummy.remove();
        return rect;
    };
    c3_chart_internal_fn.generateXYForText = function(areaIndices, barIndices, lineIndices, forX) {
        var $$ = this, getAreaPoints = $$.generateGetAreaPoints(areaIndices, false), getBarPoints = $$.generateGetBarPoints(barIndices, false), getLinePoints = $$.generateGetLinePoints(lineIndices, false), getter = forX ? $$.getXForText : $$.getYForText;
        return function(d, i) {
            var getPoints = $$.isAreaType(d) ? getAreaPoints : $$.isBarType(d) ? getBarPoints : getLinePoints;
            return getter.call($$, getPoints(d, i), d, this);
        };
    };
    c3_chart_internal_fn.getXForText = function(points, d, textElement) {
        var $$ = this, box = textElement.getBoundingClientRect(), xPos, padding;
        if ($$.config.axis_rotated) {
            padding = $$.isBarType(d) ? 4 : 6;
            xPos = points[2][1] + padding * (d.value < 0 ? -1 : 1);
        } else {
            xPos = $$.hasType("bar") ? (points[2][0] + points[0][0]) / 2 : points[0][0];
        }
        if (d.value === null) {
            if (xPos > $$.width) {
                xPos = $$.width - box.width;
            } else if (xPos < 0) {
                xPos = 4;
            }
        }
        return xPos;
    };
    c3_chart_internal_fn.getYForText = function(points, d, textElement) {
        var $$ = this, box = textElement.getBoundingClientRect(), yPos;
        if ($$.config.axis_rotated) {
            yPos = (points[0][0] + points[2][0] + box.height * .6) / 2;
        } else {
            yPos = points[2][1];
            if (d.value < 0) {
                yPos += box.height;
                if ($$.isBarType(d) && $$.isSafari()) {
                    yPos -= 3;
                } else if (!$$.isBarType(d) && $$.isChrome()) {
                    yPos += 3;
                }
            } else {
                yPos += $$.isBarType(d) ? -3 : -6;
            }
        }
        if (d.value === null && !$$.config.axis_rotated) {
            if (yPos < box.height) {
                yPos = box.height;
            } else if (yPos > this.height) {
                yPos = this.height - 4;
            }
        }
        return yPos;
    };
    c3_chart_internal_fn.setTargetType = function(targetIds, type) {
        var $$ = this, config = $$.config;
        $$.mapToTargetIds(targetIds).forEach(function(id) {
            $$.withoutFadeIn[id] = type === config.data_types[id];
            config.data_types[id] = type;
        });
        if (!targetIds) {
            config.data_type = type;
        }
    };
    c3_chart_internal_fn.hasType = function(type, targets) {
        var $$ = this, types = $$.config.data_types, has = false;
        targets = targets || $$.data.targets;
        if (targets && targets.length) {
            targets.forEach(function(target) {
                var t = types[target.id];
                if (t && t.indexOf(type) >= 0 || !t && type === "line") {
                    has = true;
                }
            });
        } else if (Object.keys(types).length) {
            Object.keys(types).forEach(function(id) {
                if (types[id] === type) {
                    has = true;
                }
            });
        } else {
            has = $$.config.data_type === type;
        }
        return has;
    };
    c3_chart_internal_fn.hasArcType = function(targets) {
        return this.hasType("pie", targets) || this.hasType("donut", targets) || this.hasType("gauge", targets);
    };
    c3_chart_internal_fn.isLineType = function(d) {
        var config = this.config, id = isString(d) ? d : d.id;
        return !config.data_types[id] || [ "line", "spline", "area", "area-spline", "step", "area-step" ].indexOf(config.data_types[id]) >= 0;
    };
    c3_chart_internal_fn.isStepType = function(d) {
        var id = isString(d) ? d : d.id;
        return [ "step", "area-step" ].indexOf(this.config.data_types[id]) >= 0;
    };
    c3_chart_internal_fn.isSplineType = function(d) {
        var id = isString(d) ? d : d.id;
        return [ "spline", "area-spline" ].indexOf(this.config.data_types[id]) >= 0;
    };
    c3_chart_internal_fn.isAreaType = function(d) {
        var id = isString(d) ? d : d.id;
        return [ "area", "area-spline", "area-step" ].indexOf(this.config.data_types[id]) >= 0;
    };
    c3_chart_internal_fn.isBarType = function(d) {
        var id = isString(d) ? d : d.id;
        return this.config.data_types[id] === "bar";
    };
    c3_chart_internal_fn.isScatterType = function(d) {
        var id = isString(d) ? d : d.id;
        return this.config.data_types[id] === "scatter";
    };
    c3_chart_internal_fn.isPieType = function(d) {
        var id = isString(d) ? d : d.id;
        return this.config.data_types[id] === "pie";
    };
    c3_chart_internal_fn.isGaugeType = function(d) {
        var id = isString(d) ? d : d.id;
        return this.config.data_types[id] === "gauge";
    };
    c3_chart_internal_fn.isDonutType = function(d) {
        var id = isString(d) ? d : d.id;
        return this.config.data_types[id] === "donut";
    };
    c3_chart_internal_fn.isArcType = function(d) {
        return this.isPieType(d) || this.isDonutType(d) || this.isGaugeType(d);
    };
    c3_chart_internal_fn.lineData = function(d) {
        return this.isLineType(d) ? [ d ] : [];
    };
    c3_chart_internal_fn.arcData = function(d) {
        return this.isArcType(d.data) ? [ d ] : [];
    };
    c3_chart_internal_fn.barData = function(d) {
        return this.isBarType(d) ? d.values : [];
    };
    c3_chart_internal_fn.lineOrScatterData = function(d) {
        return this.isLineType(d) || this.isScatterType(d) ? d.values : [];
    };
    c3_chart_internal_fn.barOrLineData = function(d) {
        return this.isBarType(d) || this.isLineType(d) ? d.values : [];
    };
    c3_chart_internal_fn.initGrid = function() {
        var $$ = this, config = $$.config, d3 = $$.d3;
        $$.grid = $$.main.append("g").attr("clip-path", $$.clipPathForGrid).attr("class", CLASS.grid);
        if (config.grid_x_show) {
            $$.grid.append("g").attr("class", CLASS.xgrids);
        }
        if (config.grid_y_show) {
            $$.grid.append("g").attr("class", CLASS.ygrids);
        }
        if (config.grid_focus_show) {
            $$.grid.append("g").attr("class", CLASS.xgridFocus).append("line").attr("class", CLASS.xgridFocus);
        }
        $$.xgrid = d3.selectAll([]);
        if (!config.grid_lines_front) {
            $$.initGridLines();
        }
    };
    c3_chart_internal_fn.initGridLines = function() {
        var $$ = this, d3 = $$.d3;
        $$.gridLines = $$.main.append("g").attr("clip-path", $$.clipPathForGrid).attr("class", CLASS.grid + " " + CLASS.gridLines);
        $$.gridLines.append("g").attr("class", CLASS.xgridLines);
        $$.gridLines.append("g").attr("class", CLASS.ygridLines);
        $$.xgridLines = d3.selectAll([]);
    };
    c3_chart_internal_fn.updateXGrid = function(withoutUpdate) {
        var $$ = this, config = $$.config, d3 = $$.d3, xgridData = $$.generateGridData(config.grid_x_type, $$.x), tickOffset = $$.isCategorized() ? $$.xAxis.tickOffset() : 0;
        $$.xgridAttr = config.axis_rotated ? {
            x1: 0,
            x2: $$.width,
            y1: function(d) {
                return $$.x(d) - tickOffset;
            },
            y2: function(d) {
                return $$.x(d) - tickOffset;
            }
        } : {
            x1: function(d) {
                return $$.x(d) + tickOffset;
            },
            x2: function(d) {
                return $$.x(d) + tickOffset;
            },
            y1: 0,
            y2: $$.height
        };
        $$.xgrid = $$.main.select("." + CLASS.xgrids).selectAll("." + CLASS.xgrid).data(xgridData);
        $$.xgrid.enter().append("line").attr("class", CLASS.xgrid);
        if (!withoutUpdate) {
            $$.xgrid.attr($$.xgridAttr).style("opacity", function() {
                return +d3.select(this).attr(config.axis_rotated ? "y1" : "x1") === (config.axis_rotated ? $$.height : 0) ? 0 : 1;
            });
        }
        $$.xgrid.exit().remove();
    };
    c3_chart_internal_fn.updateYGrid = function() {
        var $$ = this, config = $$.config, gridValues = $$.yAxis.tickValues() || $$.y.ticks(config.grid_y_ticks);
        $$.ygrid = $$.main.select("." + CLASS.ygrids).selectAll("." + CLASS.ygrid).data(gridValues);
        $$.ygrid.enter().append("line").attr("class", CLASS.ygrid);
        $$.ygrid.attr("x1", config.axis_rotated ? $$.y : 0).attr("x2", config.axis_rotated ? $$.y : $$.width).attr("y1", config.axis_rotated ? 0 : $$.y).attr("y2", config.axis_rotated ? $$.height : $$.y);
        $$.ygrid.exit().remove();
        $$.smoothLines($$.ygrid, "grid");
    };
    c3_chart_internal_fn.gridTextAnchor = function(d) {
        return d.position ? d.position : "end";
    };
    c3_chart_internal_fn.gridTextDx = function(d) {
        return d.position === "start" ? 4 : d.position === "middle" ? 0 : -4;
    };
    c3_chart_internal_fn.xGridTextX = function(d) {
        return d.position === "start" ? -this.height : d.position === "middle" ? -this.height / 2 : 0;
    };
    c3_chart_internal_fn.yGridTextX = function(d) {
        return d.position === "start" ? 0 : d.position === "middle" ? this.width / 2 : this.width;
    };
    c3_chart_internal_fn.updateGrid = function(duration) {
        var $$ = this, main = $$.main, config = $$.config, xgridLine, ygridLine, yv;
        $$.grid.style("visibility", $$.hasArcType() ? "hidden" : "visible");
        main.select("line." + CLASS.xgridFocus).style("visibility", "hidden");
        if (config.grid_x_show) {
            $$.updateXGrid();
        }
        $$.xgridLines = main.select("." + CLASS.xgridLines).selectAll("." + CLASS.xgridLine).data(config.grid_x_lines);
        xgridLine = $$.xgridLines.enter().append("g").attr("class", function(d) {
            return CLASS.xgridLine + (d["class"] ? " " + d["class"] : "");
        });
        xgridLine.append("line").style("opacity", 0);
        xgridLine.append("text").attr("text-anchor", $$.gridTextAnchor).attr("transform", config.axis_rotated ? "" : "rotate(-90)").attr("dx", $$.gridTextDx).attr("dy", -5).style("opacity", 0);
        $$.xgridLines.exit().transition().duration(duration).style("opacity", 0).remove();
        if (config.grid_y_show) {
            $$.updateYGrid();
        }
        $$.ygridLines = main.select("." + CLASS.ygridLines).selectAll("." + CLASS.ygridLine).data(config.grid_y_lines);
        ygridLine = $$.ygridLines.enter().append("g").attr("class", function(d) {
            return CLASS.ygridLine + (d["class"] ? " " + d["class"] : "");
        });
        ygridLine.append("line").style("opacity", 0);
        ygridLine.append("text").attr("text-anchor", $$.gridTextAnchor).attr("transform", config.axis_rotated ? "rotate(-90)" : "").attr("dx", $$.gridTextDx).attr("dy", -5).style("opacity", 0);
        yv = $$.yv.bind($$);
        $$.ygridLines.select("line").transition().duration(duration).attr("x1", config.axis_rotated ? yv : 0).attr("x2", config.axis_rotated ? yv : $$.width).attr("y1", config.axis_rotated ? 0 : yv).attr("y2", config.axis_rotated ? $$.height : yv).style("opacity", 1);
        $$.ygridLines.select("text").transition().duration(duration).attr("x", config.axis_rotated ? $$.xGridTextX.bind($$) : $$.yGridTextX.bind($$)).attr("y", yv).text(function(d) {
            return d.text;
        }).style("opacity", 1);
        $$.ygridLines.exit().transition().duration(duration).style("opacity", 0).remove();
    };
    c3_chart_internal_fn.redrawGrid = function(withTransition) {
        var $$ = this, config = $$.config, xv = $$.xv.bind($$), lines = $$.xgridLines.select("line"), texts = $$.xgridLines.select("text");
        return [ (withTransition ? lines.transition() : lines).attr("x1", config.axis_rotated ? 0 : xv).attr("x2", config.axis_rotated ? $$.width : xv).attr("y1", config.axis_rotated ? xv : 0).attr("y2", config.axis_rotated ? xv : $$.height).style("opacity", 1), (withTransition ? texts.transition() : texts).attr("x", config.axis_rotated ? $$.yGridTextX.bind($$) : $$.xGridTextX.bind($$)).attr("y", xv).text(function(d) {
            return d.text;
        }).style("opacity", 1) ];
    };
    c3_chart_internal_fn.showXGridFocus = function(selectedData) {
        var $$ = this, config = $$.config, dataToShow = selectedData.filter(function(d) {
            return d && isValue(d.value);
        }), focusEl = $$.main.selectAll("line." + CLASS.xgridFocus), xx = $$.xx.bind($$);
        if (!config.tooltip_show) {
            return;
        }
        if ($$.hasType("scatter") || $$.hasArcType()) {
            return;
        }
        focusEl.style("visibility", "visible").data([ dataToShow[0] ]).attr(config.axis_rotated ? "y1" : "x1", xx).attr(config.axis_rotated ? "y2" : "x2", xx);
        $$.smoothLines(focusEl, "grid");
    };
    c3_chart_internal_fn.hideXGridFocus = function() {
        this.main.select("line." + CLASS.xgridFocus).style("visibility", "hidden");
    };
    c3_chart_internal_fn.updateXgridFocus = function() {
        var $$ = this, config = $$.config;
        $$.main.select("line." + CLASS.xgridFocus).attr("x1", config.axis_rotated ? 0 : -10).attr("x2", config.axis_rotated ? $$.width : -10).attr("y1", config.axis_rotated ? -10 : 0).attr("y2", config.axis_rotated ? -10 : $$.height);
    };
    c3_chart_internal_fn.generateGridData = function(type, scale) {
        var $$ = this, gridData = [], xDomain, firstYear, lastYear, i, tickNum = $$.main.select("." + CLASS.axisX).selectAll(".tick").size();
        if (type === "year") {
            xDomain = $$.getXDomain();
            firstYear = xDomain[0].getFullYear();
            lastYear = xDomain[1].getFullYear();
            for (i = firstYear; i <= lastYear; i++) {
                gridData.push(new Date(i + "-01-01 00:00:00"));
            }
        } else {
            gridData = scale.ticks(10);
            if (gridData.length > tickNum) {
                gridData = gridData.filter(function(d) {
                    return ("" + d).indexOf(".") < 0;
                });
            }
        }
        return gridData;
    };
    c3_chart_internal_fn.getGridFilterToRemove = function(params) {
        return params ? function(line) {
            var found = false;
            [].concat(params).forEach(function(param) {
                if ("value" in param && line.value === param.value || "class" in param && line["class"] === param["class"]) {
                    found = true;
                }
            });
            return found;
        } : function() {
            return true;
        };
    };
    c3_chart_internal_fn.removeGridLines = function(params, forX) {
        var $$ = this, config = $$.config, toRemove = $$.getGridFilterToRemove(params), toShow = function(line) {
            return !toRemove(line);
        }, classLines = forX ? CLASS.xgridLines : CLASS.ygridLines, classLine = forX ? CLASS.xgridLine : CLASS.ygridLine;
        $$.main.select("." + classLines).selectAll("." + classLine).filter(toRemove).transition().duration(config.transition_duration).style("opacity", 0).remove();
        if (forX) {
            config.grid_x_lines = config.grid_x_lines.filter(toShow);
        } else {
            config.grid_y_lines = config.grid_y_lines.filter(toShow);
        }
    };
    c3_chart_internal_fn.initTooltip = function() {
        var $$ = this, config = $$.config, i;
        $$.tooltip = $$.selectChart.style("position", "relative").append("div").attr("class", CLASS.tooltipContainer).style("position", "absolute").style("pointer-events", "none").style("display", "none");
        if (config.tooltip_init_show) {
            if ($$.isTimeSeries() && isString(config.tooltip_init_x)) {
                config.tooltip_init_x = $$.parseDate(config.tooltip_init_x);
                for (i = 0; i < $$.data.targets[0].values.length; i++) {
                    if ($$.data.targets[0].values[i].x - config.tooltip_init_x === 0) {
                        break;
                    }
                }
                config.tooltip_init_x = i;
            }
            $$.tooltip.html(config.tooltip_contents.call($$, $$.data.targets.map(function(d) {
                return $$.addName(d.values[config.tooltip_init_x]);
            }), $$.axis.getXAxisTickFormat(), $$.getYFormat($$.hasArcType()), $$.color));
            $$.tooltip.style("top", config.tooltip_init_position.top).style("left", config.tooltip_init_position.left).style("display", "block");
        }
    };
    c3_chart_internal_fn.getTooltipContent = function(d, defaultTitleFormat, defaultValueFormat, color) {
        var $$ = this, config = $$.config, titleFormat = config.tooltip_format_title || defaultTitleFormat, nameFormat = config.tooltip_format_name || function(name) {
            return name;
        }, valueFormat = config.tooltip_format_value || defaultValueFormat, text, i, title, value, name, bgcolor;
        for (i = 0; i < d.length; i++) {
            if (!(d[i] && (d[i].value || d[i].value === 0))) {
                continue;
            }
            if (!text) {
                title = titleFormat ? titleFormat(d[i].x) : d[i].x;
                text = "<table class='" + CLASS.tooltip + "'>" + (title || title === 0 ? "<tr><th colspan='2'>" + title + "</th></tr>" : "");
            }
            value = valueFormat(d[i].value, d[i].ratio, d[i].id, d[i].index);
            if (value !== undefined) {
                name = nameFormat(d[i].name, d[i].ratio, d[i].id, d[i].index);
                bgcolor = $$.levelColor ? $$.levelColor(d[i].value) : color(d[i].id);
                text += "<tr class='" + CLASS.tooltipName + "-" + d[i].id + "'>";
                text += "<td class='name'><span style='background-color:" + bgcolor + "'></span>" + name + "</td>";
                text += "<td class='value'>" + value + "</td>";
                text += "</tr>";
            }
        }
        return text + "</table>";
    };
    c3_chart_internal_fn.tooltipPosition = function(dataToShow, tWidth, tHeight, element) {
        var $$ = this, config = $$.config, d3 = $$.d3;
        var svgLeft, tooltipLeft, tooltipRight, tooltipTop, chartRight;
        var forArc = $$.hasArcType(), mouse = d3.mouse(element);
        if (forArc) {
            tooltipLeft = ($$.width - ($$.isLegendRight ? $$.getLegendWidth() : 0)) / 2 + mouse[0];
            tooltipTop = $$.height / 2 + mouse[1] + 20;
        } else {
            svgLeft = $$.getSvgLeft(true);
            if (config.axis_rotated) {
                tooltipLeft = svgLeft + mouse[0] + 100;
                tooltipRight = tooltipLeft + tWidth;
                chartRight = $$.currentWidth - $$.getCurrentPaddingRight();
                tooltipTop = $$.x(dataToShow[0].x) + 20;
            } else {
                tooltipLeft = svgLeft + $$.getCurrentPaddingLeft(true) + $$.x(dataToShow[0].x) + 20;
                tooltipRight = tooltipLeft + tWidth;
                chartRight = svgLeft + $$.currentWidth - $$.getCurrentPaddingRight();
                tooltipTop = mouse[1] + 15;
            }
            if (tooltipRight > chartRight) {
                tooltipLeft -= tooltipRight - chartRight + 20;
            }
            if (tooltipTop + tHeight > $$.currentHeight) {
                tooltipTop -= tHeight + 30;
            }
        }
        if (tooltipTop < 0) {
            tooltipTop = 0;
        }
        return {
            top: tooltipTop,
            left: tooltipLeft
        };
    };
    c3_chart_internal_fn.showTooltip = function(selectedData, element) {
        var $$ = this, config = $$.config;
        var tWidth, tHeight, position;
        var forArc = $$.hasArcType(), dataToShow = selectedData.filter(function(d) {
            return d && isValue(d.value);
        }), positionFunction = config.tooltip_position || c3_chart_internal_fn.tooltipPosition;
        if (dataToShow.length === 0 || !config.tooltip_show) {
            return;
        }
        $$.tooltip.html(config.tooltip_contents.call($$, selectedData, $$.axis.getXAxisTickFormat(), $$.getYFormat(forArc), $$.color)).style("display", "block");
        tWidth = $$.tooltip.property("offsetWidth");
        tHeight = $$.tooltip.property("offsetHeight");
        position = positionFunction.call(this, dataToShow, tWidth, tHeight, element);
        $$.tooltip.style("top", position.top + "px").style("left", position.left + "px");
    };
    c3_chart_internal_fn.hideTooltip = function() {
        this.tooltip.style("display", "none");
    };
    c3_chart_internal_fn.initLegend = function() {
        var $$ = this;
        $$.legendItemTextBox = {};
        $$.legendHasRendered = false;
        $$.legend = $$.svg.append("g").attr("transform", $$.getTranslate("legend"));
        if (!$$.config.legend_show) {
            $$.legend.style("visibility", "hidden");
            $$.hiddenLegendIds = $$.mapToIds($$.data.targets);
            return;
        }
        $$.updateLegendWithDefaults();
    };
    c3_chart_internal_fn.updateLegendWithDefaults = function() {
        var $$ = this;
        $$.updateLegend($$.mapToIds($$.data.targets), {
            withTransform: false,
            withTransitionForTransform: false,
            withTransition: false
        });
    };
    c3_chart_internal_fn.updateSizeForLegend = function(legendHeight, legendWidth) {
        var $$ = this, config = $$.config, insetLegendPosition = {
            top: $$.isLegendTop ? $$.getCurrentPaddingTop() + config.legend_inset_y + 5.5 : $$.currentHeight - legendHeight - $$.getCurrentPaddingBottom() - config.legend_inset_y,
            left: $$.isLegendLeft ? $$.getCurrentPaddingLeft() + config.legend_inset_x + .5 : $$.currentWidth - legendWidth - $$.getCurrentPaddingRight() - config.legend_inset_x + .5
        };
        $$.margin3 = {
            top: $$.isLegendRight ? 0 : $$.isLegendInset ? insetLegendPosition.top : $$.currentHeight - legendHeight,
            right: NaN,
            bottom: 0,
            left: $$.isLegendRight ? $$.currentWidth - legendWidth : $$.isLegendInset ? insetLegendPosition.left : 0
        };
    };
    c3_chart_internal_fn.transformLegend = function(withTransition) {
        var $$ = this;
        (withTransition ? $$.legend.transition() : $$.legend).attr("transform", $$.getTranslate("legend"));
    };
    c3_chart_internal_fn.updateLegendStep = function(step) {
        this.legendStep = step;
    };
    c3_chart_internal_fn.updateLegendItemWidth = function(w) {
        this.legendItemWidth = w;
    };
    c3_chart_internal_fn.updateLegendItemHeight = function(h) {
        this.legendItemHeight = h;
    };
    c3_chart_internal_fn.getLegendWidth = function() {
        var $$ = this;
        return $$.config.legend_show ? $$.isLegendRight || $$.isLegendInset ? $$.legendItemWidth * ($$.legendStep + 1) : $$.currentWidth : 0;
    };
    c3_chart_internal_fn.getLegendHeight = function() {
        var $$ = this, h = 0;
        if ($$.config.legend_show) {
            if ($$.isLegendRight) {
                h = $$.currentHeight;
            } else {
                h = Math.max(20, $$.legendItemHeight) * ($$.legendStep + 1);
            }
        }
        return h;
    };
    c3_chart_internal_fn.opacityForLegend = function(legendItem) {
        return legendItem.classed(CLASS.legendItemHidden) ? null : 1;
    };
    c3_chart_internal_fn.opacityForUnfocusedLegend = function(legendItem) {
        return legendItem.classed(CLASS.legendItemHidden) ? null : .3;
    };
    c3_chart_internal_fn.toggleFocusLegend = function(targetIds, focus) {
        var $$ = this;
        targetIds = $$.mapToTargetIds(targetIds);
        $$.legend.selectAll("." + CLASS.legendItem).filter(function(id) {
            return targetIds.indexOf(id) >= 0;
        }).classed(CLASS.legendItemFocused, focus).transition().duration(100).style("opacity", function() {
            var opacity = focus ? $$.opacityForLegend : $$.opacityForUnfocusedLegend;
            return opacity.call($$, $$.d3.select(this));
        });
    };
    c3_chart_internal_fn.revertLegend = function() {
        var $$ = this, d3 = $$.d3;
        $$.legend.selectAll("." + CLASS.legendItem).classed(CLASS.legendItemFocused, false).transition().duration(100).style("opacity", function() {
            return $$.opacityForLegend(d3.select(this));
        });
    };
    c3_chart_internal_fn.showLegend = function(targetIds) {
        var $$ = this, config = $$.config;
        if (!config.legend_show) {
            config.legend_show = true;
            $$.legend.style("visibility", "visible");
            if (!$$.legendHasRendered) {
                $$.updateLegendWithDefaults();
            }
        }
        $$.removeHiddenLegendIds(targetIds);
        $$.legend.selectAll($$.selectorLegends(targetIds)).style("visibility", "visible").transition().style("opacity", function() {
            return $$.opacityForLegend($$.d3.select(this));
        });
    };
    c3_chart_internal_fn.hideLegend = function(targetIds) {
        var $$ = this, config = $$.config;
        if (config.legend_show && isEmpty(targetIds)) {
            config.legend_show = false;
            $$.legend.style("visibility", "hidden");
        }
        $$.addHiddenLegendIds(targetIds);
        $$.legend.selectAll($$.selectorLegends(targetIds)).style("opacity", 0).style("visibility", "hidden");
    };
    c3_chart_internal_fn.clearLegendItemTextBoxCache = function() {
        this.legendItemTextBox = {};
    };
    c3_chart_internal_fn.updateLegend = function(targetIds, options, transitions) {
        var $$ = this, config = $$.config;
        var xForLegend, xForLegendText, xForLegendRect, yForLegend, yForLegendText, yForLegendRect;
        var paddingTop = 4, paddingRight = 10, maxWidth = 0, maxHeight = 0, posMin = 10, tileWidth = 15;
        var l, totalLength = 0, offsets = {}, widths = {}, heights = {}, margins = [ 0 ], steps = {}, step = 0;
        var withTransition, withTransitionForTransform;
        var texts, rects, tiles, background;
        options = options || {};
        withTransition = getOption(options, "withTransition", true);
        withTransitionForTransform = getOption(options, "withTransitionForTransform", true);
        function getTextBox(textElement, id) {
            if (!$$.legendItemTextBox[id]) {
                $$.legendItemTextBox[id] = $$.getTextRect(textElement.textContent, CLASS.legendItem);
            }
            return $$.legendItemTextBox[id];
        }
        function updatePositions(textElement, id, index) {
            var reset = index === 0, isLast = index === targetIds.length - 1, box = getTextBox(textElement, id), itemWidth = box.width + tileWidth + (isLast && !($$.isLegendRight || $$.isLegendInset) ? 0 : paddingRight), itemHeight = box.height + paddingTop, itemLength = $$.isLegendRight || $$.isLegendInset ? itemHeight : itemWidth, areaLength = $$.isLegendRight || $$.isLegendInset ? $$.getLegendHeight() : $$.getLegendWidth(), margin, maxLength;
            function updateValues(id, withoutStep) {
                if (!withoutStep) {
                    margin = (areaLength - totalLength - itemLength) / 2;
                    if (margin < posMin) {
                        margin = (areaLength - itemLength) / 2;
                        totalLength = 0;
                        step++;
                    }
                }
                steps[id] = step;
                margins[step] = $$.isLegendInset ? 10 : margin;
                offsets[id] = totalLength;
                totalLength += itemLength;
            }
            if (reset) {
                totalLength = 0;
                step = 0;
                maxWidth = 0;
                maxHeight = 0;
            }
            if (config.legend_show && !$$.isLegendToShow(id)) {
                widths[id] = heights[id] = steps[id] = offsets[id] = 0;
                return;
            }
            widths[id] = itemWidth;
            heights[id] = itemHeight;
            if (!maxWidth || itemWidth >= maxWidth) {
                maxWidth = itemWidth;
            }
            if (!maxHeight || itemHeight >= maxHeight) {
                maxHeight = itemHeight;
            }
            maxLength = $$.isLegendRight || $$.isLegendInset ? maxHeight : maxWidth;
            if (config.legend_equally) {
                Object.keys(widths).forEach(function(id) {
                    widths[id] = maxWidth;
                });
                Object.keys(heights).forEach(function(id) {
                    heights[id] = maxHeight;
                });
                margin = (areaLength - maxLength * targetIds.length) / 2;
                if (margin < posMin) {
                    totalLength = 0;
                    step = 0;
                    targetIds.forEach(function(id) {
                        updateValues(id);
                    });
                } else {
                    updateValues(id, true);
                }
            } else {
                updateValues(id);
            }
        }
        if ($$.isLegendInset) {
            step = config.legend_inset_step ? config.legend_inset_step : targetIds.length;
            $$.updateLegendStep(step);
        }
        if ($$.isLegendRight) {
            xForLegend = function(id) {
                return maxWidth * steps[id];
            };
            yForLegend = function(id) {
                return margins[steps[id]] + offsets[id];
            };
        } else if ($$.isLegendInset) {
            xForLegend = function(id) {
                return maxWidth * steps[id] + 10;
            };
            yForLegend = function(id) {
                return margins[steps[id]] + offsets[id];
            };
        } else {
            xForLegend = function(id) {
                return margins[steps[id]] + offsets[id];
            };
            yForLegend = function(id) {
                return maxHeight * steps[id];
            };
        }
        xForLegendText = function(id, i) {
            return xForLegend(id, i) + 14;
        };
        yForLegendText = function(id, i) {
            return yForLegend(id, i) + 9;
        };
        xForLegendRect = function(id, i) {
            return xForLegend(id, i);
        };
        yForLegendRect = function(id, i) {
            return yForLegend(id, i) - 5;
        };
        l = $$.legend.selectAll("." + CLASS.legendItem).data(targetIds).enter().append("g").attr("class", function(id) {
            return $$.generateClass(CLASS.legendItem, id);
        }).style("visibility", function(id) {
            return $$.isLegendToShow(id) ? "visible" : "hidden";
        }).style("cursor", "pointer").on("click", function(id) {
            if (config.legend_item_onclick) {
                config.legend_item_onclick.call($$, id);
            } else {
                if ($$.d3.event.altKey) {
                    $$.api.hide();
                    $$.api.show(id);
                } else {
                    $$.api.toggle(id);
                    $$.isTargetToShow(id) ? $$.api.focus(id) : $$.api.revert();
                }
            }
        }).on("mouseover", function(id) {
            $$.d3.select(this).classed(CLASS.legendItemFocused, true);
            if (!$$.transiting && $$.isTargetToShow(id)) {
                $$.api.focus(id);
            }
            if (config.legend_item_onmouseover) {
                config.legend_item_onmouseover.call($$, id);
            }
        }).on("mouseout", function(id) {
            $$.d3.select(this).classed(CLASS.legendItemFocused, false);
            $$.api.revert();
            if (config.legend_item_onmouseout) {
                config.legend_item_onmouseout.call($$, id);
            }
        });
        l.append("text").text(function(id) {
            return isDefined(config.data_names[id]) ? config.data_names[id] : id;
        }).each(function(id, i) {
            updatePositions(this, id, i);
        }).style("pointer-events", "none").attr("x", $$.isLegendRight || $$.isLegendInset ? xForLegendText : -200).attr("y", $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendText);
        l.append("rect").attr("class", CLASS.legendItemEvent).style("fill-opacity", 0).attr("x", $$.isLegendRight || $$.isLegendInset ? xForLegendRect : -200).attr("y", $$.isLegendRight || $$.isLegendInset ? -200 : yForLegendRect);
        l.append("rect").attr("class", CLASS.legendItemTile).style("pointer-events", "none").style("fill", $$.color).attr("x", $$.isLegendRight || $$.isLegendInset ? xForLegendText : -200).attr("y", $$.isLegendRight || $$.isLegendInset ? -200 : yForLegend).attr("width", 10).attr("height", 10);
        background = $$.legend.select("." + CLASS.legendBackground + " rect");
        if ($$.isLegendInset && maxWidth > 0 && background.size() === 0) {
            background = $$.legend.insert("g", "." + CLASS.legendItem).attr("class", CLASS.legendBackground).append("rect");
        }
        texts = $$.legend.selectAll("text").data(targetIds).text(function(id) {
            return isDefined(config.data_names[id]) ? config.data_names[id] : id;
        }).each(function(id, i) {
            updatePositions(this, id, i);
        });
        (withTransition ? texts.transition() : texts).attr("x", xForLegendText).attr("y", yForLegendText);
        rects = $$.legend.selectAll("rect." + CLASS.legendItemEvent).data(targetIds);
        (withTransition ? rects.transition() : rects).attr("width", function(id) {
            return widths[id];
        }).attr("height", function(id) {
            return heights[id];
        }).attr("x", xForLegendRect).attr("y", yForLegendRect);
        tiles = $$.legend.selectAll("rect." + CLASS.legendItemTile).data(targetIds);
        (withTransition ? tiles.transition() : tiles).style("fill", $$.color).attr("x", xForLegend).attr("y", yForLegend);
        if (background) {
            (withTransition ? background.transition() : background).attr("height", $$.getLegendHeight() - 12).attr("width", maxWidth * (step + 1) + 10);
        }
        $$.legend.selectAll("." + CLASS.legendItem).classed(CLASS.legendItemHidden, function(id) {
            return !$$.isTargetToShow(id);
        });
        $$.updateLegendItemWidth(maxWidth);
        $$.updateLegendItemHeight(maxHeight);
        $$.updateLegendStep(step);
        $$.updateSizes();
        $$.updateScales();
        $$.updateSvgSize();
        $$.transformAll(withTransitionForTransform, transitions);
        $$.legendHasRendered = true;
    };
    function Axis(owner) {
        API.call(this, owner);
    }
    inherit(API, Axis);
    Axis.prototype.init = function init() {
        var $$ = this.owner, config = $$.config, main = $$.main;
        $$.axes.x = main.append("g").attr("class", CLASS.axis + " " + CLASS.axisX).attr("clip-path", $$.clipPathForXAxis).attr("transform", $$.getTranslate("x")).style("visibility", config.axis_x_show ? "visible" : "hidden");
        $$.axes.x.append("text").attr("class", CLASS.axisXLabel).attr("transform", config.axis_rotated ? "rotate(-90)" : "").style("text-anchor", this.textAnchorForXAxisLabel.bind(this));
        $$.axes.y = main.append("g").attr("class", CLASS.axis + " " + CLASS.axisY).attr("clip-path", config.axis_y_inner ? "" : $$.clipPathForYAxis).attr("transform", $$.getTranslate("y")).style("visibility", config.axis_y_show ? "visible" : "hidden");
        $$.axes.y.append("text").attr("class", CLASS.axisYLabel).attr("transform", config.axis_rotated ? "" : "rotate(-90)").style("text-anchor", this.textAnchorForYAxisLabel.bind(this));
        $$.axes.y2 = main.append("g").attr("class", CLASS.axis + " " + CLASS.axisY2).attr("transform", $$.getTranslate("y2")).style("visibility", config.axis_y2_show ? "visible" : "hidden");
        $$.axes.y2.append("text").attr("class", CLASS.axisY2Label).attr("transform", config.axis_rotated ? "" : "rotate(-90)").style("text-anchor", this.textAnchorForY2AxisLabel.bind(this));
    };
    Axis.prototype.getXAxis = function getXAxis(scale, orient, tickFormat, tickValues, withOuterTick, withoutTransition, withoutRotateTickText) {
        var $$ = this.owner, config = $$.config, axisParams = {
            isCategory: $$.isCategorized(),
            withOuterTick: withOuterTick,
            tickMultiline: config.axis_x_tick_multiline,
            tickWidth: config.axis_x_tick_width,
            tickTextRotate: withoutRotateTickText ? 0 : config.axis_x_tick_rotate,
            withoutTransition: withoutTransition
        }, axis = c3_axis($$.d3, axisParams).scale(scale).orient(orient);
        if ($$.isTimeSeries() && tickValues) {
            tickValues = tickValues.map(function(v) {
                return $$.parseDate(v);
            });
        }
        axis.tickFormat(tickFormat).tickValues(tickValues);
        if ($$.isCategorized()) {
            axis.tickCentered(config.axis_x_tick_centered);
            if (isEmpty(config.axis_x_tick_culling)) {
                config.axis_x_tick_culling = false;
            }
        }
        return axis;
    };
    Axis.prototype.updateXAxisTickValues = function updateXAxisTickValues(targets, axis) {
        var $$ = this.owner, config = $$.config, tickValues;
        if (config.axis_x_tick_fit || config.axis_x_tick_count) {
            tickValues = this.generateTickValues($$.mapTargetsToUniqueXs(targets), config.axis_x_tick_count, $$.isTimeSeries());
        }
        if (axis) {
            axis.tickValues(tickValues);
        } else {
            $$.xAxis.tickValues(tickValues);
            $$.subXAxis.tickValues(tickValues);
        }
        return tickValues;
    };
    Axis.prototype.getYAxis = function getYAxis(scale, orient, tickFormat, tickValues, withOuterTick, withoutTransition) {
        var axisParams = {
            withOuterTick: withOuterTick,
            withoutTransition: withoutTransition
        }, $$ = this.owner, d3 = $$.d3, config = $$.config, axis = c3_axis(d3, axisParams).scale(scale).orient(orient).tickFormat(tickFormat);
        if ($$.isTimeSeriesY()) {
            axis.ticks(d3.time[config.axis_y_tick_time_value], config.axis_y_tick_time_interval);
        } else {
            axis.tickValues(tickValues);
        }
        return axis;
    };
    Axis.prototype.getId = function getId(id) {
        var config = this.owner.config;
        return id in config.data_axes ? config.data_axes[id] : "y";
    };
    Axis.prototype.getXAxisTickFormat = function getXAxisTickFormat() {
        var $$ = this.owner, config = $$.config, format = $$.isTimeSeries() ? $$.defaultAxisTimeFormat : $$.isCategorized() ? $$.categoryName : function(v) {
            return v < 0 ? v.toFixed(0) : v;
        };
        if (config.axis_x_tick_format) {
            if (isFunction(config.axis_x_tick_format)) {
                format = config.axis_x_tick_format;
            } else if ($$.isTimeSeries()) {
                format = function(date) {
                    return date ? $$.axisTimeFormat(config.axis_x_tick_format)(date) : "";
                };
            }
        }
        return isFunction(format) ? function(v) {
            return format.call($$, v);
        } : format;
    };
    Axis.prototype.getTickValues = function getTickValues(tickValues, axis) {
        return tickValues ? tickValues : axis ? axis.tickValues() : undefined;
    };
    Axis.prototype.getXAxisTickValues = function getXAxisTickValues() {
        return this.getTickValues(this.owner.config.axis_x_tick_values, this.owner.xAxis);
    };
    Axis.prototype.getYAxisTickValues = function getYAxisTickValues() {
        return this.getTickValues(this.owner.config.axis_y_tick_values, this.owner.yAxis);
    };
    Axis.prototype.getY2AxisTickValues = function getY2AxisTickValues() {
        return this.getTickValues(this.owner.config.axis_y2_tick_values, this.owner.y2Axis);
    };
    Axis.prototype.getLabelOptionByAxisId = function getLabelOptionByAxisId(axisId) {
        var $$ = this.owner, config = $$.config, option;
        if (axisId === "y") {
            option = config.axis_y_label;
        } else if (axisId === "y2") {
            option = config.axis_y2_label;
        } else if (axisId === "x") {
            option = config.axis_x_label;
        }
        return option;
    };
    Axis.prototype.getLabelText = function getLabelText(axisId) {
        var option = this.getLabelOptionByAxisId(axisId);
        return isString(option) ? option : option ? option.text : null;
    };
    Axis.prototype.setLabelText = function setLabelText(axisId, text) {
        var $$ = this.owner, config = $$.config, option = this.getLabelOptionByAxisId(axisId);
        if (isString(option)) {
            if (axisId === "y") {
                config.axis_y_label = text;
            } else if (axisId === "y2") {
                config.axis_y2_label = text;
            } else if (axisId === "x") {
                config.axis_x_label = text;
            }
        } else if (option) {
            option.text = text;
        }
    };
    Axis.prototype.getLabelPosition = function getLabelPosition(axisId, defaultPosition) {
        var option = this.getLabelOptionByAxisId(axisId), position = option && typeof option === "object" && option.position ? option.position : defaultPosition;
        return {
            isInner: position.indexOf("inner") >= 0,
            isOuter: position.indexOf("outer") >= 0,
            isLeft: position.indexOf("left") >= 0,
            isCenter: position.indexOf("center") >= 0,
            isRight: position.indexOf("right") >= 0,
            isTop: position.indexOf("top") >= 0,
            isMiddle: position.indexOf("middle") >= 0,
            isBottom: position.indexOf("bottom") >= 0
        };
    };
    Axis.prototype.getXAxisLabelPosition = function getXAxisLabelPosition() {
        return this.getLabelPosition("x", this.owner.config.axis_rotated ? "inner-top" : "inner-right");
    };
    Axis.prototype.getYAxisLabelPosition = function getYAxisLabelPosition() {
        return this.getLabelPosition("y", this.owner.config.axis_rotated ? "inner-right" : "inner-top");
    };
    Axis.prototype.getY2AxisLabelPosition = function getY2AxisLabelPosition() {
        return this.getLabelPosition("y2", this.owner.config.axis_rotated ? "inner-right" : "inner-top");
    };
    Axis.prototype.getLabelPositionById = function getLabelPositionById(id) {
        return id === "y2" ? this.getY2AxisLabelPosition() : id === "y" ? this.getYAxisLabelPosition() : this.getXAxisLabelPosition();
    };
    Axis.prototype.textForXAxisLabel = function textForXAxisLabel() {
        return this.getLabelText("x");
    };
    Axis.prototype.textForYAxisLabel = function textForYAxisLabel() {
        return this.getLabelText("y");
    };
    Axis.prototype.textForY2AxisLabel = function textForY2AxisLabel() {
        return this.getLabelText("y2");
    };
    Axis.prototype.xForAxisLabel = function xForAxisLabel(forHorizontal, position) {
        var $$ = this.owner;
        if (forHorizontal) {
            return position.isLeft ? 0 : position.isCenter ? $$.width / 2 : $$.width;
        } else {
            return position.isBottom ? -$$.height : position.isMiddle ? -$$.height / 2 : 0;
        }
    };
    Axis.prototype.dxForAxisLabel = function dxForAxisLabel(forHorizontal, position) {
        if (forHorizontal) {
            return position.isLeft ? "0.5em" : position.isRight ? "-0.5em" : "0";
        } else {
            return position.isTop ? "-0.5em" : position.isBottom ? "0.5em" : "0";
        }
    };
    Axis.prototype.textAnchorForAxisLabel = function textAnchorForAxisLabel(forHorizontal, position) {
        if (forHorizontal) {
            return position.isLeft ? "start" : position.isCenter ? "middle" : "end";
        } else {
            return position.isBottom ? "start" : position.isMiddle ? "middle" : "end";
        }
    };
    Axis.prototype.xForXAxisLabel = function xForXAxisLabel() {
        return this.xForAxisLabel(!this.owner.config.axis_rotated, this.getXAxisLabelPosition());
    };
    Axis.prototype.xForYAxisLabel = function xForYAxisLabel() {
        return this.xForAxisLabel(this.owner.config.axis_rotated, this.getYAxisLabelPosition());
    };
    Axis.prototype.xForY2AxisLabel = function xForY2AxisLabel() {
        return this.xForAxisLabel(this.owner.config.axis_rotated, this.getY2AxisLabelPosition());
    };
    Axis.prototype.dxForXAxisLabel = function dxForXAxisLabel() {
        return this.dxForAxisLabel(!this.owner.config.axis_rotated, this.getXAxisLabelPosition());
    };
    Axis.prototype.dxForYAxisLabel = function dxForYAxisLabel() {
        return this.dxForAxisLabel(this.owner.config.axis_rotated, this.getYAxisLabelPosition());
    };
    Axis.prototype.dxForY2AxisLabel = function dxForY2AxisLabel() {
        return this.dxForAxisLabel(this.owner.config.axis_rotated, this.getY2AxisLabelPosition());
    };
    Axis.prototype.dyForXAxisLabel = function dyForXAxisLabel() {
        var $$ = this.owner, config = $$.config, position = this.getXAxisLabelPosition();
        if (config.axis_rotated) {
            return position.isInner ? "1.2em" : -25 - this.getMaxTickWidth("x");
        } else {
            return position.isInner ? "-0.5em" : config.axis_x_height ? config.axis_x_height - 10 : "3em";
        }
    };
    Axis.prototype.dyForYAxisLabel = function dyForYAxisLabel() {
        var $$ = this.owner, position = this.getYAxisLabelPosition();
        if ($$.config.axis_rotated) {
            return position.isInner ? "-0.5em" : "3em";
        } else {
            return position.isInner ? "1.2em" : -10 - ($$.config.axis_y_inner ? 0 : this.getMaxTickWidth("y") + 10);
        }
    };
    Axis.prototype.dyForY2AxisLabel = function dyForY2AxisLabel() {
        var $$ = this.owner, position = this.getY2AxisLabelPosition();
        if ($$.config.axis_rotated) {
            return position.isInner ? "1.2em" : "-2.2em";
        } else {
            return position.isInner ? "-0.5em" : 15 + ($$.config.axis_y2_inner ? 0 : this.getMaxTickWidth("y2") + 15);
        }
    };
    Axis.prototype.textAnchorForXAxisLabel = function textAnchorForXAxisLabel() {
        var $$ = this.owner;
        return this.textAnchorForAxisLabel(!$$.config.axis_rotated, this.getXAxisLabelPosition());
    };
    Axis.prototype.textAnchorForYAxisLabel = function textAnchorForYAxisLabel() {
        var $$ = this.owner;
        return this.textAnchorForAxisLabel($$.config.axis_rotated, this.getYAxisLabelPosition());
    };
    Axis.prototype.textAnchorForY2AxisLabel = function textAnchorForY2AxisLabel() {
        var $$ = this.owner;
        return this.textAnchorForAxisLabel($$.config.axis_rotated, this.getY2AxisLabelPosition());
    };
    Axis.prototype.getMaxTickWidth = function getMaxTickWidth(id, withoutRecompute) {
        var $$ = this.owner, config = $$.config, maxWidth = 0, targetsToShow, scale, axis, dummy, svg;
        if (withoutRecompute && $$.currentMaxTickWidths[id]) {
            return $$.currentMaxTickWidths[id];
        }
        if ($$.svg) {
            targetsToShow = $$.filterTargetsToShow($$.data.targets);
            if (id === "y") {
                scale = $$.y.copy().domain($$.getYDomain(targetsToShow, "y"));
                axis = this.getYAxis(scale, $$.yOrient, config.axis_y_tick_format, $$.yAxisTickValues, false, true);
            } else if (id === "y2") {
                scale = $$.y2.copy().domain($$.getYDomain(targetsToShow, "y2"));
                axis = this.getYAxis(scale, $$.y2Orient, config.axis_y2_tick_format, $$.y2AxisTickValues, false, true);
            } else {
                scale = $$.x.copy().domain($$.getXDomain(targetsToShow));
                axis = this.getXAxis(scale, $$.xOrient, $$.xAxisTickFormat, $$.xAxisTickValues, false, true, true);
                this.updateXAxisTickValues(targetsToShow, axis);
            }
            dummy = $$.d3.select("body").append("div").classed("c3", true);
            svg = dummy.append("svg").style("visibility", "hidden").style("position", "fixed").style("top", 0).style("left", 0), 
            svg.append("g").call(axis).each(function() {
                $$.d3.select(this).selectAll("text").each(function() {
                    var box = this.getBoundingClientRect();
                    if (maxWidth < box.width) {
                        maxWidth = box.width;
                    }
                });
                dummy.remove();
            });
        }
        $$.currentMaxTickWidths[id] = maxWidth <= 0 ? $$.currentMaxTickWidths[id] : maxWidth;
        return $$.currentMaxTickWidths[id];
    };
    Axis.prototype.updateLabels = function updateLabels(withTransition) {
        var $$ = this.owner;
        var axisXLabel = $$.main.select("." + CLASS.axisX + " ." + CLASS.axisXLabel), axisYLabel = $$.main.select("." + CLASS.axisY + " ." + CLASS.axisYLabel), axisY2Label = $$.main.select("." + CLASS.axisY2 + " ." + CLASS.axisY2Label);
        (withTransition ? axisXLabel.transition() : axisXLabel).attr("x", this.xForXAxisLabel.bind(this)).attr("dx", this.dxForXAxisLabel.bind(this)).attr("dy", this.dyForXAxisLabel.bind(this)).text(this.textForXAxisLabel.bind(this));
        (withTransition ? axisYLabel.transition() : axisYLabel).attr("x", this.xForYAxisLabel.bind(this)).attr("dx", this.dxForYAxisLabel.bind(this)).attr("dy", this.dyForYAxisLabel.bind(this)).text(this.textForYAxisLabel.bind(this));
        (withTransition ? axisY2Label.transition() : axisY2Label).attr("x", this.xForY2AxisLabel.bind(this)).attr("dx", this.dxForY2AxisLabel.bind(this)).attr("dy", this.dyForY2AxisLabel.bind(this)).text(this.textForY2AxisLabel.bind(this));
    };
    Axis.prototype.getPadding = function getPadding(padding, key, defaultValue, domainLength) {
        if (!isValue(padding[key])) {
            return defaultValue;
        }
        if (padding.unit === "ratio") {
            return padding[key] * domainLength;
        }
        return this.convertPixelsToAxisPadding(padding[key], domainLength);
    };
    Axis.prototype.convertPixelsToAxisPadding = function convertPixelsToAxisPadding(pixels, domainLength) {
        var $$ = this.owner, length = $$.config.axis_rotated ? $$.width : $$.height;
        return domainLength * (pixels / length);
    };
    Axis.prototype.generateTickValues = function generateTickValues(values, tickCount, forTimeSeries) {
        var tickValues = values, targetCount, start, end, count, interval, i, tickValue;
        if (tickCount) {
            targetCount = isFunction(tickCount) ? tickCount() : tickCount;
            if (targetCount === 1) {
                tickValues = [ values[0] ];
            } else if (targetCount === 2) {
                tickValues = [ values[0], values[values.length - 1] ];
            } else if (targetCount > 2) {
                count = targetCount - 2;
                start = values[0];
                end = values[values.length - 1];
                interval = (end - start) / (count + 1);
                tickValues = [ start ];
                for (i = 0; i < count; i++) {
                    tickValue = +start + interval * (i + 1);
                    tickValues.push(forTimeSeries ? new Date(tickValue) : tickValue);
                }
                tickValues.push(end);
            }
        }
        if (!forTimeSeries) {
            tickValues = tickValues.sort(function(a, b) {
                return a - b;
            });
        }
        return tickValues;
    };
    Axis.prototype.generateTransitions = function generateTransitions(duration) {
        var $$ = this.owner, axes = $$.axes;
        return {
            axisX: duration ? axes.x.transition().duration(duration) : axes.x,
            axisY: duration ? axes.y.transition().duration(duration) : axes.y,
            axisY2: duration ? axes.y2.transition().duration(duration) : axes.y2,
            axisSubX: duration ? axes.subx.transition().duration(duration) : axes.subx
        };
    };
    Axis.prototype.redraw = function redraw(transitions, isHidden) {
        var $$ = this.owner;
        $$.axes.x.style("opacity", isHidden ? 0 : 1);
        $$.axes.y.style("opacity", isHidden ? 0 : 1);
        $$.axes.y2.style("opacity", isHidden ? 0 : 1);
        $$.axes.subx.style("opacity", isHidden ? 0 : 1);
        transitions.axisX.call($$.xAxis);
        transitions.axisY.call($$.yAxis);
        transitions.axisY2.call($$.y2Axis);
        transitions.axisSubX.call($$.subXAxis);
    };
    c3_chart_internal_fn.getClipPath = function(id) {
        var isIE9 = window.navigator.appVersion.toLowerCase().indexOf("msie 9.") >= 0;
        return "url(" + (isIE9 ? "" : document.URL.split("#")[0]) + "#" + id + ")";
    };
    c3_chart_internal_fn.appendClip = function(parent, id) {
        return parent.append("clipPath").attr("id", id).append("rect");
    };
    c3_chart_internal_fn.getAxisClipX = function(forHorizontal) {
        var left = Math.max(30, this.margin.left);
        return forHorizontal ? -(1 + left) : -(left - 1);
    };
    c3_chart_internal_fn.getAxisClipY = function(forHorizontal) {
        return forHorizontal ? -20 : -this.margin.top;
    };
    c3_chart_internal_fn.getXAxisClipX = function() {
        var $$ = this;
        return $$.getAxisClipX(!$$.config.axis_rotated);
    };
    c3_chart_internal_fn.getXAxisClipY = function() {
        var $$ = this;
        return $$.getAxisClipY(!$$.config.axis_rotated);
    };
    c3_chart_internal_fn.getYAxisClipX = function() {
        var $$ = this;
        return $$.config.axis_y_inner ? -1 : $$.getAxisClipX($$.config.axis_rotated);
    };
    c3_chart_internal_fn.getYAxisClipY = function() {
        var $$ = this;
        return $$.getAxisClipY($$.config.axis_rotated);
    };
    c3_chart_internal_fn.getAxisClipWidth = function(forHorizontal) {
        var $$ = this, left = Math.max(30, $$.margin.left), right = Math.max(30, $$.margin.right);
        return forHorizontal ? $$.width + 2 + left + right : $$.margin.left + 20;
    };
    c3_chart_internal_fn.getAxisClipHeight = function(forHorizontal) {
        return (forHorizontal ? this.margin.bottom : this.margin.top + this.height) + 20;
    };
    c3_chart_internal_fn.getXAxisClipWidth = function() {
        var $$ = this;
        return $$.getAxisClipWidth(!$$.config.axis_rotated);
    };
    c3_chart_internal_fn.getXAxisClipHeight = function() {
        var $$ = this;
        return $$.getAxisClipHeight(!$$.config.axis_rotated);
    };
    c3_chart_internal_fn.getYAxisClipWidth = function() {
        var $$ = this;
        return $$.getAxisClipWidth($$.config.axis_rotated) + ($$.config.axis_y_inner ? 20 : 0);
    };
    c3_chart_internal_fn.getYAxisClipHeight = function() {
        var $$ = this;
        return $$.getAxisClipHeight($$.config.axis_rotated);
    };
    c3_chart_internal_fn.initPie = function() {
        var $$ = this, d3 = $$.d3, config = $$.config;
        $$.pie = d3.layout.pie().value(function(d) {
            return d.values.reduce(function(a, b) {
                return a + b.value;
            }, 0);
        });
        if (!config.data_order) {
            $$.pie.sort(null);
        }
    };
    c3_chart_internal_fn.updateRadius = function() {
        var $$ = this, config = $$.config, w = config.gauge_width || config.donut_width;
        $$.radiusExpanded = Math.min($$.arcWidth, $$.arcHeight) / 2;
        $$.radius = $$.radiusExpanded * .95;
        $$.innerRadiusRatio = w ? ($$.radius - w) / $$.radius : .6;
        $$.innerRadius = $$.hasType("donut") || $$.hasType("gauge") ? $$.radius * $$.innerRadiusRatio : 0;
    };
    c3_chart_internal_fn.updateArc = function() {
        var $$ = this;
        $$.svgArc = $$.getSvgArc();
        $$.svgArcExpanded = $$.getSvgArcExpanded();
        $$.svgArcExpandedSub = $$.getSvgArcExpanded(.98);
    };
    c3_chart_internal_fn.updateAngle = function(d) {
        var $$ = this, config = $$.config, found = false, index = 0, gMin = config.gauge_min, gMax = config.gauge_max, gTic, gValue;
        $$.pie($$.filterTargetsToShow($$.data.targets)).forEach(function(t) {
            if (!found && t.data.id === d.data.id) {
                found = true;
                d = t;
                d.index = index;
            }
            index++;
        });
        if (isNaN(d.startAngle)) {
            d.startAngle = 0;
        }
        if (isNaN(d.endAngle)) {
            d.endAngle = d.startAngle;
        }
        if ($$.isGaugeType(d.data)) {
            gTic = Math.PI / (gMax - gMin);
            gValue = d.value < gMin ? 0 : d.value < gMax ? d.value - gMin : gMax - gMin;
            d.startAngle = -1 * (Math.PI / 2);
            d.endAngle = d.startAngle + gTic * gValue;
        }
        return found ? d : null;
    };
    c3_chart_internal_fn.getSvgArc = function() {
        var $$ = this, arc = $$.d3.svg.arc().outerRadius($$.radius).innerRadius($$.innerRadius), newArc = function(d, withoutUpdate) {
            var updated;
            if (withoutUpdate) {
                return arc(d);
            }
            updated = $$.updateAngle(d);
            return updated ? arc(updated) : "M 0 0";
        };
        newArc.centroid = arc.centroid;
        return newArc;
    };
    c3_chart_internal_fn.getSvgArcExpanded = function(rate) {
        var $$ = this, arc = $$.d3.svg.arc().outerRadius($$.radiusExpanded * (rate ? rate : 1)).innerRadius($$.innerRadius);
        return function(d) {
            var updated = $$.updateAngle(d);
            return updated ? arc(updated) : "M 0 0";
        };
    };
    c3_chart_internal_fn.getArc = function(d, withoutUpdate, force) {
        return force || this.isArcType(d.data) ? this.svgArc(d, withoutUpdate) : "M 0 0";
    };
    c3_chart_internal_fn.transformForArcLabel = function(d) {
        var $$ = this, updated = $$.updateAngle(d), c, x, y, h, ratio, translate = "";
        if (updated && !$$.hasType("gauge")) {
            c = this.svgArc.centroid(updated);
            x = isNaN(c[0]) ? 0 : c[0];
            y = isNaN(c[1]) ? 0 : c[1];
            h = Math.sqrt(x * x + y * y);
            ratio = $$.radius && h ? (36 / $$.radius > .375 ? 1.175 - 36 / $$.radius : .8) * $$.radius / h : 0;
            translate = "translate(" + x * ratio + "," + y * ratio + ")";
        }
        return translate;
    };
    c3_chart_internal_fn.getArcRatio = function(d) {
        var $$ = this, whole = $$.hasType("gauge") ? Math.PI : Math.PI * 2;
        return d ? (d.endAngle - d.startAngle) / whole : null;
    };
    c3_chart_internal_fn.convertToArcData = function(d) {
        return this.addName({
            id: d.data.id,
            value: d.value,
            ratio: this.getArcRatio(d),
            index: d.index
        });
    };
    c3_chart_internal_fn.textForArcLabel = function(d) {
        var $$ = this, updated, value, ratio, id, format;
        if (!$$.shouldShowArcLabel()) {
            return "";
        }
        updated = $$.updateAngle(d);
        value = updated ? updated.value : null;
        ratio = $$.getArcRatio(updated);
        id = d.data.id;
        if (!$$.hasType("gauge") && !$$.meetsArcLabelThreshold(ratio)) {
            return "";
        }
        format = $$.getArcLabelFormat();
        return format ? format(value, ratio, id) : $$.defaultArcValueFormat(value, ratio);
    };
    c3_chart_internal_fn.expandArc = function(targetIds) {
        var $$ = this, interval;
        if ($$.transiting) {
            interval = window.setInterval(function() {
                if (!$$.transiting) {
                    window.clearInterval(interval);
                    if ($$.legend.selectAll(".c3-legend-item-focused").size() > 0) {
                        $$.expandArc(targetIds);
                    }
                }
            }, 10);
            return;
        }
        targetIds = $$.mapToTargetIds(targetIds);
        $$.svg.selectAll($$.selectorTargets(targetIds, "." + CLASS.chartArc)).each(function(d) {
            if (!$$.shouldExpand(d.data.id)) {
                return;
            }
            $$.d3.select(this).selectAll("path").transition().duration(50).attr("d", $$.svgArcExpanded).transition().duration(100).attr("d", $$.svgArcExpandedSub).each(function(d) {
                if ($$.isDonutType(d.data)) {}
            });
        });
    };
    c3_chart_internal_fn.unexpandArc = function(targetIds) {
        var $$ = this;
        if ($$.transiting) {
            return;
        }
        targetIds = $$.mapToTargetIds(targetIds);
        $$.svg.selectAll($$.selectorTargets(targetIds, "." + CLASS.chartArc)).selectAll("path").transition().duration(50).attr("d", $$.svgArc);
        $$.svg.selectAll("." + CLASS.arc).style("opacity", 1);
    };
    c3_chart_internal_fn.shouldExpand = function(id) {
        var $$ = this, config = $$.config;
        return $$.isDonutType(id) && config.donut_expand || $$.isGaugeType(id) && config.gauge_expand || $$.isPieType(id) && config.pie_expand;
    };
    c3_chart_internal_fn.shouldShowArcLabel = function() {
        var $$ = this, config = $$.config, shouldShow = true;
        if ($$.hasType("donut")) {
            shouldShow = config.donut_label_show;
        } else if ($$.hasType("pie")) {
            shouldShow = config.pie_label_show;
        }
        return shouldShow;
    };
    c3_chart_internal_fn.meetsArcLabelThreshold = function(ratio) {
        var $$ = this, config = $$.config, threshold = $$.hasType("donut") ? config.donut_label_threshold : config.pie_label_threshold;
        return ratio >= threshold;
    };
    c3_chart_internal_fn.getArcLabelFormat = function() {
        var $$ = this, config = $$.config, format = config.pie_label_format;
        if ($$.hasType("gauge")) {
            format = config.gauge_label_format;
        } else if ($$.hasType("donut")) {
            format = config.donut_label_format;
        }
        return format;
    };
    c3_chart_internal_fn.getArcTitle = function() {
        var $$ = this;
        return $$.hasType("donut") ? $$.config.donut_title : "";
    };
    c3_chart_internal_fn.updateTargetsForArc = function(targets) {
        var $$ = this, main = $$.main, mainPieUpdate, mainPieEnter, classChartArc = $$.classChartArc.bind($$), classArcs = $$.classArcs.bind($$), classFocus = $$.classFocus.bind($$);
        mainPieUpdate = main.select("." + CLASS.chartArcs).selectAll("." + CLASS.chartArc).data($$.pie(targets)).attr("class", function(d) {
            return classChartArc(d) + classFocus(d.data);
        });
        mainPieEnter = mainPieUpdate.enter().append("g").attr("class", classChartArc);
        mainPieEnter.append("g").attr("class", classArcs);
        mainPieEnter.append("text").attr("dy", $$.hasType("gauge") ? "-.1em" : ".35em").style("opacity", 0).style("text-anchor", "middle").style("pointer-events", "none");
    };
    c3_chart_internal_fn.initArc = function() {
        var $$ = this;
        $$.arcs = $$.main.select("." + CLASS.chart).append("g").attr("class", CLASS.chartArcs).attr("transform", $$.getTranslate("arc"));
        $$.arcs.append("text").attr("class", CLASS.chartArcsTitle).style("text-anchor", "middle").text($$.getArcTitle());
    };
    c3_chart_internal_fn.redrawArc = function(duration, durationForExit, withTransform) {
        var $$ = this, d3 = $$.d3, config = $$.config, main = $$.main, mainArc;
        mainArc = main.selectAll("." + CLASS.arcs).selectAll("." + CLASS.arc).data($$.arcData.bind($$));
        mainArc.enter().append("path").attr("class", $$.classArc.bind($$)).style("fill", function(d) {
            return $$.color(d.data);
        }).style("cursor", function(d) {
            return config.interaction_enabled && config.data_selection_isselectable(d) ? "pointer" : null;
        }).style("opacity", 0).each(function(d) {
            if ($$.isGaugeType(d.data)) {
                d.startAngle = d.endAngle = -1 * (Math.PI / 2);
            }
            this._current = d;
        });
        mainArc.attr("transform", function(d) {
            return !$$.isGaugeType(d.data) && withTransform ? "scale(0)" : "";
        }).style("opacity", function(d) {
            return d === this._current ? 0 : 1;
        }).on("mouseover", config.interaction_enabled ? function(d) {
            var updated, arcData;
            if ($$.transiting) {
                return;
            }
            updated = $$.updateAngle(d);
            arcData = $$.convertToArcData(updated);
            $$.expandArc(updated.data.id);
            $$.api.focus(updated.data.id);
            $$.toggleFocusLegend(updated.data.id, true);
            $$.config.data_onmouseover(arcData, this);
        } : null).on("mousemove", config.interaction_enabled ? function(d) {
            var updated = $$.updateAngle(d), arcData = $$.convertToArcData(updated), selectedData = [ arcData ];
            $$.showTooltip(selectedData, this);
        } : null).on("mouseout", config.interaction_enabled ? function(d) {
            var updated, arcData;
            if ($$.transiting) {
                return;
            }
            updated = $$.updateAngle(d);
            arcData = $$.convertToArcData(updated);
            $$.unexpandArc(updated.data.id);
            $$.api.revert();
            $$.revertLegend();
            $$.hideTooltip();
            $$.config.data_onmouseout(arcData, this);
        } : null).on("click", config.interaction_enabled ? function(d, i) {
            var updated = $$.updateAngle(d), arcData = $$.convertToArcData(updated);
            if ($$.toggleShape) {
                $$.toggleShape(this, arcData, i);
            }
            $$.config.data_onclick.call($$.api, arcData, this);
        } : null).each(function() {
            $$.transiting = true;
        }).transition().duration(duration).attrTween("d", function(d) {
            var updated = $$.updateAngle(d), interpolate;
            if (!updated) {
                return function() {
                    return "M 0 0";
                };
            }
            if (isNaN(this._current.startAngle)) {
                this._current.startAngle = 0;
            }
            if (isNaN(this._current.endAngle)) {
                this._current.endAngle = this._current.startAngle;
            }
            interpolate = d3.interpolate(this._current, updated);
            this._current = interpolate(0);
            return function(t) {
                var interpolated = interpolate(t);
                interpolated.data = d.data;
                return $$.getArc(interpolated, true);
            };
        }).attr("transform", withTransform ? "scale(1)" : "").style("fill", function(d) {
            return $$.levelColor ? $$.levelColor(d.data.values[0].value) : $$.color(d.data.id);
        }).style("opacity", 1).call($$.endall, function() {
            $$.transiting = false;
        });
        mainArc.exit().transition().duration(durationForExit).style("opacity", 0).remove();
        main.selectAll("." + CLASS.chartArc).select("text").style("opacity", 0).attr("class", function(d) {
            return $$.isGaugeType(d.data) ? CLASS.gaugeValue : "";
        }).text($$.textForArcLabel.bind($$)).attr("transform", $$.transformForArcLabel.bind($$)).style("font-size", function(d) {
            return $$.isGaugeType(d.data) ? Math.round($$.radius / 5) + "px" : "";
        }).transition().duration(duration).style("opacity", function(d) {
            return $$.isTargetToShow(d.data.id) && $$.isArcType(d.data) ? 1 : 0;
        });
        main.select("." + CLASS.chartArcsTitle).style("opacity", $$.hasType("donut") || $$.hasType("gauge") ? 1 : 0);
        if ($$.hasType("gauge")) {
            $$.arcs.select("." + CLASS.chartArcsBackground).attr("d", function() {
                var d = {
                    data: [ {
                        value: config.gauge_max
                    } ],
                    startAngle: -1 * (Math.PI / 2),
                    endAngle: Math.PI / 2
                };
                return $$.getArc(d, true, true);
            });
            $$.arcs.select("." + CLASS.chartArcsGaugeUnit).attr("dy", ".75em").text(config.gauge_label_show ? config.gauge_units : "");
            $$.arcs.select("." + CLASS.chartArcsGaugeMin).attr("dx", -1 * ($$.innerRadius + ($$.radius - $$.innerRadius) / 2) + "px").attr("dy", "1.2em").text(config.gauge_label_show ? config.gauge_min : "");
            $$.arcs.select("." + CLASS.chartArcsGaugeMax).attr("dx", $$.innerRadius + ($$.radius - $$.innerRadius) / 2 + "px").attr("dy", "1.2em").text(config.gauge_label_show ? config.gauge_max : "");
        }
    };
    c3_chart_internal_fn.initGauge = function() {
        var arcs = this.arcs;
        if (this.hasType("gauge")) {
            arcs.append("path").attr("class", CLASS.chartArcsBackground);
            arcs.append("text").attr("class", CLASS.chartArcsGaugeUnit).style("text-anchor", "middle").style("pointer-events", "none");
            arcs.append("text").attr("class", CLASS.chartArcsGaugeMin).style("text-anchor", "middle").style("pointer-events", "none");
            arcs.append("text").attr("class", CLASS.chartArcsGaugeMax).style("text-anchor", "middle").style("pointer-events", "none");
        }
    };
    c3_chart_internal_fn.getGaugeLabelHeight = function() {
        return this.config.gauge_label_show ? 20 : 0;
    };
    c3_chart_internal_fn.initRegion = function() {
        var $$ = this;
        $$.region = $$.main.append("g").attr("clip-path", $$.clipPath).attr("class", CLASS.regions);
    };
    c3_chart_internal_fn.updateRegion = function(duration) {
        var $$ = this, config = $$.config;
        $$.region.style("visibility", $$.hasArcType() ? "hidden" : "visible");
        $$.mainRegion = $$.main.select("." + CLASS.regions).selectAll("." + CLASS.region).data(config.regions);
        $$.mainRegion.enter().append("g").attr("class", $$.classRegion.bind($$)).append("rect").style("fill-opacity", 0);
        $$.mainRegion.exit().transition().duration(duration).style("opacity", 0).remove();
    };
    c3_chart_internal_fn.redrawRegion = function(withTransition) {
        var $$ = this, regions = $$.mainRegion.selectAll("rect"), x = $$.regionX.bind($$), y = $$.regionY.bind($$), w = $$.regionWidth.bind($$), h = $$.regionHeight.bind($$);
        return [ (withTransition ? regions.transition() : regions).attr("x", x).attr("y", y).attr("width", w).attr("height", h).style("fill-opacity", function(d) {
            return isValue(d.opacity) ? d.opacity : .1;
        }) ];
    };
    c3_chart_internal_fn.regionX = function(d) {
        var $$ = this, config = $$.config, xPos, yScale = d.axis === "y" ? $$.y : $$.y2;
        if (d.axis === "y" || d.axis === "y2") {
            xPos = config.axis_rotated ? "start" in d ? yScale(d.start) : 0 : 0;
        } else {
            xPos = config.axis_rotated ? 0 : "start" in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.start) : d.start) : 0;
        }
        return xPos;
    };
    c3_chart_internal_fn.regionY = function(d) {
        var $$ = this, config = $$.config, yPos, yScale = d.axis === "y" ? $$.y : $$.y2;
        if (d.axis === "y" || d.axis === "y2") {
            yPos = config.axis_rotated ? 0 : "end" in d ? yScale(d.end) : 0;
        } else {
            yPos = config.axis_rotated ? "start" in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.start) : d.start) : 0 : 0;
        }
        return yPos;
    };
    c3_chart_internal_fn.regionWidth = function(d) {
        var $$ = this, config = $$.config, start = $$.regionX(d), end, yScale = d.axis === "y" ? $$.y : $$.y2;
        if (d.axis === "y" || d.axis === "y2") {
            end = config.axis_rotated ? "end" in d ? yScale(d.end) : $$.width : $$.width;
        } else {
            end = config.axis_rotated ? $$.width : "end" in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.end) : d.end) : $$.width;
        }
        return end < start ? 0 : end - start;
    };
    c3_chart_internal_fn.regionHeight = function(d) {
        var $$ = this, config = $$.config, start = this.regionY(d), end, yScale = d.axis === "y" ? $$.y : $$.y2;
        if (d.axis === "y" || d.axis === "y2") {
            end = config.axis_rotated ? $$.height : "start" in d ? yScale(d.start) : $$.height;
        } else {
            end = config.axis_rotated ? "end" in d ? $$.x($$.isTimeSeries() ? $$.parseDate(d.end) : d.end) : $$.height : $$.height;
        }
        return end < start ? 0 : end - start;
    };
    c3_chart_internal_fn.isRegionOnX = function(d) {
        return !d.axis || d.axis === "x";
    };
    c3_chart_internal_fn.drag = function(mouse) {
        var $$ = this, config = $$.config, main = $$.main, d3 = $$.d3;
        var sx, sy, mx, my, minX, maxX, minY, maxY;
        if ($$.hasArcType()) {
            return;
        }
        if (!config.data_selection_enabled) {
            return;
        }
        if (config.zoom_enabled && !$$.zoom.altDomain) {
            return;
        }
        if (!config.data_selection_multiple) {
            return;
        }
        sx = $$.dragStart[0];
        sy = $$.dragStart[1];
        mx = mouse[0];
        my = mouse[1];
        minX = Math.min(sx, mx);
        maxX = Math.max(sx, mx);
        minY = config.data_selection_grouped ? $$.margin.top : Math.min(sy, my);
        maxY = config.data_selection_grouped ? $$.height : Math.max(sy, my);
        main.select("." + CLASS.dragarea).attr("x", minX).attr("y", minY).attr("width", maxX - minX).attr("height", maxY - minY);
        main.selectAll("." + CLASS.shapes).selectAll("." + CLASS.shape).filter(function(d) {
            return config.data_selection_isselectable(d);
        }).each(function(d, i) {
            var shape = d3.select(this), isSelected = shape.classed(CLASS.SELECTED), isIncluded = shape.classed(CLASS.INCLUDED), _x, _y, _w, _h, toggle, isWithin = false, box;
            if (shape.classed(CLASS.circle)) {
                _x = shape.attr("cx") * 1;
                _y = shape.attr("cy") * 1;
                toggle = $$.togglePoint;
                isWithin = minX < _x && _x < maxX && minY < _y && _y < maxY;
            } else if (shape.classed(CLASS.bar)) {
                box = getPathBox(this);
                _x = box.x;
                _y = box.y;
                _w = box.width;
                _h = box.height;
                toggle = $$.togglePath;
                isWithin = !(maxX < _x || _x + _w < minX) && !(maxY < _y || _y + _h < minY);
            } else {
                return;
            }
            if (isWithin ^ isIncluded) {
                shape.classed(CLASS.INCLUDED, !isIncluded);
                shape.classed(CLASS.SELECTED, !isSelected);
                toggle.call($$, !isSelected, shape, d, i);
            }
        });
    };
    c3_chart_internal_fn.dragstart = function(mouse) {
        var $$ = this, config = $$.config;
        if ($$.hasArcType()) {
            return;
        }
        if (!config.data_selection_enabled) {
            return;
        }
        $$.dragStart = mouse;
        $$.main.select("." + CLASS.chart).append("rect").attr("class", CLASS.dragarea).style("opacity", .1);
        $$.dragging = true;
    };
    c3_chart_internal_fn.dragend = function() {
        var $$ = this, config = $$.config;
        if ($$.hasArcType()) {
            return;
        }
        if (!config.data_selection_enabled) {
            return;
        }
        $$.main.select("." + CLASS.dragarea).transition().duration(100).style("opacity", 0).remove();
        $$.main.selectAll("." + CLASS.shape).classed(CLASS.INCLUDED, false);
        $$.dragging = false;
    };
    c3_chart_internal_fn.selectPoint = function(target, d, i) {
        var $$ = this, config = $$.config, cx = (config.axis_rotated ? $$.circleY : $$.circleX).bind($$), cy = (config.axis_rotated ? $$.circleX : $$.circleY).bind($$), r = $$.pointSelectR.bind($$);
        config.data_onselected.call($$.api, d, target.node());
        $$.main.select("." + CLASS.selectedCircles + $$.getTargetSelectorSuffix(d.id)).selectAll("." + CLASS.selectedCircle + "-" + i).data([ d ]).enter().append("circle").attr("class", function() {
            return $$.generateClass(CLASS.selectedCircle, i);
        }).attr("cx", cx).attr("cy", cy).attr("stroke", function() {
            return $$.color(d);
        }).attr("r", function(d) {
            return $$.pointSelectR(d) * 1.4;
        }).transition().duration(100).attr("r", r);
    };
    c3_chart_internal_fn.unselectPoint = function(target, d, i) {
        var $$ = this;
        $$.config.data_onunselected(d, target.node());
        $$.main.select("." + CLASS.selectedCircles + $$.getTargetSelectorSuffix(d.id)).selectAll("." + CLASS.selectedCircle + "-" + i).transition().duration(100).attr("r", 0).remove();
    };
    c3_chart_internal_fn.togglePoint = function(selected, target, d, i) {
        selected ? this.selectPoint(target, d, i) : this.unselectPoint(target, d, i);
    };
    c3_chart_internal_fn.selectPath = function(target, d) {
        var $$ = this;
        $$.config.data_onselected.call($$, d, target.node());
        target.transition().duration(100).style("fill", function() {
            return $$.d3.rgb($$.color(d)).brighter(.75);
        });
    };
    c3_chart_internal_fn.unselectPath = function(target, d) {
        var $$ = this;
        $$.config.data_onunselected.call($$, d, target.node());
        target.transition().duration(100).style("fill", function() {
            return $$.color(d);
        });
    };
    c3_chart_internal_fn.togglePath = function(selected, target, d, i) {
        selected ? this.selectPath(target, d, i) : this.unselectPath(target, d, i);
    };
    c3_chart_internal_fn.getToggle = function(that, d) {
        var $$ = this, toggle;
        if (that.nodeName === "circle") {
            if ($$.isStepType(d)) {
                toggle = function() {};
            } else {
                toggle = $$.togglePoint;
            }
        } else if (that.nodeName === "path") {
            toggle = $$.togglePath;
        }
        return toggle;
    };
    c3_chart_internal_fn.toggleShape = function(that, d, i) {
        var $$ = this, d3 = $$.d3, config = $$.config, shape = d3.select(that), isSelected = shape.classed(CLASS.SELECTED), toggle = $$.getToggle(that, d).bind($$);
        if (config.data_selection_enabled && config.data_selection_isselectable(d)) {
            if (!config.data_selection_multiple) {
                $$.main.selectAll("." + CLASS.shapes + (config.data_selection_grouped ? $$.getTargetSelectorSuffix(d.id) : "")).selectAll("." + CLASS.shape).each(function(d, i) {
                    var shape = d3.select(this);
                    if (shape.classed(CLASS.SELECTED)) {
                        toggle(false, shape.classed(CLASS.SELECTED, false), d, i);
                    }
                });
            }
            shape.classed(CLASS.SELECTED, !isSelected);
            toggle(!isSelected, shape, d, i);
        }
    };
    c3_chart_internal_fn.initBrush = function() {
        var $$ = this, d3 = $$.d3;
        $$.brush = d3.svg.brush().on("brush", function() {
            $$.redrawForBrush();
        });
        $$.brush.update = function() {
            if ($$.context) {
                $$.context.select("." + CLASS.brush).call(this);
            }
            return this;
        };
        $$.brush.scale = function(scale) {
            return $$.config.axis_rotated ? this.y(scale) : this.x(scale);
        };
    };
    c3_chart_internal_fn.initSubchart = function() {
        var $$ = this, config = $$.config, context = $$.context = $$.svg.append("g").attr("transform", $$.getTranslate("context"));
        context.style("visibility", config.subchart_show ? "visible" : "hidden");
        context.append("g").attr("clip-path", $$.clipPathForSubchart).attr("class", CLASS.chart);
        context.select("." + CLASS.chart).append("g").attr("class", CLASS.chartBars);
        context.select("." + CLASS.chart).append("g").attr("class", CLASS.chartLines);
        context.append("g").attr("clip-path", $$.clipPath).attr("class", CLASS.brush).call($$.brush);
        $$.axes.subx = context.append("g").attr("class", CLASS.axisX).attr("transform", $$.getTranslate("subx")).attr("clip-path", config.axis_rotated ? "" : $$.clipPathForXAxis);
    };
    c3_chart_internal_fn.updateTargetsForSubchart = function(targets) {
        var $$ = this, context = $$.context, config = $$.config, contextLineEnter, contextLineUpdate, contextBarEnter, contextBarUpdate, classChartBar = $$.classChartBar.bind($$), classBars = $$.classBars.bind($$), classChartLine = $$.classChartLine.bind($$), classLines = $$.classLines.bind($$), classAreas = $$.classAreas.bind($$);
        if (config.subchart_show) {
            contextBarUpdate = context.select("." + CLASS.chartBars).selectAll("." + CLASS.chartBar).data(targets).attr("class", classChartBar);
            contextBarEnter = contextBarUpdate.enter().append("g").style("opacity", 0).attr("class", classChartBar);
            contextBarEnter.append("g").attr("class", classBars);
            contextLineUpdate = context.select("." + CLASS.chartLines).selectAll("." + CLASS.chartLine).data(targets).attr("class", classChartLine);
            contextLineEnter = contextLineUpdate.enter().append("g").style("opacity", 0).attr("class", classChartLine);
            contextLineEnter.append("g").attr("class", classLines);
            contextLineEnter.append("g").attr("class", classAreas);
            context.selectAll("." + CLASS.brush + " rect").attr(config.axis_rotated ? "width" : "height", config.axis_rotated ? $$.width2 : $$.height2);
        }
    };
    c3_chart_internal_fn.updateBarForSubchart = function(durationForExit) {
        var $$ = this;
        $$.contextBar = $$.context.selectAll("." + CLASS.bars).selectAll("." + CLASS.bar).data($$.barData.bind($$));
        $$.contextBar.enter().append("path").attr("class", $$.classBar.bind($$)).style("stroke", "none").style("fill", $$.color);
        $$.contextBar.style("opacity", $$.initialOpacity.bind($$));
        $$.contextBar.exit().transition().duration(durationForExit).style("opacity", 0).remove();
    };
    c3_chart_internal_fn.redrawBarForSubchart = function(drawBarOnSub, withTransition, duration) {
        (withTransition ? this.contextBar.transition().duration(duration) : this.contextBar).attr("d", drawBarOnSub).style("opacity", 1);
    };
    c3_chart_internal_fn.updateLineForSubchart = function(durationForExit) {
        var $$ = this;
        $$.contextLine = $$.context.selectAll("." + CLASS.lines).selectAll("." + CLASS.line).data($$.lineData.bind($$));
        $$.contextLine.enter().append("path").attr("class", $$.classLine.bind($$)).style("stroke", $$.color);
        $$.contextLine.style("opacity", $$.initialOpacity.bind($$));
        $$.contextLine.exit().transition().duration(durationForExit).style("opacity", 0).remove();
    };
    c3_chart_internal_fn.redrawLineForSubchart = function(drawLineOnSub, withTransition, duration) {
        (withTransition ? this.contextLine.transition().duration(duration) : this.contextLine).attr("d", drawLineOnSub).style("opacity", 1);
    };
    c3_chart_internal_fn.updateAreaForSubchart = function(durationForExit) {
        var $$ = this, d3 = $$.d3;
        $$.contextArea = $$.context.selectAll("." + CLASS.areas).selectAll("." + CLASS.area).data($$.lineData.bind($$));
        $$.contextArea.enter().append("path").attr("class", $$.classArea.bind($$)).style("fill", $$.color).style("opacity", function() {
            $$.orgAreaOpacity = +d3.select(this).style("opacity");
            return 0;
        });
        $$.contextArea.style("opacity", 0);
        $$.contextArea.exit().transition().duration(durationForExit).style("opacity", 0).remove();
    };
    c3_chart_internal_fn.redrawAreaForSubchart = function(drawAreaOnSub, withTransition, duration) {
        (withTransition ? this.contextArea.transition().duration(duration) : this.contextArea).attr("d", drawAreaOnSub).style("fill", this.color).style("opacity", this.orgAreaOpacity);
    };
    c3_chart_internal_fn.redrawSubchart = function(withSubchart, transitions, duration, durationForExit, areaIndices, barIndices, lineIndices) {
        var $$ = this, d3 = $$.d3, config = $$.config, drawAreaOnSub, drawBarOnSub, drawLineOnSub;
        $$.context.style("visibility", config.subchart_show ? "visible" : "hidden");
        if (config.subchart_show) {
            if (d3.event && d3.event.type === "zoom") {
                $$.brush.extent($$.x.orgDomain()).update();
            }
            if (withSubchart) {
                if (!$$.brush.empty()) {
                    $$.brush.extent($$.x.orgDomain()).update();
                }
                drawAreaOnSub = $$.generateDrawArea(areaIndices, true);
                drawBarOnSub = $$.generateDrawBar(barIndices, true);
                drawLineOnSub = $$.generateDrawLine(lineIndices, true);
                $$.updateBarForSubchart(duration);
                $$.updateLineForSubchart(duration);
                $$.updateAreaForSubchart(duration);
                $$.redrawBarForSubchart(drawBarOnSub, duration, duration);
                $$.redrawLineForSubchart(drawLineOnSub, duration, duration);
                $$.redrawAreaForSubchart(drawAreaOnSub, duration, duration);
            }
        }
    };
    c3_chart_internal_fn.redrawForBrush = function() {
        var $$ = this, x = $$.x;
        $$.redraw({
            withTransition: false,
            withY: $$.config.zoom_rescale,
            withSubchart: false,
            withUpdateXDomain: true,
            withDimension: false
        });
        $$.config.subchart_onbrush.call($$.api, x.orgDomain());
    };
    c3_chart_internal_fn.transformContext = function(withTransition, transitions) {
        var $$ = this, subXAxis;
        if (transitions && transitions.axisSubX) {
            subXAxis = transitions.axisSubX;
        } else {
            subXAxis = $$.context.select("." + CLASS.axisX);
            if (withTransition) {
                subXAxis = subXAxis.transition();
            }
        }
        $$.context.attr("transform", $$.getTranslate("context"));
        subXAxis.attr("transform", $$.getTranslate("subx"));
    };
    c3_chart_internal_fn.getDefaultExtent = function() {
        var $$ = this, config = $$.config, extent = isFunction(config.axis_x_extent) ? config.axis_x_extent($$.getXDomain($$.data.targets)) : config.axis_x_extent;
        if ($$.isTimeSeries()) {
            extent = [ $$.parseDate(extent[0]), $$.parseDate(extent[1]) ];
        }
        return extent;
    };
    c3_chart_internal_fn.initZoom = function() {
        var $$ = this, d3 = $$.d3, config = $$.config, startEvent;
        $$.zoom = d3.behavior.zoom().on("zoomstart", function() {
            startEvent = d3.event.sourceEvent;
            $$.zoom.altDomain = d3.event.sourceEvent.altKey ? $$.x.orgDomain() : null;
            config.zoom_onzoomstart.call($$.api, d3.event.sourceEvent);
        }).on("zoom", function() {
            $$.redrawForZoom.call($$);
        }).on("zoomend", function() {
            var event = d3.event.sourceEvent;
            if (event && startEvent.clientX === event.clientX && startEvent.clientY === event.clientY) {
                return;
            }
            $$.redrawEventRect();
            $$.updateZoom();
            config.zoom_onzoomend.call($$.api, $$.x.orgDomain());
        });
        $$.zoom.scale = function(scale) {
            return config.axis_rotated ? this.y(scale) : this.x(scale);
        };
        $$.zoom.orgScaleExtent = function() {
            var extent = config.zoom_extent ? config.zoom_extent : [ 1, 10 ];
            return [ extent[0], Math.max($$.getMaxDataCount() / extent[1], extent[1]) ];
        };
        $$.zoom.updateScaleExtent = function() {
            var ratio = diffDomain($$.x.orgDomain()) / diffDomain($$.orgXDomain), extent = this.orgScaleExtent();
            this.scaleExtent([ extent[0] * ratio, extent[1] * ratio ]);
            return this;
        };
    };
    c3_chart_internal_fn.updateZoom = function() {
        var $$ = this, z = $$.config.zoom_enabled ? $$.zoom : function() {};
        $$.main.select("." + CLASS.zoomRect).call(z).on("dblclick.zoom", null);
        $$.main.selectAll("." + CLASS.eventRect).call(z).on("dblclick.zoom", null);
    };
    c3_chart_internal_fn.redrawForZoom = function() {
        var $$ = this, d3 = $$.d3, config = $$.config, zoom = $$.zoom, x = $$.x;
        if (!config.zoom_enabled) {
            return;
        }
        if ($$.filterTargetsToShow($$.data.targets).length === 0) {
            return;
        }
        if (d3.event.sourceEvent.type === "mousemove" && zoom.altDomain) {
            x.domain(zoom.altDomain);
            zoom.scale(x).updateScaleExtent();
            return;
        }
        if ($$.isCategorized() && x.orgDomain()[0] === $$.orgXDomain[0]) {
            x.domain([ $$.orgXDomain[0] - 1e-10, x.orgDomain()[1] ]);
        }
        $$.redraw({
            withTransition: false,
            withY: config.zoom_rescale,
            withSubchart: false,
            withEventRect: false,
            withDimension: false
        });
        if (d3.event.sourceEvent.type === "mousemove") {
            $$.cancelClick = true;
        }
        config.zoom_onzoom.call($$.api, x.orgDomain());
    };
    c3_chart_internal_fn.generateColor = function() {
        var $$ = this, config = $$.config, d3 = $$.d3, colors = config.data_colors, pattern = notEmpty(config.color_pattern) ? config.color_pattern : d3.scale.category10().range(), callback = config.data_color, ids = [];
        return function(d) {
            var id = d.id || d.data && d.data.id || d, color;
            if (colors[id] instanceof Function) {
                color = colors[id](d);
            } else if (colors[id]) {
                color = colors[id];
            } else {
                if (ids.indexOf(id) < 0) {
                    ids.push(id);
                }
                color = pattern[ids.indexOf(id) % pattern.length];
                colors[id] = color;
            }
            return callback instanceof Function ? callback(color, d) : color;
        };
    };
    c3_chart_internal_fn.generateLevelColor = function() {
        var $$ = this, config = $$.config, colors = config.color_pattern, threshold = config.color_threshold, asValue = threshold.unit === "value", values = threshold.values && threshold.values.length ? threshold.values : [], max = threshold.max || 100;
        return notEmpty(config.color_threshold) ? function(value) {
            var i, v, color = colors[colors.length - 1];
            for (i = 0; i < values.length; i++) {
                v = asValue ? value : value * 100 / max;
                if (v < values[i]) {
                    color = colors[i];
                    break;
                }
            }
            return color;
        } : null;
    };
    c3_chart_internal_fn.getYFormat = function(forArc) {
        var $$ = this, formatForY = forArc && !$$.hasType("gauge") ? $$.defaultArcValueFormat : $$.yFormat, formatForY2 = forArc && !$$.hasType("gauge") ? $$.defaultArcValueFormat : $$.y2Format;
        return function(v, ratio, id) {
            var format = $$.axis.getId(id) === "y2" ? formatForY2 : formatForY;
            return format.call($$, v, ratio);
        };
    };
    c3_chart_internal_fn.yFormat = function(v) {
        var $$ = this, config = $$.config, format = config.axis_y_tick_format ? config.axis_y_tick_format : $$.defaultValueFormat;
        return format(v);
    };
    c3_chart_internal_fn.y2Format = function(v) {
        var $$ = this, config = $$.config, format = config.axis_y2_tick_format ? config.axis_y2_tick_format : $$.defaultValueFormat;
        return format(v);
    };
    c3_chart_internal_fn.defaultValueFormat = function(v) {
        return isValue(v) ? +v : "";
    };
    c3_chart_internal_fn.defaultArcValueFormat = function(v, ratio) {
        return (ratio * 100).toFixed(1) + "%";
    };
    c3_chart_internal_fn.dataLabelFormat = function(targetId) {
        var $$ = this, data_labels = $$.config.data_labels, format, defaultFormat = function(v) {
            return isValue(v) ? +v : "";
        };
        if (typeof data_labels.format === "function") {
            format = data_labels.format;
        } else if (typeof data_labels.format === "object") {
            if (data_labels.format[targetId]) {
                format = data_labels.format[targetId] === true ? defaultFormat : data_labels.format[targetId];
            } else {
                format = function() {
                    return "";
                };
            }
        } else {
            format = defaultFormat;
        }
        return format;
    };
    c3_chart_internal_fn.hasCaches = function(ids) {
        for (var i = 0; i < ids.length; i++) {
            if (!(ids[i] in this.cache)) {
                return false;
            }
        }
        return true;
    };
    c3_chart_internal_fn.addCache = function(id, target) {
        this.cache[id] = this.cloneTarget(target);
    };
    c3_chart_internal_fn.getCaches = function(ids) {
        var targets = [], i;
        for (i = 0; i < ids.length; i++) {
            if (ids[i] in this.cache) {
                targets.push(this.cloneTarget(this.cache[ids[i]]));
            }
        }
        return targets;
    };
    var CLASS = c3_chart_internal_fn.CLASS = {
        target: "c3-target",
        chart: "c3-chart",
        chartLine: "c3-chart-line",
        chartLines: "c3-chart-lines",
        chartBar: "c3-chart-bar",
        chartBars: "c3-chart-bars",
        chartText: "c3-chart-text",
        chartTexts: "c3-chart-texts",
        chartArc: "c3-chart-arc",
        chartArcs: "c3-chart-arcs",
        chartArcsTitle: "c3-chart-arcs-title",
        chartArcsBackground: "c3-chart-arcs-background",
        chartArcsGaugeUnit: "c3-chart-arcs-gauge-unit",
        chartArcsGaugeMax: "c3-chart-arcs-gauge-max",
        chartArcsGaugeMin: "c3-chart-arcs-gauge-min",
        selectedCircle: "c3-selected-circle",
        selectedCircles: "c3-selected-circles",
        eventRect: "c3-event-rect",
        eventRects: "c3-event-rects",
        eventRectsSingle: "c3-event-rects-single",
        eventRectsMultiple: "c3-event-rects-multiple",
        zoomRect: "c3-zoom-rect",
        brush: "c3-brush",
        focused: "c3-focused",
        defocused: "c3-defocused",
        region: "c3-region",
        regions: "c3-regions",
        tooltipContainer: "c3-tooltip-container",
        tooltip: "c3-tooltip",
        tooltipName: "c3-tooltip-name",
        shape: "c3-shape",
        shapes: "c3-shapes",
        line: "c3-line",
        lines: "c3-lines",
        bar: "c3-bar",
        bars: "c3-bars",
        circle: "c3-circle",
        circles: "c3-circles",
        arc: "c3-arc",
        arcs: "c3-arcs",
        area: "c3-area",
        areas: "c3-areas",
        empty: "c3-empty",
        text: "c3-text",
        texts: "c3-texts",
        gaugeValue: "c3-gauge-value",
        grid: "c3-grid",
        gridLines: "c3-grid-lines",
        xgrid: "c3-xgrid",
        xgrids: "c3-xgrids",
        xgridLine: "c3-xgrid-line",
        xgridLines: "c3-xgrid-lines",
        xgridFocus: "c3-xgrid-focus",
        ygrid: "c3-ygrid",
        ygrids: "c3-ygrids",
        ygridLine: "c3-ygrid-line",
        ygridLines: "c3-ygrid-lines",
        axis: "c3-axis",
        axisX: "c3-axis-x",
        axisXLabel: "c3-axis-x-label",
        axisY: "c3-axis-y",
        axisYLabel: "c3-axis-y-label",
        axisY2: "c3-axis-y2",
        axisY2Label: "c3-axis-y2-label",
        legendBackground: "c3-legend-background",
        legendItem: "c3-legend-item",
        legendItemEvent: "c3-legend-item-event",
        legendItemTile: "c3-legend-item-tile",
        legendItemHidden: "c3-legend-item-hidden",
        legendItemFocused: "c3-legend-item-focused",
        dragarea: "c3-dragarea",
        EXPANDED: "_expanded_",
        SELECTED: "_selected_",
        INCLUDED: "_included_"
    };
    c3_chart_internal_fn.generateClass = function(prefix, targetId) {
        return " " + prefix + " " + prefix + this.getTargetSelectorSuffix(targetId);
    };
    c3_chart_internal_fn.classText = function(d) {
        return this.generateClass(CLASS.text, d.index);
    };
    c3_chart_internal_fn.classTexts = function(d) {
        return this.generateClass(CLASS.texts, d.id);
    };
    c3_chart_internal_fn.classShape = function(d) {
        return this.generateClass(CLASS.shape, d.index);
    };
    c3_chart_internal_fn.classShapes = function(d) {
        return this.generateClass(CLASS.shapes, d.id);
    };
    c3_chart_internal_fn.classLine = function(d) {
        return this.classShape(d) + this.generateClass(CLASS.line, d.id);
    };
    c3_chart_internal_fn.classLines = function(d) {
        return this.classShapes(d) + this.generateClass(CLASS.lines, d.id);
    };
    c3_chart_internal_fn.classCircle = function(d) {
        return this.classShape(d) + this.generateClass(CLASS.circle, d.index);
    };
    c3_chart_internal_fn.classCircles = function(d) {
        return this.classShapes(d) + this.generateClass(CLASS.circles, d.id);
    };
    c3_chart_internal_fn.classBar = function(d) {
        return this.classShape(d) + this.generateClass(CLASS.bar, d.index);
    };
    c3_chart_internal_fn.classBars = function(d) {
        return this.classShapes(d) + this.generateClass(CLASS.bars, d.id);
    };
    c3_chart_internal_fn.classArc = function(d) {
        return this.classShape(d.data) + this.generateClass(CLASS.arc, d.data.id);
    };
    c3_chart_internal_fn.classArcs = function(d) {
        return this.classShapes(d.data) + this.generateClass(CLASS.arcs, d.data.id);
    };
    c3_chart_internal_fn.classArea = function(d) {
        return this.classShape(d) + this.generateClass(CLASS.area, d.id);
    };
    c3_chart_internal_fn.classAreas = function(d) {
        return this.classShapes(d) + this.generateClass(CLASS.areas, d.id);
    };
    c3_chart_internal_fn.classRegion = function(d, i) {
        return this.generateClass(CLASS.region, i) + " " + ("class" in d ? d["class"] : "");
    };
    c3_chart_internal_fn.classEvent = function(d) {
        return this.generateClass(CLASS.eventRect, d.index);
    };
    c3_chart_internal_fn.classTarget = function(id) {
        var $$ = this;
        var additionalClassSuffix = $$.config.data_classes[id], additionalClass = "";
        if (additionalClassSuffix) {
            additionalClass = " " + CLASS.target + "-" + additionalClassSuffix;
        }
        return $$.generateClass(CLASS.target, id) + additionalClass;
    };
    c3_chart_internal_fn.classFocus = function(d) {
        return this.classFocused(d) + this.classDefocused(d);
    };
    c3_chart_internal_fn.classFocused = function(d) {
        return " " + (this.focusedTargetIds.indexOf(d.id) >= 0 ? CLASS.focused : "");
    };
    c3_chart_internal_fn.classDefocused = function(d) {
        return " " + (this.defocusedTargetIds.indexOf(d.id) >= 0 ? CLASS.defocused : "");
    };
    c3_chart_internal_fn.classChartText = function(d) {
        return CLASS.chartText + this.classTarget(d.id);
    };
    c3_chart_internal_fn.classChartLine = function(d) {
        return CLASS.chartLine + this.classTarget(d.id);
    };
    c3_chart_internal_fn.classChartBar = function(d) {
        return CLASS.chartBar + this.classTarget(d.id);
    };
    c3_chart_internal_fn.classChartArc = function(d) {
        return CLASS.chartArc + this.classTarget(d.data.id);
    };
    c3_chart_internal_fn.getTargetSelectorSuffix = function(targetId) {
        return targetId || targetId === 0 ? ("-" + targetId).replace(/[\s?!@#$%^&*()_=+,.<>'":;\[\]\/|~`{}\\]/g, "-") : "";
    };
    c3_chart_internal_fn.selectorTarget = function(id, prefix) {
        return (prefix || "") + "." + CLASS.target + this.getTargetSelectorSuffix(id);
    };
    c3_chart_internal_fn.selectorTargets = function(ids, prefix) {
        var $$ = this;
        ids = ids || [];
        return ids.length ? ids.map(function(id) {
            return $$.selectorTarget(id, prefix);
        }) : null;
    };
    c3_chart_internal_fn.selectorLegend = function(id) {
        return "." + CLASS.legendItem + this.getTargetSelectorSuffix(id);
    };
    c3_chart_internal_fn.selectorLegends = function(ids) {
        var $$ = this;
        return ids && ids.length ? ids.map(function(id) {
            return $$.selectorLegend(id);
        }) : null;
    };
    var isValue = c3_chart_internal_fn.isValue = function(v) {
        return v || v === 0;
    }, isFunction = c3_chart_internal_fn.isFunction = function(o) {
        return typeof o === "function";
    }, isString = c3_chart_internal_fn.isString = function(o) {
        return typeof o === "string";
    }, isUndefined = c3_chart_internal_fn.isUndefined = function(v) {
        return typeof v === "undefined";
    }, isDefined = c3_chart_internal_fn.isDefined = function(v) {
        return typeof v !== "undefined";
    }, ceil10 = c3_chart_internal_fn.ceil10 = function(v) {
        return Math.ceil(v / 10) * 10;
    }, asHalfPixel = c3_chart_internal_fn.asHalfPixel = function(n) {
        return Math.ceil(n) + .5;
    }, diffDomain = c3_chart_internal_fn.diffDomain = function(d) {
        return d[1] - d[0];
    }, isEmpty = c3_chart_internal_fn.isEmpty = function(o) {
        return !o || isString(o) && o.length === 0 || typeof o === "object" && Object.keys(o).length === 0;
    }, notEmpty = c3_chart_internal_fn.notEmpty = function(o) {
        return Object.keys(o).length > 0;
    }, getOption = c3_chart_internal_fn.getOption = function(options, key, defaultValue) {
        return isDefined(options[key]) ? options[key] : defaultValue;
    }, hasValue = c3_chart_internal_fn.hasValue = function(dict, value) {
        var found = false;
        Object.keys(dict).forEach(function(key) {
            if (dict[key] === value) {
                found = true;
            }
        });
        return found;
    }, getPathBox = c3_chart_internal_fn.getPathBox = function(path) {
        var box = path.getBoundingClientRect(), items = [ path.pathSegList.getItem(0), path.pathSegList.getItem(1) ], minX = items[0].x, minY = Math.min(items[0].y, items[1].y);
        return {
            x: minX,
            y: minY,
            width: box.width,
            height: box.height
        };
    };
    c3_chart_fn.focus = function(targetIds) {
        var $$ = this.internal, candidates;
        targetIds = $$.mapToTargetIds(targetIds);
        candidates = $$.svg.selectAll($$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))), 
        this.revert();
        this.defocus();
        candidates.classed(CLASS.focused, true).classed(CLASS.defocused, false);
        if ($$.hasArcType()) {
            $$.expandArc(targetIds);
        }
        $$.toggleFocusLegend(targetIds, true);
        $$.focusedTargetIds = targetIds;
        $$.defocusedTargetIds = $$.defocusedTargetIds.filter(function(id) {
            return targetIds.indexOf(id) < 0;
        });
    };
    c3_chart_fn.defocus = function(targetIds) {
        var $$ = this.internal, candidates;
        targetIds = $$.mapToTargetIds(targetIds);
        candidates = $$.svg.selectAll($$.selectorTargets(targetIds.filter($$.isTargetToShow, $$))), 
        candidates.classed(CLASS.focused, false).classed(CLASS.defocused, true);
        if ($$.hasArcType()) {
            $$.unexpandArc(targetIds);
        }
        $$.toggleFocusLegend(targetIds, false);
        $$.focusedTargetIds = $$.focusedTargetIds.filter(function(id) {
            return targetIds.indexOf(id) < 0;
        });
        $$.defocusedTargetIds = targetIds;
    };
    c3_chart_fn.revert = function(targetIds) {
        var $$ = this.internal, candidates;
        targetIds = $$.mapToTargetIds(targetIds);
        candidates = $$.svg.selectAll($$.selectorTargets(targetIds));
        candidates.classed(CLASS.focused, false).classed(CLASS.defocused, false);
        if ($$.hasArcType()) {
            $$.unexpandArc(targetIds);
        }
        if ($$.config.legend_show) {
            $$.showLegend(targetIds.filter($$.isLegendToShow.bind($$)));
            $$.legend.selectAll($$.selectorLegends(targetIds)).filter(function() {
                return $$.d3.select(this).classed(CLASS.legendItemFocused);
            }).classed(CLASS.legendItemFocused, false);
        }
        $$.focusedTargetIds = [];
        $$.defocusedTargetIds = [];
    };
    c3_chart_fn.show = function(targetIds, options) {
        var $$ = this.internal, targets;
        targetIds = $$.mapToTargetIds(targetIds);
        options = options || {};
        $$.removeHiddenTargetIds(targetIds);
        targets = $$.svg.selectAll($$.selectorTargets(targetIds));
        targets.transition().style("opacity", 1, "important").call($$.endall, function() {
            targets.style("opacity", null).style("opacity", 1);
        });
        if (options.withLegend) {
            $$.showLegend(targetIds);
        }
        $$.redraw({
            withUpdateOrgXDomain: true,
            withUpdateXDomain: true,
            withLegend: true
        });
    };
    c3_chart_fn.hide = function(targetIds, options) {
        var $$ = this.internal, targets;
        targetIds = $$.mapToTargetIds(targetIds);
        options = options || {};
        $$.addHiddenTargetIds(targetIds);
        targets = $$.svg.selectAll($$.selectorTargets(targetIds));
        targets.transition().style("opacity", 0, "important").call($$.endall, function() {
            targets.style("opacity", null).style("opacity", 0);
        });
        if (options.withLegend) {
            $$.hideLegend(targetIds);
        }
        $$.redraw({
            withUpdateOrgXDomain: true,
            withUpdateXDomain: true,
            withLegend: true
        });
    };
    c3_chart_fn.toggle = function(targetIds, options) {
        var that = this, $$ = this.internal;
        $$.mapToTargetIds(targetIds).forEach(function(targetId) {
            $$.isTargetToShow(targetId) ? that.hide(targetId, options) : that.show(targetId, options);
        });
    };
    c3_chart_fn.zoom = function(domain) {
        var $$ = this.internal;
        if (domain) {
            if ($$.isTimeSeries()) {
                domain = domain.map(function(x) {
                    return $$.parseDate(x);
                });
            }
            $$.brush.extent(domain);
            $$.redraw({
                withUpdateXDomain: true,
                withY: $$.config.zoom_rescale
            });
            $$.config.zoom_onzoom.call(this, $$.x.orgDomain());
        }
        return $$.brush.extent();
    };
    c3_chart_fn.zoom.enable = function(enabled) {
        var $$ = this.internal;
        $$.config.zoom_enabled = enabled;
        $$.updateAndRedraw();
    };
    c3_chart_fn.unzoom = function() {
        var $$ = this.internal;
        $$.brush.clear().update();
        $$.redraw({
            withUpdateXDomain: true
        });
    };
    c3_chart_fn.load = function(args) {
        var $$ = this.internal, config = $$.config;
        if (args.xs) {
            $$.addXs(args.xs);
        }
        if ("classes" in args) {
            Object.keys(args.classes).forEach(function(id) {
                config.data_classes[id] = args.classes[id];
            });
        }
        if ("categories" in args && $$.isCategorized()) {
            config.axis_x_categories = args.categories;
        }
        if ("axes" in args) {
            Object.keys(args.axes).forEach(function(id) {
                config.data_axes[id] = args.axes[id];
            });
        }
        if ("colors" in args) {
            Object.keys(args.colors).forEach(function(id) {
                config.data_colors[id] = args.colors[id];
            });
        }
        if ("cacheIds" in args && $$.hasCaches(args.cacheIds)) {
            $$.load($$.getCaches(args.cacheIds), args.done);
            return;
        }
        if ("unload" in args) {
            $$.unload($$.mapToTargetIds(typeof args.unload === "boolean" && args.unload ? null : args.unload), function() {
                $$.loadFromArgs(args);
            });
        } else {
            $$.loadFromArgs(args);
        }
    };
    c3_chart_fn.unload = function(args) {
        var $$ = this.internal;
        args = args || {};
        if (args instanceof Array) {
            args = {
                ids: args
            };
        } else if (typeof args === "string") {
            args = {
                ids: [ args ]
            };
        }
        $$.unload($$.mapToTargetIds(args.ids), function() {
            $$.redraw({
                withUpdateOrgXDomain: true,
                withUpdateXDomain: true,
                withLegend: true
            });
            if (args.done) {
                args.done();
            }
        });
    };
    c3_chart_fn.flow = function(args) {
        var $$ = this.internal, targets, data, notfoundIds = [], orgDataCount = $$.getMaxDataCount(), dataCount, domain, baseTarget, baseValue, length = 0, tail = 0, diff, to;
        if (args.json) {
            data = $$.convertJsonToData(args.json, args.keys);
        } else if (args.rows) {
            data = $$.convertRowsToData(args.rows);
        } else if (args.columns) {
            data = $$.convertColumnsToData(args.columns);
        } else {
            return;
        }
        targets = $$.convertDataToTargets(data, true);
        $$.data.targets.forEach(function(t) {
            var found = false, i, j;
            for (i = 0; i < targets.length; i++) {
                if (t.id === targets[i].id) {
                    found = true;
                    if (t.values[t.values.length - 1]) {
                        tail = t.values[t.values.length - 1].index + 1;
                    }
                    length = targets[i].values.length;
                    for (j = 0; j < length; j++) {
                        targets[i].values[j].index = tail + j;
                        if (!$$.isTimeSeries()) {
                            targets[i].values[j].x = tail + j;
                        }
                    }
                    t.values = t.values.concat(targets[i].values);
                    targets.splice(i, 1);
                    break;
                }
            }
            if (!found) {
                notfoundIds.push(t.id);
            }
        });
        $$.data.targets.forEach(function(t) {
            var i, j;
            for (i = 0; i < notfoundIds.length; i++) {
                if (t.id === notfoundIds[i]) {
                    tail = t.values[t.values.length - 1].index + 1;
                    for (j = 0; j < length; j++) {
                        t.values.push({
                            id: t.id,
                            index: tail + j,
                            x: $$.isTimeSeries() ? $$.getOtherTargetX(tail + j) : tail + j,
                            value: null
                        });
                    }
                }
            }
        });
        if ($$.data.targets.length) {
            targets.forEach(function(t) {
                var i, missing = [];
                for (i = $$.data.targets[0].values[0].index; i < tail; i++) {
                    missing.push({
                        id: t.id,
                        index: i,
                        x: $$.isTimeSeries() ? $$.getOtherTargetX(i) : i,
                        value: null
                    });
                }
                t.values.forEach(function(v) {
                    v.index += tail;
                    if (!$$.isTimeSeries()) {
                        v.x += tail;
                    }
                });
                t.values = missing.concat(t.values);
            });
        }
        $$.data.targets = $$.data.targets.concat(targets);
        dataCount = $$.getMaxDataCount();
        baseTarget = $$.data.targets[0];
        baseValue = baseTarget.values[0];
        if (isDefined(args.to)) {
            length = 0;
            to = $$.isTimeSeries() ? $$.parseDate(args.to) : args.to;
            baseTarget.values.forEach(function(v) {
                if (v.x < to) {
                    length++;
                }
            });
        } else if (isDefined(args.length)) {
            length = args.length;
        }
        if (!orgDataCount) {
            if ($$.isTimeSeries()) {
                if (baseTarget.values.length > 1) {
                    diff = baseTarget.values[baseTarget.values.length - 1].x - baseValue.x;
                } else {
                    diff = baseValue.x - $$.getXDomain($$.data.targets)[0];
                }
            } else {
                diff = 1;
            }
            domain = [ baseValue.x - diff, baseValue.x ];
            $$.updateXDomain(null, true, true, false, domain);
        } else if (orgDataCount === 1) {
            if ($$.isTimeSeries()) {
                diff = (baseTarget.values[baseTarget.values.length - 1].x - baseValue.x) / 2;
                domain = [ new Date(+baseValue.x - diff), new Date(+baseValue.x + diff) ];
                $$.updateXDomain(null, true, true, false, domain);
            }
        }
        $$.updateTargets($$.data.targets);
        $$.redraw({
            flow: {
                index: baseValue.index,
                length: length,
                duration: isValue(args.duration) ? args.duration : $$.config.transition_duration,
                done: args.done,
                orgDataCount: orgDataCount
            },
            withLegend: true,
            withTransition: orgDataCount > 1,
            withTrimXDomain: false,
            withUpdateXAxis: true
        });
    };
    c3_chart_internal_fn.generateFlow = function(args) {
        var $$ = this, config = $$.config, d3 = $$.d3;
        return function() {
            var targets = args.targets, flow = args.flow, drawBar = args.drawBar, drawLine = args.drawLine, drawArea = args.drawArea, cx = args.cx, cy = args.cy, xv = args.xv, xForText = args.xForText, yForText = args.yForText, duration = args.duration;
            var translateX, scaleX = 1, transform, flowIndex = flow.index, flowLength = flow.length, flowStart = $$.getValueOnIndex($$.data.targets[0].values, flowIndex), flowEnd = $$.getValueOnIndex($$.data.targets[0].values, flowIndex + flowLength), orgDomain = $$.x.domain(), domain, durationForFlow = flow.duration || duration, done = flow.done || function() {}, wait = $$.generateWait();
            var xgrid = $$.xgrid || d3.selectAll([]), xgridLines = $$.xgridLines || d3.selectAll([]), mainRegion = $$.mainRegion || d3.selectAll([]), mainText = $$.mainText || d3.selectAll([]), mainBar = $$.mainBar || d3.selectAll([]), mainLine = $$.mainLine || d3.selectAll([]), mainArea = $$.mainArea || d3.selectAll([]), mainCircle = $$.mainCircle || d3.selectAll([]);
            $$.flowing = true;
            $$.data.targets.forEach(function(d) {
                d.values.splice(0, flowLength);
            });
            domain = $$.updateXDomain(targets, true, true);
            if ($$.updateXGrid) {
                $$.updateXGrid(true);
            }
            if (!flow.orgDataCount) {
                if ($$.data.targets[0].values.length !== 1) {
                    translateX = $$.x(orgDomain[0]) - $$.x(domain[0]);
                } else {
                    if ($$.isTimeSeries()) {
                        flowStart = $$.getValueOnIndex($$.data.targets[0].values, 0);
                        flowEnd = $$.getValueOnIndex($$.data.targets[0].values, $$.data.targets[0].values.length - 1);
                        translateX = $$.x(flowStart.x) - $$.x(flowEnd.x);
                    } else {
                        translateX = diffDomain(domain) / 2;
                    }
                }
            } else if (flow.orgDataCount === 1 || flowStart.x === flowEnd.x) {
                translateX = $$.x(orgDomain[0]) - $$.x(domain[0]);
            } else {
                if ($$.isTimeSeries()) {
                    translateX = $$.x(orgDomain[0]) - $$.x(domain[0]);
                } else {
                    translateX = $$.x(flowStart.x) - $$.x(flowEnd.x);
                }
            }
            scaleX = diffDomain(orgDomain) / diffDomain(domain);
            transform = "translate(" + translateX + ",0) scale(" + scaleX + ",1)";
            $$.hideXGridFocus();
            $$.hideTooltip();
            d3.transition().ease("linear").duration(durationForFlow).each(function() {
                wait.add($$.axes.x.transition().call($$.xAxis));
                wait.add(mainBar.transition().attr("transform", transform));
                wait.add(mainLine.transition().attr("transform", transform));
                wait.add(mainArea.transition().attr("transform", transform));
                wait.add(mainCircle.transition().attr("transform", transform));
                wait.add(mainText.transition().attr("transform", transform));
                wait.add(mainRegion.filter($$.isRegionOnX).transition().attr("transform", transform));
                wait.add(xgrid.transition().attr("transform", transform));
                wait.add(xgridLines.transition().attr("transform", transform));
            }).call(wait, function() {
                var i, shapes = [], texts = [], eventRects = [];
                if (flowLength) {
                    for (i = 0; i < flowLength; i++) {
                        shapes.push("." + CLASS.shape + "-" + (flowIndex + i));
                        texts.push("." + CLASS.text + "-" + (flowIndex + i));
                        eventRects.push("." + CLASS.eventRect + "-" + (flowIndex + i));
                    }
                    $$.svg.selectAll("." + CLASS.shapes).selectAll(shapes).remove();
                    $$.svg.selectAll("." + CLASS.texts).selectAll(texts).remove();
                    $$.svg.selectAll("." + CLASS.eventRects).selectAll(eventRects).remove();
                    $$.svg.select("." + CLASS.xgrid).remove();
                }
                xgrid.attr("transform", null).attr($$.xgridAttr);
                xgridLines.attr("transform", null);
                xgridLines.select("line").attr("x1", config.axis_rotated ? 0 : xv).attr("x2", config.axis_rotated ? $$.width : xv);
                xgridLines.select("text").attr("x", config.axis_rotated ? $$.width : 0).attr("y", xv);
                mainBar.attr("transform", null).attr("d", drawBar);
                mainLine.attr("transform", null).attr("d", drawLine);
                mainArea.attr("transform", null).attr("d", drawArea);
                mainCircle.attr("transform", null).attr("cx", cx).attr("cy", cy);
                mainText.attr("transform", null).attr("x", xForText).attr("y", yForText).style("fill-opacity", $$.opacityForText.bind($$));
                mainRegion.attr("transform", null);
                mainRegion.select("rect").filter($$.isRegionOnX).attr("x", $$.regionX.bind($$)).attr("width", $$.regionWidth.bind($$));
                if (config.interaction_enabled) {
                    $$.redrawEventRect();
                }
                done();
                $$.flowing = false;
            });
        };
    };
    c3_chart_fn.selected = function(targetId) {
        var $$ = this.internal, d3 = $$.d3;
        return d3.merge($$.main.selectAll("." + CLASS.shapes + $$.getTargetSelectorSuffix(targetId)).selectAll("." + CLASS.shape).filter(function() {
            return d3.select(this).classed(CLASS.SELECTED);
        }).map(function(d) {
            return d.map(function(d) {
                var data = d.__data__;
                return data.data ? data.data : data;
            });
        }));
    };
    c3_chart_fn.select = function(ids, indices, resetOther) {
        var $$ = this.internal, d3 = $$.d3, config = $$.config;
        if (!config.data_selection_enabled) {
            return;
        }
        $$.main.selectAll("." + CLASS.shapes).selectAll("." + CLASS.shape).each(function(d, i) {
            var shape = d3.select(this), id = d.data ? d.data.id : d.id, toggle = $$.getToggle(this, d).bind($$), isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0, isTargetIndex = !indices || indices.indexOf(i) >= 0, isSelected = shape.classed(CLASS.SELECTED);
            if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) {
                return;
            }
            if (isTargetId && isTargetIndex) {
                if (config.data_selection_isselectable(d) && !isSelected) {
                    toggle(true, shape.classed(CLASS.SELECTED, true), d, i);
                }
            } else if (isDefined(resetOther) && resetOther) {
                if (isSelected) {
                    toggle(false, shape.classed(CLASS.SELECTED, false), d, i);
                }
            }
        });
    };
    c3_chart_fn.unselect = function(ids, indices) {
        var $$ = this.internal, d3 = $$.d3, config = $$.config;
        if (!config.data_selection_enabled) {
            return;
        }
        $$.main.selectAll("." + CLASS.shapes).selectAll("." + CLASS.shape).each(function(d, i) {
            var shape = d3.select(this), id = d.data ? d.data.id : d.id, toggle = $$.getToggle(this, d).bind($$), isTargetId = config.data_selection_grouped || !ids || ids.indexOf(id) >= 0, isTargetIndex = !indices || indices.indexOf(i) >= 0, isSelected = shape.classed(CLASS.SELECTED);
            if (shape.classed(CLASS.line) || shape.classed(CLASS.area)) {
                return;
            }
            if (isTargetId && isTargetIndex) {
                if (config.data_selection_isselectable(d)) {
                    if (isSelected) {
                        toggle(false, shape.classed(CLASS.SELECTED, false), d, i);
                    }
                }
            }
        });
    };
    c3_chart_fn.transform = function(type, targetIds) {
        var $$ = this.internal, options = [ "pie", "donut" ].indexOf(type) >= 0 ? {
            withTransform: true
        } : null;
        $$.transformTo(targetIds, type, options);
    };
    c3_chart_internal_fn.transformTo = function(targetIds, type, optionsForRedraw) {
        var $$ = this, withTransitionForAxis = !$$.hasArcType(), options = optionsForRedraw || {
            withTransitionForAxis: withTransitionForAxis
        };
        options.withTransitionForTransform = false;
        $$.transiting = false;
        $$.setTargetType(targetIds, type);
        $$.updateTargets($$.data.targets);
        $$.updateAndRedraw(options);
    };
    c3_chart_fn.groups = function(groups) {
        var $$ = this.internal, config = $$.config;
        if (isUndefined(groups)) {
            return config.data_groups;
        }
        config.data_groups = groups;
        $$.redraw();
        return config.data_groups;
    };
    c3_chart_fn.xgrids = function(grids) {
        var $$ = this.internal, config = $$.config;
        if (!grids) {
            return config.grid_x_lines;
        }
        config.grid_x_lines = grids;
        $$.redrawWithoutRescale();
        return config.grid_x_lines;
    };
    c3_chart_fn.xgrids.add = function(grids) {
        var $$ = this.internal;
        return this.xgrids($$.config.grid_x_lines.concat(grids ? grids : []));
    };
    c3_chart_fn.xgrids.remove = function(params) {
        var $$ = this.internal;
        $$.removeGridLines(params, true);
    };
    c3_chart_fn.ygrids = function(grids) {
        var $$ = this.internal, config = $$.config;
        if (!grids) {
            return config.grid_y_lines;
        }
        config.grid_y_lines = grids;
        $$.redrawWithoutRescale();
        return config.grid_y_lines;
    };
    c3_chart_fn.ygrids.add = function(grids) {
        var $$ = this.internal;
        return this.ygrids($$.config.grid_y_lines.concat(grids ? grids : []));
    };
    c3_chart_fn.ygrids.remove = function(params) {
        var $$ = this.internal;
        $$.removeGridLines(params, false);
    };
    c3_chart_fn.regions = function(regions) {
        var $$ = this.internal, config = $$.config;
        if (!regions) {
            return config.regions;
        }
        config.regions = regions;
        $$.redrawWithoutRescale();
        return config.regions;
    };
    c3_chart_fn.regions.add = function(regions) {
        var $$ = this.internal, config = $$.config;
        if (!regions) {
            return config.regions;
        }
        config.regions = config.regions.concat(regions);
        $$.redrawWithoutRescale();
        return config.regions;
    };
    c3_chart_fn.regions.remove = function(options) {
        var $$ = this.internal, config = $$.config, duration, classes, regions;
        options = options || {};
        duration = $$.getOption(options, "duration", config.transition_duration);
        classes = $$.getOption(options, "classes", [ CLASS.region ]);
        regions = $$.main.select("." + CLASS.regions).selectAll(classes.map(function(c) {
            return "." + c;
        }));
        (duration ? regions.transition().duration(duration) : regions).style("opacity", 0).remove();
        config.regions = config.regions.filter(function(region) {
            var found = false;
            if (!region["class"]) {
                return true;
            }
            region["class"].split(" ").forEach(function(c) {
                if (classes.indexOf(c) >= 0) {
                    found = true;
                }
            });
            return !found;
        });
        return config.regions;
    };
    c3_chart_fn.data = function(targetIds) {
        var targets = this.internal.data.targets;
        return typeof targetIds === "undefined" ? targets : targets.filter(function(t) {
            return [].concat(targetIds).indexOf(t.id) >= 0;
        });
    };
    c3_chart_fn.data.shown = function(targetIds) {
        return this.internal.filterTargetsToShow(this.data(targetIds));
    };
    c3_chart_fn.data.values = function(targetId) {
        var targets, values = null;
        if (targetId) {
            targets = this.data(targetId);
            values = targets[0] ? targets[0].values.map(function(d) {
                return d.value;
            }) : null;
        }
        return values;
    };
    c3_chart_fn.data.names = function(names) {
        this.internal.clearLegendItemTextBoxCache();
        return this.internal.updateDataAttributes("names", names);
    };
    c3_chart_fn.data.colors = function(colors) {
        return this.internal.updateDataAttributes("colors", colors);
    };
    c3_chart_fn.data.axes = function(axes) {
        return this.internal.updateDataAttributes("axes", axes);
    };
    c3_chart_fn.category = function(i, category) {
        var $$ = this.internal, config = $$.config;
        if (arguments.length > 1) {
            config.axis_x_categories[i] = category;
            $$.redraw();
        }
        return config.axis_x_categories[i];
    };
    c3_chart_fn.categories = function(categories) {
        var $$ = this.internal, config = $$.config;
        if (!arguments.length) {
            return config.axis_x_categories;
        }
        config.axis_x_categories = categories;
        $$.redraw();
        return config.axis_x_categories;
    };
    c3_chart_fn.color = function(id) {
        var $$ = this.internal;
        return $$.color(id);
    };
    c3_chart_fn.x = function(x) {
        var $$ = this.internal;
        if (arguments.length) {
            $$.updateTargetX($$.data.targets, x);
            $$.redraw({
                withUpdateOrgXDomain: true,
                withUpdateXDomain: true
            });
        }
        return $$.data.xs;
    };
    c3_chart_fn.xs = function(xs) {
        var $$ = this.internal;
        if (arguments.length) {
            $$.updateTargetXs($$.data.targets, xs);
            $$.redraw({
                withUpdateOrgXDomain: true,
                withUpdateXDomain: true
            });
        }
        return $$.data.xs;
    };
    c3_chart_fn.axis = function() {};
    c3_chart_fn.axis.labels = function(labels) {
        var $$ = this.internal;
        if (arguments.length) {
            Object.keys(labels).forEach(function(axisId) {
                $$.axis.setLabelText(axisId, labels[axisId]);
            });
            $$.axis.updateLabels();
        }
    };
    c3_chart_fn.axis.max = function(max) {
        var $$ = this.internal, config = $$.config;
        if (arguments.length) {
            if (typeof max === "object") {
                if (isValue(max.x)) {
                    config.axis_x_max = max.x;
                }
                if (isValue(max.y)) {
                    config.axis_y_max = max.y;
                }
                if (isValue(max.y2)) {
                    config.axis_y2_max = max.y2;
                }
            } else {
                config.axis_y_max = config.axis_y2_max = max;
            }
            $$.redraw({
                withUpdateOrgXDomain: true,
                withUpdateXDomain: true
            });
        } else {
            return {
                x: config.axis_x_max,
                y: config.axis_y_max,
                y2: config.axis_y2_max
            };
        }
    };
    c3_chart_fn.axis.min = function(min) {
        var $$ = this.internal, config = $$.config;
        if (arguments.length) {
            if (typeof min === "object") {
                if (isValue(min.x)) {
                    config.axis_x_min = min.x;
                }
                if (isValue(min.y)) {
                    config.axis_y_min = min.y;
                }
                if (isValue(min.y2)) {
                    config.axis_y2_min = min.y2;
                }
            } else {
                config.axis_y_min = config.axis_y2_min = min;
            }
            $$.redraw({
                withUpdateOrgXDomain: true,
                withUpdateXDomain: true
            });
        } else {
            return {
                x: config.axis_x_min,
                y: config.axis_y_min,
                y2: config.axis_y2_min
            };
        }
    };
    c3_chart_fn.axis.range = function(range) {
        if (arguments.length) {
            if (isDefined(range.max)) {
                this.axis.max(range.max);
            }
            if (isDefined(range.min)) {
                this.axis.min(range.min);
            }
        } else {
            return {
                max: this.axis.max(),
                min: this.axis.min()
            };
        }
    };
    c3_chart_fn.legend = function() {};
    c3_chart_fn.legend.show = function(targetIds) {
        var $$ = this.internal;
        $$.showLegend($$.mapToTargetIds(targetIds));
        $$.updateAndRedraw({
            withLegend: true
        });
    };
    c3_chart_fn.legend.hide = function(targetIds) {
        var $$ = this.internal;
        $$.hideLegend($$.mapToTargetIds(targetIds));
        $$.updateAndRedraw({
            withLegend: true
        });
    };
    c3_chart_fn.resize = function(size) {
        var $$ = this.internal, config = $$.config;
        config.size_width = size ? size.width : null;
        config.size_height = size ? size.height : null;
        this.flush();
    };
    c3_chart_fn.flush = function() {
        var $$ = this.internal;
        $$.updateAndRedraw({
            withLegend: true,
            withTransition: false,
            withTransitionForTransform: false
        });
    };
    c3_chart_fn.destroy = function() {
        var $$ = this.internal;
        window.clearInterval($$.intervalForObserveInserted);
        window.onresize = null;
        $$.selectChart.classed("c3", false).html("");
        Object.keys($$).forEach(function(key) {
            $$[key] = null;
        });
        return null;
    };
    c3_chart_fn.tooltip = function() {};
    c3_chart_fn.tooltip.show = function(args) {
        var $$ = this.internal, index, mouse;
        if (args.mouse) {
            mouse = args.mouse;
        }
        if (args.data) {
            if ($$.isMultipleX()) {
                mouse = [ $$.x(args.data.x), $$.getYScale(args.data.id)(args.data.value) ];
                index = null;
            } else {
                index = isValue(args.data.index) ? args.data.index : $$.getIndexByX(args.data.x);
            }
        } else if (typeof args.x !== "undefined") {
            index = $$.getIndexByX(args.x);
        } else if (typeof args.index !== "undefined") {
            index = args.index;
        }
        $$.dispatchEvent("mouseover", index, mouse);
        $$.dispatchEvent("mousemove", index, mouse);
    };
    c3_chart_fn.tooltip.hide = function() {
        this.internal.dispatchEvent("mouseout", 0);
    };
    var tickTextCharSize;
    function c3_axis(d3, params) {
        var scale = d3.scale.linear(), orient = "bottom", innerTickSize = 6, outerTickSize, tickPadding = 3, tickValues = null, tickFormat, tickArguments;
        var tickOffset = 0, tickCulling = true, tickCentered;
        params = params || {};
        outerTickSize = params.withOuterTick ? 6 : 0;
        function axisX(selection, x) {
            selection.attr("transform", function(d) {
                return "translate(" + Math.ceil(x(d) + tickOffset) + ", 0)";
            });
        }
        function axisY(selection, y) {
            selection.attr("transform", function(d) {
                return "translate(0," + Math.ceil(y(d)) + ")";
            });
        }
        function scaleExtent(domain) {
            var start = domain[0], stop = domain[domain.length - 1];
            return start < stop ? [ start, stop ] : [ stop, start ];
        }
        function generateTicks(scale) {
            var i, domain, ticks = [];
            if (scale.ticks) {
                return scale.ticks.apply(scale, tickArguments);
            }
            domain = scale.domain();
            for (i = Math.ceil(domain[0]); i < domain[1]; i++) {
                ticks.push(i);
            }
            if (ticks.length > 0 && ticks[0] > 0) {
                ticks.unshift(ticks[0] - (ticks[1] - ticks[0]));
            }
            return ticks;
        }
        function copyScale() {
            var newScale = scale.copy(), domain;
            if (params.isCategory) {
                domain = scale.domain();
                newScale.domain([ domain[0], domain[1] - 1 ]);
            }
            return newScale;
        }
        function textFormatted(v) {
            var formatted = tickFormat ? tickFormat(v) : v;
            return typeof formatted !== "undefined" ? formatted : "";
        }
        function getSizeFor1Char(tick) {
            if (tickTextCharSize) {
                return tickTextCharSize;
            }
            var size = {
                h: 11.5,
                w: 5.5
            };
            tick.select("text").text(textFormatted).each(function(d) {
                var box = this.getBoundingClientRect(), text = textFormatted(d), h = box.height, w = text ? box.width / text.length : undefined;
                if (h && w) {
                    size.h = h;
                    size.w = w;
                }
            }).text("");
            tickTextCharSize = size;
            return size;
        }
        function transitionise(selection) {
            return params.withoutTransition ? selection : d3.transition(selection);
        }
        function axis(g) {
            g.each(function() {
                var g = axis.g = d3.select(this);
                var scale0 = this.__chart__ || scale, scale1 = this.__chart__ = copyScale();
                var ticks = tickValues ? tickValues : generateTicks(scale1), tick = g.selectAll(".tick").data(ticks, scale1), tickEnter = tick.enter().insert("g", ".domain").attr("class", "tick").style("opacity", 1e-6), tickExit = tick.exit().remove(), tickUpdate = transitionise(tick).style("opacity", 1), tickTransform, tickX, tickY;
                var range = scale.rangeExtent ? scale.rangeExtent() : scaleExtent(scale.range()), path = g.selectAll(".domain").data([ 0 ]), pathUpdate = (path.enter().append("path").attr("class", "domain"), 
                transitionise(path));
                tickEnter.append("line");
                tickEnter.append("text");
                var lineEnter = tickEnter.select("line"), lineUpdate = tickUpdate.select("line"), textEnter = tickEnter.select("text"), textUpdate = tickUpdate.select("text");
                if (params.isCategory) {
                    tickOffset = Math.ceil((scale1(1) - scale1(0)) / 2);
                    tickX = tickCentered ? 0 : tickOffset;
                    tickY = tickCentered ? tickOffset : 0;
                } else {
                    tickOffset = tickX = 0;
                }
                var text, tspan, sizeFor1Char = getSizeFor1Char(g.select(".tick")), counts = [];
                var tickLength = Math.max(innerTickSize, 0) + tickPadding, isVertical = orient === "left" || orient === "right";
                function splitTickText(d, maxWidth) {
                    var tickText = textFormatted(d), subtext, spaceIndex, textWidth, splitted = [];
                    if (Object.prototype.toString.call(tickText) === "[object Array]") {
                        return tickText;
                    }
                    if (!maxWidth || maxWidth <= 0) {
                        maxWidth = isVertical ? 95 : params.isCategory ? Math.ceil(scale1(ticks[1]) - scale1(ticks[0])) - 12 : 110;
                    }
                    function split(splitted, text) {
                        spaceIndex = undefined;
                        for (var i = 1; i < text.length; i++) {
                            if (text.charAt(i) === " ") {
                                spaceIndex = i;
                            }
                            subtext = text.substr(0, i + 1);
                            textWidth = sizeFor1Char.w * subtext.length;
                            if (maxWidth < textWidth) {
                                return split(splitted.concat(text.substr(0, spaceIndex ? spaceIndex : i)), text.slice(spaceIndex ? spaceIndex + 1 : i));
                            }
                        }
                        return splitted.concat(text);
                    }
                    return split(splitted, tickText + "");
                }
                function tspanDy(d, i) {
                    var dy = sizeFor1Char.h;
                    if (i === 0) {
                        if (orient === "left" || orient === "right") {
                            dy = -((counts[d.index] - 1) * (sizeFor1Char.h / 2) - 3);
                        } else {
                            dy = ".71em";
                        }
                    }
                    return dy;
                }
                function tickSize(d) {
                    var tickPosition = scale(d) + (tickCentered ? 0 : tickOffset);
                    return range[0] < tickPosition && tickPosition < range[1] ? innerTickSize : 0;
                }
                text = tick.select("text");
                tspan = text.selectAll("tspan").data(function(d, i) {
                    var splitted = params.tickMultiline ? splitTickText(d, params.tickWidth) : [].concat(textFormatted(d));
                    counts[i] = splitted.length;
                    return splitted.map(function(s) {
                        return {
                            index: i,
                            splitted: s
                        };
                    });
                });
                tspan.enter().append("tspan");
                tspan.exit().remove();
                tspan.text(function(d) {
                    return d.splitted;
                });
                var rotate = params.tickTextRotate;
                function textAnchorForText(rotate) {
                    if (!rotate) {
                        return "middle";
                    }
                    return rotate > 0 ? "start" : "end";
                }
                function textTransform(rotate) {
                    if (!rotate) {
                        return "";
                    }
                    return "rotate(" + rotate + ")";
                }
                function dxForText(rotate) {
                    if (!rotate) {
                        return 0;
                    }
                    return 8 * Math.sin(Math.PI * (rotate / 180));
                }
                function yForText(rotate) {
                    if (!rotate) {
                        return tickLength;
                    }
                    return 11.5 - 2.5 * (rotate / 15) * (rotate > 0 ? 1 : -1);
                }
                switch (orient) {
                  case "bottom":
                    {
                        tickTransform = axisX;
                        lineEnter.attr("y2", innerTickSize);
                        textEnter.attr("y", tickLength);
                        lineUpdate.attr("x1", tickX).attr("x2", tickX).attr("y2", tickSize);
                        textUpdate.attr("x", 0).attr("y", yForText(rotate)).style("text-anchor", textAnchorForText(rotate)).attr("transform", textTransform(rotate));
                        tspan.attr("x", 0).attr("dy", tspanDy).attr("dx", dxForText(rotate));
                        pathUpdate.attr("d", "M" + range[0] + "," + outerTickSize + "V0H" + range[1] + "V" + outerTickSize);
                        break;
                    }

                  case "top":
                    {
                        tickTransform = axisX;
                        lineEnter.attr("y2", -innerTickSize);
                        textEnter.attr("y", -tickLength);
                        lineUpdate.attr("x2", 0).attr("y2", -innerTickSize);
                        textUpdate.attr("x", 0).attr("y", -tickLength);
                        text.style("text-anchor", "middle");
                        tspan.attr("x", 0).attr("dy", "0em");
                        pathUpdate.attr("d", "M" + range[0] + "," + -outerTickSize + "V0H" + range[1] + "V" + -outerTickSize);
                        break;
                    }

                  case "left":
                    {
                        tickTransform = axisY;
                        lineEnter.attr("x2", -innerTickSize);
                        textEnter.attr("x", -tickLength);
                        lineUpdate.attr("x2", -innerTickSize).attr("y1", tickY).attr("y2", tickY);
                        textUpdate.attr("x", -tickLength).attr("y", tickOffset);
                        text.style("text-anchor", "end");
                        tspan.attr("x", -tickLength).attr("dy", tspanDy);
                        pathUpdate.attr("d", "M" + -outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + -outerTickSize);
                        break;
                    }

                  case "right":
                    {
                        tickTransform = axisY;
                        lineEnter.attr("x2", innerTickSize);
                        textEnter.attr("x", tickLength);
                        lineUpdate.attr("x2", innerTickSize).attr("y2", 0);
                        textUpdate.attr("x", tickLength).attr("y", 0);
                        text.style("text-anchor", "start");
                        tspan.attr("x", tickLength).attr("dy", tspanDy);
                        pathUpdate.attr("d", "M" + outerTickSize + "," + range[0] + "H0V" + range[1] + "H" + outerTickSize);
                        break;
                    }
                }
                if (scale1.rangeBand) {
                    var x = scale1, dx = x.rangeBand() / 2;
                    scale0 = scale1 = function(d) {
                        return x(d) + dx;
                    };
                } else if (scale0.rangeBand) {
                    scale0 = scale1;
                } else {
                    tickExit.call(tickTransform, scale1);
                }
                tickEnter.call(tickTransform, scale0);
                tickUpdate.call(tickTransform, scale1);
            });
        }
        axis.scale = function(x) {
            if (!arguments.length) {
                return scale;
            }
            scale = x;
            return axis;
        };
        axis.orient = function(x) {
            if (!arguments.length) {
                return orient;
            }
            orient = x in {
                top: 1,
                right: 1,
                bottom: 1,
                left: 1
            } ? x + "" : "bottom";
            return axis;
        };
        axis.tickFormat = function(format) {
            if (!arguments.length) {
                return tickFormat;
            }
            tickFormat = format;
            return axis;
        };
        axis.tickCentered = function(isCentered) {
            if (!arguments.length) {
                return tickCentered;
            }
            tickCentered = isCentered;
            return axis;
        };
        axis.tickOffset = function() {
            return tickOffset;
        };
        axis.tickInterval = function() {
            var interval, length;
            if (params.isCategory) {
                interval = tickOffset * 2;
            } else {
                length = axis.g.select("path.domain").node().getTotalLength() - outerTickSize * 2;
                interval = length / axis.g.selectAll("line").size();
            }
            return interval === Infinity ? 0 : interval;
        };
        axis.ticks = function() {
            if (!arguments.length) {
                return tickArguments;
            }
            tickArguments = arguments;
            return axis;
        };
        axis.tickCulling = function(culling) {
            if (!arguments.length) {
                return tickCulling;
            }
            tickCulling = culling;
            return axis;
        };
        axis.tickValues = function(x) {
            if (typeof x === "function") {
                tickValues = function() {
                    return x(scale.domain());
                };
            } else {
                if (!arguments.length) {
                    return tickValues;
                }
                tickValues = x;
            }
            return axis;
        };
        return axis;
    }
    c3_chart_internal_fn.isSafari = function() {
        var ua = window.navigator.userAgent;
        return ua.indexOf("Safari") >= 0 && ua.indexOf("Chrome") < 0;
    };
    c3_chart_internal_fn.isChrome = function() {
        var ua = window.navigator.userAgent;
        return ua.indexOf("Chrome") >= 0;
    };
    if (!Function.prototype.bind) {
        Function.prototype.bind = function(oThis) {
            if (typeof this !== "function") {
                throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
            }
            var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function() {}, fBound = function() {
                return fToBind.apply(this instanceof fNOP ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments)));
            };
            fNOP.prototype = this.prototype;
            fBound.prototype = new fNOP();
            return fBound;
        };
    }
    if (typeof define === "function" && define.amd) {
        define("c3", [ "d3" ], c3);
    } else if ("undefined" !== typeof exports && "undefined" !== typeof module) {
        module.exports = c3;
    } else {
        window.c3 = c3;
    }
})(window);

(function(define) {
    define([ "jquery", "lodash" ], function($, _) {
        return function() {
            var $container;
            var listener;
            var toastId = 0;
            var toastType = {
                alert: "alert",
                info: "info",
                success: "success",
                warning: "warning"
            };
            var toastr = {
                clear: clear,
                remove: remove,
                alert: alert,
                getContainer: getContainer,
                info: info,
                options: {},
                subscribe: subscribe,
                success: success,
                version: "2.0.3",
                warning: warning
            };
            return toastr;
            function alert(title, message, options) {
                return notify({
                    type: toastType.alert,
                    title: title,
                    message: message,
                    options: options
                });
            }
            function info(title, message, options) {
                return notify({
                    type: toastType.info,
                    title: title,
                    message: message,
                    options: options
                });
            }
            function success(title, message, options) {
                return notify({
                    type: toastType.success,
                    title: title,
                    message: message,
                    options: options
                });
            }
            function warning(title, message, options) {
                return notify({
                    type: toastType.warning,
                    title: title,
                    message: message,
                    options: options
                });
            }
            function subscribe(callback) {
                listener = callback;
            }
            function getContainer(options, create) {
                if (!options) {
                    options = getOptions();
                }
                $container = $("#" + options.containerId);
                if ($container.length) {
                    return $container;
                }
                if (create) {
                    $container = createContainer(options);
                }
                return $container;
            }
            function clear($toastElement) {
                var options = getOptions();
                if (!$container) {
                    getContainer(options);
                }
                if (!clearToast($toastElement, options)) {
                    clearContainer(options);
                }
            }
            function remove($toastElement) {
                var options = getOptions();
                if (!$container) {
                    getContainer(options);
                }
                if ($toastElement && $(":focus", $toastElement).length === 0) {
                    removeToast($toastElement);
                    return;
                }
                if ($container.children().length) {
                    $container.remove();
                }
            }
            function clearContainer(options) {
                var toastsToClear = $container.children();
                for (var i = toastsToClear.length - 1; i >= 0; i--) {
                    clearToast($(toastsToClear[i]), options);
                }
            }
            function clearToast($toastElement, options) {
                if ($toastElement && $(":focus", $toastElement).length === 0) {
                    $toastElement[options.hideMethod]({
                        duration: options.hideDuration,
                        easing: options.hideEasing,
                        complete: function() {
                            removeToast($toastElement);
                        }
                    });
                    return true;
                }
                return false;
            }
            function createContainer(options) {
                $container = $("<div/>").attr("id", options.containerId).addClass(options.positionClass).attr("aria-live", "polite").attr("role", "alert");
                $container.appendTo($(options.target));
                return $container;
            }
            function getDefaults() {
                return {
                    tapToDismiss: false,
                    toastClass: "notification",
                    containerId: "notifications-container",
                    debug: false,
                    showMethod: "fadeIn",
                    showDuration: 300,
                    showEasing: "swing",
                    onShown: undefined,
                    hideMethod: "fadeOut",
                    hideDuration: 1e3,
                    hideEasing: "swing",
                    onHidden: undefined,
                    extendedTimeOut: 1e3,
                    onCloseClick: undefined,
                    positionClass: "notification-below-header",
                    timeOut: 5e3,
                    titleClass: "headline",
                    messageClass: "notification-content",
                    closeIcon: "icon icon-times-circle",
                    target: "body",
                    newestOnTop: true
                };
            }
            function publish(args) {
                if (!listener) {
                    return;
                }
                listener(args);
            }
            function getTemplate() {
                return this._template || (this._template = '<div class="{{= toastClass }} {{= toastClass }}-{{= type }}">' + '<div class="notification-header">' + '<p class="{{= titleClass }}">' + '<i class="icon icon-state-{{= type }}"></i>&nbsp;' + '<span class="text">{{= title }}</span>' + '<i class="js-close close-icon {{= closeIcon }}"></i>' + "</p>" + "</div>" + '<div class="{{= messageClass }}" style="display: none;">{{= message }}</div>' + "</div>");
            }
            function notify(map) {
                var globalOptions = getOptions(), options = $.extend(globalOptions, map);
                if (typeof map.options !== "undefined") {
                    options = $.extend(options, map.options);
                }
                toastId++;
                $container = getContainer(options, true);
                var template = _.template(getTemplate())(options), $template = $(template);
                var intervalId = null, $toastElement = $template, $closeElement = $toastElement.find(".js-close"), response = {
                    toastId: toastId,
                    state: "visible",
                    startTime: new Date(),
                    options: options
                };
                if (options.message) {
                    $toastElement.find("." + options.messageClass).show();
                }
                $toastElement.hide();
                if (options.newestOnTop) {
                    $container.prepend($toastElement);
                } else {
                    $container.append($toastElement);
                }
                $toastElement[options.showMethod]({
                    duration: options.showDuration,
                    easing: options.showEasing,
                    complete: options.onShown
                });
                if (options.timeOut > 0) {
                    intervalId = setTimeout(hideToast, options.timeOut);
                }
                $toastElement.hover(stickAround, delayedHideToast);
                if (!options.onclick && options.tapToDismiss) {
                    $toastElement.click(hideToast);
                }
                if ($closeElement) {
                    $closeElement.click(function(event) {
                        if (event.stopPropagation) {
                            event.stopPropagation();
                        } else if (event.cancelBubble !== undefined && event.cancelBubble !== true) {
                            event.cancelBubble = true;
                        }
                        if (options.onCloseClick) {
                            options.onCloseClick(event);
                        }
                        hideToast(true);
                    });
                }
                if (options.onclick) {
                    $toastElement.click(function() {
                        options.onclick();
                        hideToast();
                    });
                }
                publish(response);
                if (options.debug && console) {
                    console.log(response);
                }
                return $toastElement;
                function hideToast(override) {
                    if ($(":focus", $toastElement).length && !override) {
                        return;
                    }
                    return $toastElement[options.hideMethod]({
                        duration: options.hideDuration,
                        easing: options.hideEasing,
                        complete: function() {
                            removeToast($toastElement);
                            if (options.onHidden && response.state !== "hidden") {
                                options.onHidden();
                            }
                            response.state = "hidden";
                            response.endTime = new Date();
                            publish(response);
                        }
                    });
                }
                function delayedHideToast() {
                    if (options.timeOut > 0 || options.extendedTimeOut > 0) {
                        intervalId = setTimeout(hideToast, options.extendedTimeOut);
                    }
                }
                function stickAround() {
                    clearTimeout(intervalId);
                    $toastElement.stop(true, true)[options.showMethod]({
                        duration: options.showDuration,
                        easing: options.showEasing
                    });
                }
            }
            function getOptions() {
                return $.extend({}, getDefaults(), toastr.options);
            }
            function removeToast($toastElement) {
                if (!$container) {
                    $container = getContainer();
                }
                if ($toastElement.is(":visible")) {
                    return;
                }
                $toastElement.remove();
                $toastElement = null;
                if ($container.children().length === 0) {
                    $container.remove();
                }
            }
        }();
    });
})(typeof define === "function" && define.amd ? define : function(deps, factory) {
    if (typeof module !== "undefined" && module.exports) {
        module.exports = factory(require("jquery", "lodash"));
    } else {
        window["toastr"] = factory(window["jQuery"], window["_"]);
    }
});

(function(global, factory) {
    typeof exports === "object" && typeof module !== "undefined" ? module.exports = factory() : typeof define === "function" && define.amd ? define(factory) : global.moment = factory();
})(this, function() {
    "use strict";
    var hookCallback;
    function hooks() {
        return hookCallback.apply(null, arguments);
    }
    function setHookCallback(callback) {
        hookCallback = callback;
    }
    function isArray(input) {
        return input instanceof Array || Object.prototype.toString.call(input) === "[object Array]";
    }
    function isObject(input) {
        return input != null && Object.prototype.toString.call(input) === "[object Object]";
    }
    function isObjectEmpty(obj) {
        if (Object.getOwnPropertyNames) {
            return Object.getOwnPropertyNames(obj).length === 0;
        } else {
            var k;
            for (k in obj) {
                if (obj.hasOwnProperty(k)) {
                    return false;
                }
            }
            return true;
        }
    }
    function isUndefined(input) {
        return input === void 0;
    }
    function isNumber(input) {
        return typeof input === "number" || Object.prototype.toString.call(input) === "[object Number]";
    }
    function isDate(input) {
        return input instanceof Date || Object.prototype.toString.call(input) === "[object Date]";
    }
    function map(arr, fn) {
        var res = [], i;
        for (i = 0; i < arr.length; ++i) {
            res.push(fn(arr[i], i));
        }
        return res;
    }
    function hasOwnProp(a, b) {
        return Object.prototype.hasOwnProperty.call(a, b);
    }
    function extend(a, b) {
        for (var i in b) {
            if (hasOwnProp(b, i)) {
                a[i] = b[i];
            }
        }
        if (hasOwnProp(b, "toString")) {
            a.toString = b.toString;
        }
        if (hasOwnProp(b, "valueOf")) {
            a.valueOf = b.valueOf;
        }
        return a;
    }
    function createUTC(input, format, locale, strict) {
        return createLocalOrUTC(input, format, locale, strict, true).utc();
    }
    function defaultParsingFlags() {
        return {
            empty: false,
            unusedTokens: [],
            unusedInput: [],
            overflow: -2,
            charsLeftOver: 0,
            nullInput: false,
            invalidMonth: null,
            invalidFormat: false,
            userInvalidated: false,
            iso: false,
            parsedDateParts: [],
            meridiem: null,
            rfc2822: false,
            weekdayMismatch: false
        };
    }
    function getParsingFlags(m) {
        if (m._pf == null) {
            m._pf = defaultParsingFlags();
        }
        return m._pf;
    }
    var some;
    if (Array.prototype.some) {
        some = Array.prototype.some;
    } else {
        some = function(fun) {
            var t = Object(this);
            var len = t.length >>> 0;
            for (var i = 0; i < len; i++) {
                if (i in t && fun.call(this, t[i], i, t)) {
                    return true;
                }
            }
            return false;
        };
    }
    function isValid(m) {
        if (m._isValid == null) {
            var flags = getParsingFlags(m);
            var parsedParts = some.call(flags.parsedDateParts, function(i) {
                return i != null;
            });
            var isNowValid = !isNaN(m._d.getTime()) && flags.overflow < 0 && !flags.empty && !flags.invalidMonth && !flags.invalidWeekday && !flags.weekdayMismatch && !flags.nullInput && !flags.invalidFormat && !flags.userInvalidated && (!flags.meridiem || flags.meridiem && parsedParts);
            if (m._strict) {
                isNowValid = isNowValid && flags.charsLeftOver === 0 && flags.unusedTokens.length === 0 && flags.bigHour === undefined;
            }
            if (Object.isFrozen == null || !Object.isFrozen(m)) {
                m._isValid = isNowValid;
            } else {
                return isNowValid;
            }
        }
        return m._isValid;
    }
    function createInvalid(flags) {
        var m = createUTC(NaN);
        if (flags != null) {
            extend(getParsingFlags(m), flags);
        } else {
            getParsingFlags(m).userInvalidated = true;
        }
        return m;
    }
    var momentProperties = hooks.momentProperties = [];
    function copyConfig(to, from) {
        var i, prop, val;
        if (!isUndefined(from._isAMomentObject)) {
            to._isAMomentObject = from._isAMomentObject;
        }
        if (!isUndefined(from._i)) {
            to._i = from._i;
        }
        if (!isUndefined(from._f)) {
            to._f = from._f;
        }
        if (!isUndefined(from._l)) {
            to._l = from._l;
        }
        if (!isUndefined(from._strict)) {
            to._strict = from._strict;
        }
        if (!isUndefined(from._tzm)) {
            to._tzm = from._tzm;
        }
        if (!isUndefined(from._isUTC)) {
            to._isUTC = from._isUTC;
        }
        if (!isUndefined(from._offset)) {
            to._offset = from._offset;
        }
        if (!isUndefined(from._pf)) {
            to._pf = getParsingFlags(from);
        }
        if (!isUndefined(from._locale)) {
            to._locale = from._locale;
        }
        if (momentProperties.length > 0) {
            for (i = 0; i < momentProperties.length; i++) {
                prop = momentProperties[i];
                val = from[prop];
                if (!isUndefined(val)) {
                    to[prop] = val;
                }
            }
        }
        return to;
    }
    var updateInProgress = false;
    function Moment(config) {
        copyConfig(this, config);
        this._d = new Date(config._d != null ? config._d.getTime() : NaN);
        if (!this.isValid()) {
            this._d = new Date(NaN);
        }
        if (updateInProgress === false) {
            updateInProgress = true;
            hooks.updateOffset(this);
            updateInProgress = false;
        }
    }
    function isMoment(obj) {
        return obj instanceof Moment || obj != null && obj._isAMomentObject != null;
    }
    function absFloor(number) {
        if (number < 0) {
            return Math.ceil(number) || 0;
        } else {
            return Math.floor(number);
        }
    }
    function toInt(argumentForCoercion) {
        var coercedNumber = +argumentForCoercion, value = 0;
        if (coercedNumber !== 0 && isFinite(coercedNumber)) {
            value = absFloor(coercedNumber);
        }
        return value;
    }
    function compareArrays(array1, array2, dontConvert) {
        var len = Math.min(array1.length, array2.length), lengthDiff = Math.abs(array1.length - array2.length), diffs = 0, i;
        for (i = 0; i < len; i++) {
            if (dontConvert && array1[i] !== array2[i] || !dontConvert && toInt(array1[i]) !== toInt(array2[i])) {
                diffs++;
            }
        }
        return diffs + lengthDiff;
    }
    function warn(msg) {
        if (hooks.suppressDeprecationWarnings === false && typeof console !== "undefined" && console.warn) {
            console.warn("Deprecation warning: " + msg);
        }
    }
    function deprecate(msg, fn) {
        var firstTime = true;
        return extend(function() {
            if (hooks.deprecationHandler != null) {
                hooks.deprecationHandler(null, msg);
            }
            if (firstTime) {
                var args = [];
                var arg;
                for (var i = 0; i < arguments.length; i++) {
                    arg = "";
                    if (typeof arguments[i] === "object") {
                        arg += "\n[" + i + "] ";
                        for (var key in arguments[0]) {
                            arg += key + ": " + arguments[0][key] + ", ";
                        }
                        arg = arg.slice(0, -2);
                    } else {
                        arg = arguments[i];
                    }
                    args.push(arg);
                }
                warn(msg + "\nArguments: " + Array.prototype.slice.call(args).join("") + "\n" + new Error().stack);
                firstTime = false;
            }
            return fn.apply(this, arguments);
        }, fn);
    }
    var deprecations = {};
    function deprecateSimple(name, msg) {
        if (hooks.deprecationHandler != null) {
            hooks.deprecationHandler(name, msg);
        }
        if (!deprecations[name]) {
            warn(msg);
            deprecations[name] = true;
        }
    }
    hooks.suppressDeprecationWarnings = false;
    hooks.deprecationHandler = null;
    function isFunction(input) {
        return input instanceof Function || Object.prototype.toString.call(input) === "[object Function]";
    }
    function set(config) {
        var prop, i;
        for (i in config) {
            prop = config[i];
            if (isFunction(prop)) {
                this[i] = prop;
            } else {
                this["_" + i] = prop;
            }
        }
        this._config = config;
        this._dayOfMonthOrdinalParseLenient = new RegExp((this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) + "|" + /\d{1,2}/.source);
    }
    function mergeConfigs(parentConfig, childConfig) {
        var res = extend({}, parentConfig), prop;
        for (prop in childConfig) {
            if (hasOwnProp(childConfig, prop)) {
                if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
                    res[prop] = {};
                    extend(res[prop], parentConfig[prop]);
                    extend(res[prop], childConfig[prop]);
                } else if (childConfig[prop] != null) {
                    res[prop] = childConfig[prop];
                } else {
                    delete res[prop];
                }
            }
        }
        for (prop in parentConfig) {
            if (hasOwnProp(parentConfig, prop) && !hasOwnProp(childConfig, prop) && isObject(parentConfig[prop])) {
                res[prop] = extend({}, res[prop]);
            }
        }
        return res;
    }
    function Locale(config) {
        if (config != null) {
            this.set(config);
        }
    }
    var keys;
    if (Object.keys) {
        keys = Object.keys;
    } else {
        keys = function(obj) {
            var i, res = [];
            for (i in obj) {
                if (hasOwnProp(obj, i)) {
                    res.push(i);
                }
            }
            return res;
        };
    }
    var defaultCalendar = {
        sameDay: "[Today at] LT",
        nextDay: "[Tomorrow at] LT",
        nextWeek: "dddd [at] LT",
        lastDay: "[Yesterday at] LT",
        lastWeek: "[Last] dddd [at] LT",
        sameElse: "L"
    };
    function calendar(key, mom, now) {
        var output = this._calendar[key] || this._calendar["sameElse"];
        return isFunction(output) ? output.call(mom, now) : output;
    }
    var defaultLongDateFormat = {
        LTS: "h:mm:ss A",
        LT: "h:mm A",
        L: "MM/DD/YYYY",
        LL: "MMMM D, YYYY",
        LLL: "MMMM D, YYYY h:mm A",
        LLLL: "dddd, MMMM D, YYYY h:mm A"
    };
    function longDateFormat(key) {
        var format = this._longDateFormat[key], formatUpper = this._longDateFormat[key.toUpperCase()];
        if (format || !formatUpper) {
            return format;
        }
        this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function(val) {
            return val.slice(1);
        });
        return this._longDateFormat[key];
    }
    var defaultInvalidDate = "Invalid date";
    function invalidDate() {
        return this._invalidDate;
    }
    var defaultOrdinal = "%d";
    var defaultDayOfMonthOrdinalParse = /\d{1,2}/;
    function ordinal(number) {
        return this._ordinal.replace("%d", number);
    }
    var defaultRelativeTime = {
        future: "in %s",
        past: "%s ago",
        s: "a few seconds",
        ss: "%d seconds",
        m: "a minute",
        mm: "%d minutes",
        h: "an hour",
        hh: "%d hours",
        d: "a day",
        dd: "%d days",
        M: "a month",
        MM: "%d months",
        y: "a year",
        yy: "%d years"
    };
    function relativeTime(number, withoutSuffix, string, isFuture) {
        var output = this._relativeTime[string];
        return isFunction(output) ? output(number, withoutSuffix, string, isFuture) : output.replace(/%d/i, number);
    }
    function pastFuture(diff, output) {
        var format = this._relativeTime[diff > 0 ? "future" : "past"];
        return isFunction(format) ? format(output) : format.replace(/%s/i, output);
    }
    var aliases = {};
    function addUnitAlias(unit, shorthand) {
        var lowerCase = unit.toLowerCase();
        aliases[lowerCase] = aliases[lowerCase + "s"] = aliases[shorthand] = unit;
    }
    function normalizeUnits(units) {
        return typeof units === "string" ? aliases[units] || aliases[units.toLowerCase()] : undefined;
    }
    function normalizeObjectUnits(inputObject) {
        var normalizedInput = {}, normalizedProp, prop;
        for (prop in inputObject) {
            if (hasOwnProp(inputObject, prop)) {
                normalizedProp = normalizeUnits(prop);
                if (normalizedProp) {
                    normalizedInput[normalizedProp] = inputObject[prop];
                }
            }
        }
        return normalizedInput;
    }
    var priorities = {};
    function addUnitPriority(unit, priority) {
        priorities[unit] = priority;
    }
    function getPrioritizedUnits(unitsObj) {
        var units = [];
        for (var u in unitsObj) {
            units.push({
                unit: u,
                priority: priorities[u]
            });
        }
        units.sort(function(a, b) {
            return a.priority - b.priority;
        });
        return units;
    }
    function zeroFill(number, targetLength, forceSign) {
        var absNumber = "" + Math.abs(number), zerosToFill = targetLength - absNumber.length, sign = number >= 0;
        return (sign ? forceSign ? "+" : "" : "-") + Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
    }
    var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;
    var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
    var formatFunctions = {};
    var formatTokenFunctions = {};
    function addFormatToken(token, padded, ordinal, callback) {
        var func = callback;
        if (typeof callback === "string") {
            func = function() {
                return this[callback]();
            };
        }
        if (token) {
            formatTokenFunctions[token] = func;
        }
        if (padded) {
            formatTokenFunctions[padded[0]] = function() {
                return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
            };
        }
        if (ordinal) {
            formatTokenFunctions[ordinal] = function() {
                return this.localeData().ordinal(func.apply(this, arguments), token);
            };
        }
    }
    function removeFormattingTokens(input) {
        if (input.match(/\[[\s\S]/)) {
            return input.replace(/^\[|\]$/g, "");
        }
        return input.replace(/\\/g, "");
    }
    function makeFormatFunction(format) {
        var array = format.match(formattingTokens), i, length;
        for (i = 0, length = array.length; i < length; i++) {
            if (formatTokenFunctions[array[i]]) {
                array[i] = formatTokenFunctions[array[i]];
            } else {
                array[i] = removeFormattingTokens(array[i]);
            }
        }
        return function(mom) {
            var output = "", i;
            for (i = 0; i < length; i++) {
                output += isFunction(array[i]) ? array[i].call(mom, format) : array[i];
            }
            return output;
        };
    }
    function formatMoment(m, format) {
        if (!m.isValid()) {
            return m.localeData().invalidDate();
        }
        format = expandFormat(format, m.localeData());
        formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);
        return formatFunctions[format](m);
    }
    function expandFormat(format, locale) {
        var i = 5;
        function replaceLongDateFormatTokens(input) {
            return locale.longDateFormat(input) || input;
        }
        localFormattingTokens.lastIndex = 0;
        while (i >= 0 && localFormattingTokens.test(format)) {
            format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
            localFormattingTokens.lastIndex = 0;
            i -= 1;
        }
        return format;
    }
    var match1 = /\d/;
    var match2 = /\d\d/;
    var match3 = /\d{3}/;
    var match4 = /\d{4}/;
    var match6 = /[+-]?\d{6}/;
    var match1to2 = /\d\d?/;
    var match3to4 = /\d\d\d\d?/;
    var match5to6 = /\d\d\d\d\d\d?/;
    var match1to3 = /\d{1,3}/;
    var match1to4 = /\d{1,4}/;
    var match1to6 = /[+-]?\d{1,6}/;
    var matchUnsigned = /\d+/;
    var matchSigned = /[+-]?\d+/;
    var matchOffset = /Z|[+-]\d\d:?\d\d/gi;
    var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi;
    var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/;
    var matchWord = /[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i;
    var regexes = {};
    function addRegexToken(token, regex, strictRegex) {
        regexes[token] = isFunction(regex) ? regex : function(isStrict, localeData) {
            return isStrict && strictRegex ? strictRegex : regex;
        };
    }
    function getParseRegexForToken(token, config) {
        if (!hasOwnProp(regexes, token)) {
            return new RegExp(unescapeFormat(token));
        }
        return regexes[token](config._strict, config._locale);
    }
    function unescapeFormat(s) {
        return regexEscape(s.replace("\\", "").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function(matched, p1, p2, p3, p4) {
            return p1 || p2 || p3 || p4;
        }));
    }
    function regexEscape(s) {
        return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&");
    }
    var tokens = {};
    function addParseToken(token, callback) {
        var i, func = callback;
        if (typeof token === "string") {
            token = [ token ];
        }
        if (isNumber(callback)) {
            func = function(input, array) {
                array[callback] = toInt(input);
            };
        }
        for (i = 0; i < token.length; i++) {
            tokens[token[i]] = func;
        }
    }
    function addWeekParseToken(token, callback) {
        addParseToken(token, function(input, array, config, token) {
            config._w = config._w || {};
            callback(input, config._w, config, token);
        });
    }
    function addTimeToArrayFromToken(token, input, config) {
        if (input != null && hasOwnProp(tokens, token)) {
            tokens[token](input, config._a, config, token);
        }
    }
    var YEAR = 0;
    var MONTH = 1;
    var DATE = 2;
    var HOUR = 3;
    var MINUTE = 4;
    var SECOND = 5;
    var MILLISECOND = 6;
    var WEEK = 7;
    var WEEKDAY = 8;
    addFormatToken("Y", 0, 0, function() {
        var y = this.year();
        return y <= 9999 ? "" + y : "+" + y;
    });
    addFormatToken(0, [ "YY", 2 ], 0, function() {
        return this.year() % 100;
    });
    addFormatToken(0, [ "YYYY", 4 ], 0, "year");
    addFormatToken(0, [ "YYYYY", 5 ], 0, "year");
    addFormatToken(0, [ "YYYYYY", 6, true ], 0, "year");
    addUnitAlias("year", "y");
    addUnitPriority("year", 1);
    addRegexToken("Y", matchSigned);
    addRegexToken("YY", match1to2, match2);
    addRegexToken("YYYY", match1to4, match4);
    addRegexToken("YYYYY", match1to6, match6);
    addRegexToken("YYYYYY", match1to6, match6);
    addParseToken([ "YYYYY", "YYYYYY" ], YEAR);
    addParseToken("YYYY", function(input, array) {
        array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input);
    });
    addParseToken("YY", function(input, array) {
        array[YEAR] = hooks.parseTwoDigitYear(input);
    });
    addParseToken("Y", function(input, array) {
        array[YEAR] = parseInt(input, 10);
    });
    function daysInYear(year) {
        return isLeapYear(year) ? 366 : 365;
    }
    function isLeapYear(year) {
        return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0;
    }
    hooks.parseTwoDigitYear = function(input) {
        return toInt(input) + (toInt(input) > 68 ? 1900 : 2e3);
    };
    var getSetYear = makeGetSet("FullYear", true);
    function getIsLeapYear() {
        return isLeapYear(this.year());
    }
    function makeGetSet(unit, keepTime) {
        return function(value) {
            if (value != null) {
                set$1(this, unit, value);
                hooks.updateOffset(this, keepTime);
                return this;
            } else {
                return get(this, unit);
            }
        };
    }
    function get(mom, unit) {
        return mom.isValid() ? mom._d["get" + (mom._isUTC ? "UTC" : "") + unit]() : NaN;
    }
    function set$1(mom, unit, value) {
        if (mom.isValid() && !isNaN(value)) {
            if (unit === "FullYear" && isLeapYear(mom.year()) && mom.month() === 1 && mom.date() === 29) {
                mom._d["set" + (mom._isUTC ? "UTC" : "") + unit](value, mom.month(), daysInMonth(value, mom.month()));
            } else {
                mom._d["set" + (mom._isUTC ? "UTC" : "") + unit](value);
            }
        }
    }
    function stringGet(units) {
        units = normalizeUnits(units);
        if (isFunction(this[units])) {
            return this[units]();
        }
        return this;
    }
    function stringSet(units, value) {
        if (typeof units === "object") {
            units = normalizeObjectUnits(units);
            var prioritized = getPrioritizedUnits(units);
            for (var i = 0; i < prioritized.length; i++) {
                this[prioritized[i].unit](units[prioritized[i].unit]);
            }
        } else {
            units = normalizeUnits(units);
            if (isFunction(this[units])) {
                return this[units](value);
            }
        }
        return this;
    }
    function mod(n, x) {
        return (n % x + x) % x;
    }
    var indexOf;
    if (Array.prototype.indexOf) {
        indexOf = Array.prototype.indexOf;
    } else {
        indexOf = function(o) {
            var i;
            for (i = 0; i < this.length; ++i) {
                if (this[i] === o) {
                    return i;
                }
            }
            return -1;
        };
    }
    function daysInMonth(year, month) {
        if (isNaN(year) || isNaN(month)) {
            return NaN;
        }
        var modMonth = mod(month, 12);
        year += (month - modMonth) / 12;
        return modMonth === 1 ? isLeapYear(year) ? 29 : 28 : 31 - modMonth % 7 % 2;
    }
    addFormatToken("M", [ "MM", 2 ], "Mo", function() {
        return this.month() + 1;
    });
    addFormatToken("MMM", 0, 0, function(format) {
        return this.localeData().monthsShort(this, format);
    });
    addFormatToken("MMMM", 0, 0, function(format) {
        return this.localeData().months(this, format);
    });
    addUnitAlias("month", "M");
    addUnitPriority("month", 8);
    addRegexToken("M", match1to2);
    addRegexToken("MM", match1to2, match2);
    addRegexToken("MMM", function(isStrict, locale) {
        return locale.monthsShortRegex(isStrict);
    });
    addRegexToken("MMMM", function(isStrict, locale) {
        return locale.monthsRegex(isStrict);
    });
    addParseToken([ "M", "MM" ], function(input, array) {
        array[MONTH] = toInt(input) - 1;
    });
    addParseToken([ "MMM", "MMMM" ], function(input, array, config, token) {
        var month = config._locale.monthsParse(input, token, config._strict);
        if (month != null) {
            array[MONTH] = month;
        } else {
            getParsingFlags(config).invalidMonth = input;
        }
    });
    var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/;
    var defaultLocaleMonths = "January_February_March_April_May_June_July_August_September_October_November_December".split("_");
    function localeMonths(m, format) {
        if (!m) {
            return isArray(this._months) ? this._months : this._months["standalone"];
        }
        return isArray(this._months) ? this._months[m.month()] : this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? "format" : "standalone"][m.month()];
    }
    var defaultLocaleMonthsShort = "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_");
    function localeMonthsShort(m, format) {
        if (!m) {
            return isArray(this._monthsShort) ? this._monthsShort : this._monthsShort["standalone"];
        }
        return isArray(this._monthsShort) ? this._monthsShort[m.month()] : this._monthsShort[MONTHS_IN_FORMAT.test(format) ? "format" : "standalone"][m.month()];
    }
    function handleStrictParse(monthName, format, strict) {
        var i, ii, mom, llc = monthName.toLocaleLowerCase();
        if (!this._monthsParse) {
            this._monthsParse = [];
            this._longMonthsParse = [];
            this._shortMonthsParse = [];
            for (i = 0; i < 12; ++i) {
                mom = createUTC([ 2e3, i ]);
                this._shortMonthsParse[i] = this.monthsShort(mom, "").toLocaleLowerCase();
                this._longMonthsParse[i] = this.months(mom, "").toLocaleLowerCase();
            }
        }
        if (strict) {
            if (format === "MMM") {
                ii = indexOf.call(this._shortMonthsParse, llc);
                return ii !== -1 ? ii : null;
            } else {
                ii = indexOf.call(this._longMonthsParse, llc);
                return ii !== -1 ? ii : null;
            }
        } else {
            if (format === "MMM") {
                ii = indexOf.call(this._shortMonthsParse, llc);
                if (ii !== -1) {
                    return ii;
                }
                ii = indexOf.call(this._longMonthsParse, llc);
                return ii !== -1 ? ii : null;
            } else {
                ii = indexOf.call(this._longMonthsParse, llc);
                if (ii !== -1) {
                    return ii;
                }
                ii = indexOf.call(this._shortMonthsParse, llc);
                return ii !== -1 ? ii : null;
            }
        }
    }
    function localeMonthsParse(monthName, format, strict) {
        var i, mom, regex;
        if (this._monthsParseExact) {
            return handleStrictParse.call(this, monthName, format, strict);
        }
        if (!this._monthsParse) {
            this._monthsParse = [];
            this._longMonthsParse = [];
            this._shortMonthsParse = [];
        }
        for (i = 0; i < 12; i++) {
            mom = createUTC([ 2e3, i ]);
            if (strict && !this._longMonthsParse[i]) {
                this._longMonthsParse[i] = new RegExp("^" + this.months(mom, "").replace(".", "") + "$", "i");
                this._shortMonthsParse[i] = new RegExp("^" + this.monthsShort(mom, "").replace(".", "") + "$", "i");
            }
            if (!strict && !this._monthsParse[i]) {
                regex = "^" + this.months(mom, "") + "|^" + this.monthsShort(mom, "");
                this._monthsParse[i] = new RegExp(regex.replace(".", ""), "i");
            }
            if (strict && format === "MMMM" && this._longMonthsParse[i].test(monthName)) {
                return i;
            } else if (strict && format === "MMM" && this._shortMonthsParse[i].test(monthName)) {
                return i;
            } else if (!strict && this._monthsParse[i].test(monthName)) {
                return i;
            }
        }
    }
    function setMonth(mom, value) {
        var dayOfMonth;
        if (!mom.isValid()) {
            return mom;
        }
        if (typeof value === "string") {
            if (/^\d+$/.test(value)) {
                value = toInt(value);
            } else {
                value = mom.localeData().monthsParse(value);
                if (!isNumber(value)) {
                    return mom;
                }
            }
        }
        dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
        mom._d["set" + (mom._isUTC ? "UTC" : "") + "Month"](value, dayOfMonth);
        return mom;
    }
    function getSetMonth(value) {
        if (value != null) {
            setMonth(this, value);
            hooks.updateOffset(this, true);
            return this;
        } else {
            return get(this, "Month");
        }
    }
    function getDaysInMonth() {
        return daysInMonth(this.year(), this.month());
    }
    var defaultMonthsShortRegex = matchWord;
    function monthsShortRegex(isStrict) {
        if (this._monthsParseExact) {
            if (!hasOwnProp(this, "_monthsRegex")) {
                computeMonthsParse.call(this);
            }
            if (isStrict) {
                return this._monthsShortStrictRegex;
            } else {
                return this._monthsShortRegex;
            }
        } else {
            if (!hasOwnProp(this, "_monthsShortRegex")) {
                this._monthsShortRegex = defaultMonthsShortRegex;
            }
            return this._monthsShortStrictRegex && isStrict ? this._monthsShortStrictRegex : this._monthsShortRegex;
        }
    }
    var defaultMonthsRegex = matchWord;
    function monthsRegex(isStrict) {
        if (this._monthsParseExact) {
            if (!hasOwnProp(this, "_monthsRegex")) {
                computeMonthsParse.call(this);
            }
            if (isStrict) {
                return this._monthsStrictRegex;
            } else {
                return this._monthsRegex;
            }
        } else {
            if (!hasOwnProp(this, "_monthsRegex")) {
                this._monthsRegex = defaultMonthsRegex;
            }
            return this._monthsStrictRegex && isStrict ? this._monthsStrictRegex : this._monthsRegex;
        }
    }
    function computeMonthsParse() {
        function cmpLenRev(a, b) {
            return b.length - a.length;
        }
        var shortPieces = [], longPieces = [], mixedPieces = [], i, mom;
        for (i = 0; i < 12; i++) {
            mom = createUTC([ 2e3, i ]);
            shortPieces.push(this.monthsShort(mom, ""));
            longPieces.push(this.months(mom, ""));
            mixedPieces.push(this.months(mom, ""));
            mixedPieces.push(this.monthsShort(mom, ""));
        }
        shortPieces.sort(cmpLenRev);
        longPieces.sort(cmpLenRev);
        mixedPieces.sort(cmpLenRev);
        for (i = 0; i < 12; i++) {
            shortPieces[i] = regexEscape(shortPieces[i]);
            longPieces[i] = regexEscape(longPieces[i]);
        }
        for (i = 0; i < 24; i++) {
            mixedPieces[i] = regexEscape(mixedPieces[i]);
        }
        this._monthsRegex = new RegExp("^(" + mixedPieces.join("|") + ")", "i");
        this._monthsShortRegex = this._monthsRegex;
        this._monthsStrictRegex = new RegExp("^(" + longPieces.join("|") + ")", "i");
        this._monthsShortStrictRegex = new RegExp("^(" + shortPieces.join("|") + ")", "i");
    }
    function createDate(y, m, d, h, M, s, ms) {
        var date;
        if (y < 100 && y >= 0) {
            date = new Date(y + 400, m, d, h, M, s, ms);
            if (isFinite(date.getFullYear())) {
                date.setFullYear(y);
            }
        } else {
            date = new Date(y, m, d, h, M, s, ms);
        }
        return date;
    }
    function createUTCDate(y) {
        var date;
        if (y < 100 && y >= 0) {
            var args = Array.prototype.slice.call(arguments);
            args[0] = y + 400;
            date = new Date(Date.UTC.apply(null, args));
            if (isFinite(date.getUTCFullYear())) {
                date.setUTCFullYear(y);
            }
        } else {
            date = new Date(Date.UTC.apply(null, arguments));
        }
        return date;
    }
    function firstWeekOffset(year, dow, doy) {
        var fwd = 7 + dow - doy, fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
        return -fwdlw + fwd - 1;
    }
    function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
        var localWeekday = (7 + weekday - dow) % 7, weekOffset = firstWeekOffset(year, dow, doy), dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset, resYear, resDayOfYear;
        if (dayOfYear <= 0) {
            resYear = year - 1;
            resDayOfYear = daysInYear(resYear) + dayOfYear;
        } else if (dayOfYear > daysInYear(year)) {
            resYear = year + 1;
            resDayOfYear = dayOfYear - daysInYear(year);
        } else {
            resYear = year;
            resDayOfYear = dayOfYear;
        }
        return {
            year: resYear,
            dayOfYear: resDayOfYear
        };
    }
    function weekOfYear(mom, dow, doy) {
        var weekOffset = firstWeekOffset(mom.year(), dow, doy), week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1, resWeek, resYear;
        if (week < 1) {
            resYear = mom.year() - 1;
            resWeek = week + weeksInYear(resYear, dow, doy);
        } else if (week > weeksInYear(mom.year(), dow, doy)) {
            resWeek = week - weeksInYear(mom.year(), dow, doy);
            resYear = mom.year() + 1;
        } else {
            resYear = mom.year();
            resWeek = week;
        }
        return {
            week: resWeek,
            year: resYear
        };
    }
    function weeksInYear(year, dow, doy) {
        var weekOffset = firstWeekOffset(year, dow, doy), weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
        return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
    }
    addFormatToken("w", [ "ww", 2 ], "wo", "week");
    addFormatToken("W", [ "WW", 2 ], "Wo", "isoWeek");
    addUnitAlias("week", "w");
    addUnitAlias("isoWeek", "W");
    addUnitPriority("week", 5);
    addUnitPriority("isoWeek", 5);
    addRegexToken("w", match1to2);
    addRegexToken("ww", match1to2, match2);
    addRegexToken("W", match1to2);
    addRegexToken("WW", match1to2, match2);
    addWeekParseToken([ "w", "ww", "W", "WW" ], function(input, week, config, token) {
        week[token.substr(0, 1)] = toInt(input);
    });
    function localeWeek(mom) {
        return weekOfYear(mom, this._week.dow, this._week.doy).week;
    }
    var defaultLocaleWeek = {
        dow: 0,
        doy: 6
    };
    function localeFirstDayOfWeek() {
        return this._week.dow;
    }
    function localeFirstDayOfYear() {
        return this._week.doy;
    }
    function getSetWeek(input) {
        var week = this.localeData().week(this);
        return input == null ? week : this.add((input - week) * 7, "d");
    }
    function getSetISOWeek(input) {
        var week = weekOfYear(this, 1, 4).week;
        return input == null ? week : this.add((input - week) * 7, "d");
    }
    addFormatToken("d", 0, "do", "day");
    addFormatToken("dd", 0, 0, function(format) {
        return this.localeData().weekdaysMin(this, format);
    });
    addFormatToken("ddd", 0, 0, function(format) {
        return this.localeData().weekdaysShort(this, format);
    });
    addFormatToken("dddd", 0, 0, function(format) {
        return this.localeData().weekdays(this, format);
    });
    addFormatToken("e", 0, 0, "weekday");
    addFormatToken("E", 0, 0, "isoWeekday");
    addUnitAlias("day", "d");
    addUnitAlias("weekday", "e");
    addUnitAlias("isoWeekday", "E");
    addUnitPriority("day", 11);
    addUnitPriority("weekday", 11);
    addUnitPriority("isoWeekday", 11);
    addRegexToken("d", match1to2);
    addRegexToken("e", match1to2);
    addRegexToken("E", match1to2);
    addRegexToken("dd", function(isStrict, locale) {
        return locale.weekdaysMinRegex(isStrict);
    });
    addRegexToken("ddd", function(isStrict, locale) {
        return locale.weekdaysShortRegex(isStrict);
    });
    addRegexToken("dddd", function(isStrict, locale) {
        return locale.weekdaysRegex(isStrict);
    });
    addWeekParseToken([ "dd", "ddd", "dddd" ], function(input, week, config, token) {
        var weekday = config._locale.weekdaysParse(input, token, config._strict);
        if (weekday != null) {
            week.d = weekday;
        } else {
            getParsingFlags(config).invalidWeekday = input;
        }
    });
    addWeekParseToken([ "d", "e", "E" ], function(input, week, config, token) {
        week[token] = toInt(input);
    });
    function parseWeekday(input, locale) {
        if (typeof input !== "string") {
            return input;
        }
        if (!isNaN(input)) {
            return parseInt(input, 10);
        }
        input = locale.weekdaysParse(input);
        if (typeof input === "number") {
            return input;
        }
        return null;
    }
    function parseIsoWeekday(input, locale) {
        if (typeof input === "string") {
            return locale.weekdaysParse(input) % 7 || 7;
        }
        return isNaN(input) ? null : input;
    }
    function shiftWeekdays(ws, n) {
        return ws.slice(n, 7).concat(ws.slice(0, n));
    }
    var defaultLocaleWeekdays = "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_");
    function localeWeekdays(m, format) {
        var weekdays = isArray(this._weekdays) ? this._weekdays : this._weekdays[m && m !== true && this._weekdays.isFormat.test(format) ? "format" : "standalone"];
        return m === true ? shiftWeekdays(weekdays, this._week.dow) : m ? weekdays[m.day()] : weekdays;
    }
    var defaultLocaleWeekdaysShort = "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_");
    function localeWeekdaysShort(m) {
        return m === true ? shiftWeekdays(this._weekdaysShort, this._week.dow) : m ? this._weekdaysShort[m.day()] : this._weekdaysShort;
    }
    var defaultLocaleWeekdaysMin = "Su_Mo_Tu_We_Th_Fr_Sa".split("_");
    function localeWeekdaysMin(m) {
        return m === true ? shiftWeekdays(this._weekdaysMin, this._week.dow) : m ? this._weekdaysMin[m.day()] : this._weekdaysMin;
    }
    function handleStrictParse$1(weekdayName, format, strict) {
        var i, ii, mom, llc = weekdayName.toLocaleLowerCase();
        if (!this._weekdaysParse) {
            this._weekdaysParse = [];
            this._shortWeekdaysParse = [];
            this._minWeekdaysParse = [];
            for (i = 0; i < 7; ++i) {
                mom = createUTC([ 2e3, 1 ]).day(i);
                this._minWeekdaysParse[i] = this.weekdaysMin(mom, "").toLocaleLowerCase();
                this._shortWeekdaysParse[i] = this.weekdaysShort(mom, "").toLocaleLowerCase();
                this._weekdaysParse[i] = this.weekdays(mom, "").toLocaleLowerCase();
            }
        }
        if (strict) {
            if (format === "dddd") {
                ii = indexOf.call(this._weekdaysParse, llc);
                return ii !== -1 ? ii : null;
            } else if (format === "ddd") {
                ii = indexOf.call(this._shortWeekdaysParse, llc);
                return ii !== -1 ? ii : null;
            } else {
                ii = indexOf.call(this._minWeekdaysParse, llc);
                return ii !== -1 ? ii : null;
            }
        } else {
            if (format === "dddd") {
                ii = indexOf.call(this._weekdaysParse, llc);
                if (ii !== -1) {
                    return ii;
                }
                ii = indexOf.call(this._shortWeekdaysParse, llc);
                if (ii !== -1) {
                    return ii;
                }
                ii = indexOf.call(this._minWeekdaysParse, llc);
                return ii !== -1 ? ii : null;
            } else if (format === "ddd") {
                ii = indexOf.call(this._shortWeekdaysParse, llc);
                if (ii !== -1) {
                    return ii;
                }
                ii = indexOf.call(this._weekdaysParse, llc);
                if (ii !== -1) {
                    return ii;
                }
                ii = indexOf.call(this._minWeekdaysParse, llc);
                return ii !== -1 ? ii : null;
            } else {
                ii = indexOf.call(this._minWeekdaysParse, llc);
                if (ii !== -1) {
                    return ii;
                }
                ii = indexOf.call(this._weekdaysParse, llc);
                if (ii !== -1) {
                    return ii;
                }
                ii = indexOf.call(this._shortWeekdaysParse, llc);
                return ii !== -1 ? ii : null;
            }
        }
    }
    function localeWeekdaysParse(weekdayName, format, strict) {
        var i, mom, regex;
        if (this._weekdaysParseExact) {
            return handleStrictParse$1.call(this, weekdayName, format, strict);
        }
        if (!this._weekdaysParse) {
            this._weekdaysParse = [];
            this._minWeekdaysParse = [];
            this._shortWeekdaysParse = [];
            this._fullWeekdaysParse = [];
        }
        for (i = 0; i < 7; i++) {
            mom = createUTC([ 2e3, 1 ]).day(i);
            if (strict && !this._fullWeekdaysParse[i]) {
                this._fullWeekdaysParse[i] = new RegExp("^" + this.weekdays(mom, "").replace(".", "\\.?") + "$", "i");
                this._shortWeekdaysParse[i] = new RegExp("^" + this.weekdaysShort(mom, "").replace(".", "\\.?") + "$", "i");
                this._minWeekdaysParse[i] = new RegExp("^" + this.weekdaysMin(mom, "").replace(".", "\\.?") + "$", "i");
            }
            if (!this._weekdaysParse[i]) {
                regex = "^" + this.weekdays(mom, "") + "|^" + this.weekdaysShort(mom, "") + "|^" + this.weekdaysMin(mom, "");
                this._weekdaysParse[i] = new RegExp(regex.replace(".", ""), "i");
            }
            if (strict && format === "dddd" && this._fullWeekdaysParse[i].test(weekdayName)) {
                return i;
            } else if (strict && format === "ddd" && this._shortWeekdaysParse[i].test(weekdayName)) {
                return i;
            } else if (strict && format === "dd" && this._minWeekdaysParse[i].test(weekdayName)) {
                return i;
            } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
                return i;
            }
        }
    }
    function getSetDayOfWeek(input) {
        if (!this.isValid()) {
            return input != null ? this : NaN;
        }
        var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
        if (input != null) {
            input = parseWeekday(input, this.localeData());
            return this.add(input - day, "d");
        } else {
            return day;
        }
    }
    function getSetLocaleDayOfWeek(input) {
        if (!this.isValid()) {
            return input != null ? this : NaN;
        }
        var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
        return input == null ? weekday : this.add(input - weekday, "d");
    }
    function getSetISODayOfWeek(input) {
        if (!this.isValid()) {
            return input != null ? this : NaN;
        }
        if (input != null) {
            var weekday = parseIsoWeekday(input, this.localeData());
            return this.day(this.day() % 7 ? weekday : weekday - 7);
        } else {
            return this.day() || 7;
        }
    }
    var defaultWeekdaysRegex = matchWord;
    function weekdaysRegex(isStrict) {
        if (this._weekdaysParseExact) {
            if (!hasOwnProp(this, "_weekdaysRegex")) {
                computeWeekdaysParse.call(this);
            }
            if (isStrict) {
                return this._weekdaysStrictRegex;
            } else {
                return this._weekdaysRegex;
            }
        } else {
            if (!hasOwnProp(this, "_weekdaysRegex")) {
                this._weekdaysRegex = defaultWeekdaysRegex;
            }
            return this._weekdaysStrictRegex && isStrict ? this._weekdaysStrictRegex : this._weekdaysRegex;
        }
    }
    var defaultWeekdaysShortRegex = matchWord;
    function weekdaysShortRegex(isStrict) {
        if (this._weekdaysParseExact) {
            if (!hasOwnProp(this, "_weekdaysRegex")) {
                computeWeekdaysParse.call(this);
            }
            if (isStrict) {
                return this._weekdaysShortStrictRegex;
            } else {
                return this._weekdaysShortRegex;
            }
        } else {
            if (!hasOwnProp(this, "_weekdaysShortRegex")) {
                this._weekdaysShortRegex = defaultWeekdaysShortRegex;
            }
            return this._weekdaysShortStrictRegex && isStrict ? this._weekdaysShortStrictRegex : this._weekdaysShortRegex;
        }
    }
    var defaultWeekdaysMinRegex = matchWord;
    function weekdaysMinRegex(isStrict) {
        if (this._weekdaysParseExact) {
            if (!hasOwnProp(this, "_weekdaysRegex")) {
                computeWeekdaysParse.call(this);
            }
            if (isStrict) {
                return this._weekdaysMinStrictRegex;
            } else {
                return this._weekdaysMinRegex;
            }
        } else {
            if (!hasOwnProp(this, "_weekdaysMinRegex")) {
                this._weekdaysMinRegex = defaultWeekdaysMinRegex;
            }
            return this._weekdaysMinStrictRegex && isStrict ? this._weekdaysMinStrictRegex : this._weekdaysMinRegex;
        }
    }
    function computeWeekdaysParse() {
        function cmpLenRev(a, b) {
            return b.length - a.length;
        }
        var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [], i, mom, minp, shortp, longp;
        for (i = 0; i < 7; i++) {
            mom = createUTC([ 2e3, 1 ]).day(i);
            minp = this.weekdaysMin(mom, "");
            shortp = this.weekdaysShort(mom, "");
            longp = this.weekdays(mom, "");
            minPieces.push(minp);
            shortPieces.push(shortp);
            longPieces.push(longp);
            mixedPieces.push(minp);
            mixedPieces.push(shortp);
            mixedPieces.push(longp);
        }
        minPieces.sort(cmpLenRev);
        shortPieces.sort(cmpLenRev);
        longPieces.sort(cmpLenRev);
        mixedPieces.sort(cmpLenRev);
        for (i = 0; i < 7; i++) {
            shortPieces[i] = regexEscape(shortPieces[i]);
            longPieces[i] = regexEscape(longPieces[i]);
            mixedPieces[i] = regexEscape(mixedPieces[i]);
        }
        this._weekdaysRegex = new RegExp("^(" + mixedPieces.join("|") + ")", "i");
        this._weekdaysShortRegex = this._weekdaysRegex;
        this._weekdaysMinRegex = this._weekdaysRegex;
        this._weekdaysStrictRegex = new RegExp("^(" + longPieces.join("|") + ")", "i");
        this._weekdaysShortStrictRegex = new RegExp("^(" + shortPieces.join("|") + ")", "i");
        this._weekdaysMinStrictRegex = new RegExp("^(" + minPieces.join("|") + ")", "i");
    }
    function hFormat() {
        return this.hours() % 12 || 12;
    }
    function kFormat() {
        return this.hours() || 24;
    }
    addFormatToken("H", [ "HH", 2 ], 0, "hour");
    addFormatToken("h", [ "hh", 2 ], 0, hFormat);
    addFormatToken("k", [ "kk", 2 ], 0, kFormat);
    addFormatToken("hmm", 0, 0, function() {
        return "" + hFormat.apply(this) + zeroFill(this.minutes(), 2);
    });
    addFormatToken("hmmss", 0, 0, function() {
        return "" + hFormat.apply(this) + zeroFill(this.minutes(), 2) + zeroFill(this.seconds(), 2);
    });
    addFormatToken("Hmm", 0, 0, function() {
        return "" + this.hours() + zeroFill(this.minutes(), 2);
    });
    addFormatToken("Hmmss", 0, 0, function() {
        return "" + this.hours() + zeroFill(this.minutes(), 2) + zeroFill(this.seconds(), 2);
    });
    function meridiem(token, lowercase) {
        addFormatToken(token, 0, 0, function() {
            return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
        });
    }
    meridiem("a", true);
    meridiem("A", false);
    addUnitAlias("hour", "h");
    addUnitPriority("hour", 13);
    function matchMeridiem(isStrict, locale) {
        return locale._meridiemParse;
    }
    addRegexToken("a", matchMeridiem);
    addRegexToken("A", matchMeridiem);
    addRegexToken("H", match1to2);
    addRegexToken("h", match1to2);
    addRegexToken("k", match1to2);
    addRegexToken("HH", match1to2, match2);
    addRegexToken("hh", match1to2, match2);
    addRegexToken("kk", match1to2, match2);
    addRegexToken("hmm", match3to4);
    addRegexToken("hmmss", match5to6);
    addRegexToken("Hmm", match3to4);
    addRegexToken("Hmmss", match5to6);
    addParseToken([ "H", "HH" ], HOUR);
    addParseToken([ "k", "kk" ], function(input, array, config) {
        var kInput = toInt(input);
        array[HOUR] = kInput === 24 ? 0 : kInput;
    });
    addParseToken([ "a", "A" ], function(input, array, config) {
        config._isPm = config._locale.isPM(input);
        config._meridiem = input;
    });
    addParseToken([ "h", "hh" ], function(input, array, config) {
        array[HOUR] = toInt(input);
        getParsingFlags(config).bigHour = true;
    });
    addParseToken("hmm", function(input, array, config) {
        var pos = input.length - 2;
        array[HOUR] = toInt(input.substr(0, pos));
        array[MINUTE] = toInt(input.substr(pos));
        getParsingFlags(config).bigHour = true;
    });
    addParseToken("hmmss", function(input, array, config) {
        var pos1 = input.length - 4;
        var pos2 = input.length - 2;
        array[HOUR] = toInt(input.substr(0, pos1));
        array[MINUTE] = toInt(input.substr(pos1, 2));
        array[SECOND] = toInt(input.substr(pos2));
        getParsingFlags(config).bigHour = true;
    });
    addParseToken("Hmm", function(input, array, config) {
        var pos = input.length - 2;
        array[HOUR] = toInt(input.substr(0, pos));
        array[MINUTE] = toInt(input.substr(pos));
    });
    addParseToken("Hmmss", function(input, array, config) {
        var pos1 = input.length - 4;
        var pos2 = input.length - 2;
        array[HOUR] = toInt(input.substr(0, pos1));
        array[MINUTE] = toInt(input.substr(pos1, 2));
        array[SECOND] = toInt(input.substr(pos2));
    });
    function localeIsPM(input) {
        return (input + "").toLowerCase().charAt(0) === "p";
    }
    var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
    function localeMeridiem(hours, minutes, isLower) {
        if (hours > 11) {
            return isLower ? "pm" : "PM";
        } else {
            return isLower ? "am" : "AM";
        }
    }
    var getSetHour = makeGetSet("Hours", true);
    var baseConfig = {
        calendar: defaultCalendar,
        longDateFormat: defaultLongDateFormat,
        invalidDate: defaultInvalidDate,
        ordinal: defaultOrdinal,
        dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse,
        relativeTime: defaultRelativeTime,
        months: defaultLocaleMonths,
        monthsShort: defaultLocaleMonthsShort,
        week: defaultLocaleWeek,
        weekdays: defaultLocaleWeekdays,
        weekdaysMin: defaultLocaleWeekdaysMin,
        weekdaysShort: defaultLocaleWeekdaysShort,
        meridiemParse: defaultLocaleMeridiemParse
    };
    var locales = {};
    var localeFamilies = {};
    var globalLocale;
    function normalizeLocale(key) {
        return key ? key.toLowerCase().replace("_", "-") : key;
    }
    function chooseLocale(names) {
        var i = 0, j, next, locale, split;
        while (i < names.length) {
            split = normalizeLocale(names[i]).split("-");
            j = split.length;
            next = normalizeLocale(names[i + 1]);
            next = next ? next.split("-") : null;
            while (j > 0) {
                locale = loadLocale(split.slice(0, j).join("-"));
                if (locale) {
                    return locale;
                }
                if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
                    break;
                }
                j--;
            }
            i++;
        }
        return globalLocale;
    }
    function loadLocale(name) {
        var oldLocale = null;
        if (!locales[name] && typeof module !== "undefined" && module && module.exports) {
            try {
                oldLocale = globalLocale._abbr;
                var aliasedRequire = require;
                aliasedRequire("./locale/" + name);
                getSetGlobalLocale(oldLocale);
            } catch (e) {}
        }
        return locales[name];
    }
    function getSetGlobalLocale(key, values) {
        var data;
        if (key) {
            if (isUndefined(values)) {
                data = getLocale(key);
            } else {
                data = defineLocale(key, values);
            }
            if (data) {
                globalLocale = data;
            } else {
                if (typeof console !== "undefined" && console.warn) {
                    console.warn("Locale " + key + " not found. Did you forget to load it?");
                }
            }
        }
        return globalLocale._abbr;
    }
    function defineLocale(name, config) {
        if (config !== null) {
            var locale, parentConfig = baseConfig;
            config.abbr = name;
            if (locales[name] != null) {
                deprecateSimple("defineLocaleOverride", "use moment.updateLocale(localeName, config) to change " + "an existing locale. moment.defineLocale(localeName, " + "config) should only be used for creating a new locale " + "See http://momentjs.com/guides/#/warnings/define-locale/ for more info.");
                parentConfig = locales[name]._config;
            } else if (config.parentLocale != null) {
                if (locales[config.parentLocale] != null) {
                    parentConfig = locales[config.parentLocale]._config;
                } else {
                    locale = loadLocale(config.parentLocale);
                    if (locale != null) {
                        parentConfig = locale._config;
                    } else {
                        if (!localeFamilies[config.parentLocale]) {
                            localeFamilies[config.parentLocale] = [];
                        }
                        localeFamilies[config.parentLocale].push({
                            name: name,
                            config: config
                        });
                        return null;
                    }
                }
            }
            locales[name] = new Locale(mergeConfigs(parentConfig, config));
            if (localeFamilies[name]) {
                localeFamilies[name].forEach(function(x) {
                    defineLocale(x.name, x.config);
                });
            }
            getSetGlobalLocale(name);
            return locales[name];
        } else {
            delete locales[name];
            return null;
        }
    }
    function updateLocale(name, config) {
        if (config != null) {
            var locale, tmpLocale, parentConfig = baseConfig;
            tmpLocale = loadLocale(name);
            if (tmpLocale != null) {
                parentConfig = tmpLocale._config;
            }
            config = mergeConfigs(parentConfig, config);
            locale = new Locale(config);
            locale.parentLocale = locales[name];
            locales[name] = locale;
            getSetGlobalLocale(name);
        } else {
            if (locales[name] != null) {
                if (locales[name].parentLocale != null) {
                    locales[name] = locales[name].parentLocale;
                } else if (locales[name] != null) {
                    delete locales[name];
                }
            }
        }
        return locales[name];
    }
    function getLocale(key) {
        var locale;
        if (key && key._locale && key._locale._abbr) {
            key = key._locale._abbr;
        }
        if (!key) {
            return globalLocale;
        }
        if (!isArray(key)) {
            locale = loadLocale(key);
            if (locale) {
                return locale;
            }
            key = [ key ];
        }
        return chooseLocale(key);
    }
    function listLocales() {
        return keys(locales);
    }
    function checkOverflow(m) {
        var overflow;
        var a = m._a;
        if (a && getParsingFlags(m).overflow === -2) {
            overflow = a[MONTH] < 0 || a[MONTH] > 11 ? MONTH : a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE : a[HOUR] < 0 || a[HOUR] > 24 || a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0) ? HOUR : a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE : a[SECOND] < 0 || a[SECOND] > 59 ? SECOND : a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND : -1;
            if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
                overflow = DATE;
            }
            if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
                overflow = WEEK;
            }
            if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
                overflow = WEEKDAY;
            }
            getParsingFlags(m).overflow = overflow;
        }
        return m;
    }
    function defaults(a, b, c) {
        if (a != null) {
            return a;
        }
        if (b != null) {
            return b;
        }
        return c;
    }
    function currentDateArray(config) {
        var nowValue = new Date(hooks.now());
        if (config._useUTC) {
            return [ nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate() ];
        }
        return [ nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate() ];
    }
    function configFromArray(config) {
        var i, date, input = [], currentDate, expectedWeekday, yearToUse;
        if (config._d) {
            return;
        }
        currentDate = currentDateArray(config);
        if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
            dayOfYearFromWeekInfo(config);
        }
        if (config._dayOfYear != null) {
            yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
            if (config._dayOfYear > daysInYear(yearToUse) || config._dayOfYear === 0) {
                getParsingFlags(config)._overflowDayOfYear = true;
            }
            date = createUTCDate(yearToUse, 0, config._dayOfYear);
            config._a[MONTH] = date.getUTCMonth();
            config._a[DATE] = date.getUTCDate();
        }
        for (i = 0; i < 3 && config._a[i] == null; ++i) {
            config._a[i] = input[i] = currentDate[i];
        }
        for (;i < 7; i++) {
            config._a[i] = input[i] = config._a[i] == null ? i === 2 ? 1 : 0 : config._a[i];
        }
        if (config._a[HOUR] === 24 && config._a[MINUTE] === 0 && config._a[SECOND] === 0 && config._a[MILLISECOND] === 0) {
            config._nextDay = true;
            config._a[HOUR] = 0;
        }
        config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
        expectedWeekday = config._useUTC ? config._d.getUTCDay() : config._d.getDay();
        if (config._tzm != null) {
            config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
        }
        if (config._nextDay) {
            config._a[HOUR] = 24;
        }
        if (config._w && typeof config._w.d !== "undefined" && config._w.d !== expectedWeekday) {
            getParsingFlags(config).weekdayMismatch = true;
        }
    }
    function dayOfYearFromWeekInfo(config) {
        var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;
        w = config._w;
        if (w.GG != null || w.W != null || w.E != null) {
            dow = 1;
            doy = 4;
            weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(createLocal(), 1, 4).year);
            week = defaults(w.W, 1);
            weekday = defaults(w.E, 1);
            if (weekday < 1 || weekday > 7) {
                weekdayOverflow = true;
            }
        } else {
            dow = config._locale._week.dow;
            doy = config._locale._week.doy;
            var curWeek = weekOfYear(createLocal(), dow, doy);
            weekYear = defaults(w.gg, config._a[YEAR], curWeek.year);
            week = defaults(w.w, curWeek.week);
            if (w.d != null) {
                weekday = w.d;
                if (weekday < 0 || weekday > 6) {
                    weekdayOverflow = true;
                }
            } else if (w.e != null) {
                weekday = w.e + dow;
                if (w.e < 0 || w.e > 6) {
                    weekdayOverflow = true;
                }
            } else {
                weekday = dow;
            }
        }
        if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
            getParsingFlags(config)._overflowWeeks = true;
        } else if (weekdayOverflow != null) {
            getParsingFlags(config)._overflowWeekday = true;
        } else {
            temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
            config._a[YEAR] = temp.year;
            config._dayOfYear = temp.dayOfYear;
        }
    }
    var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
    var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
    var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;
    var isoDates = [ [ "YYYYYY-MM-DD", /[+-]\d{6}-\d\d-\d\d/ ], [ "YYYY-MM-DD", /\d{4}-\d\d-\d\d/ ], [ "GGGG-[W]WW-E", /\d{4}-W\d\d-\d/ ], [ "GGGG-[W]WW", /\d{4}-W\d\d/, false ], [ "YYYY-DDD", /\d{4}-\d{3}/ ], [ "YYYY-MM", /\d{4}-\d\d/, false ], [ "YYYYYYMMDD", /[+-]\d{10}/ ], [ "YYYYMMDD", /\d{8}/ ], [ "GGGG[W]WWE", /\d{4}W\d{3}/ ], [ "GGGG[W]WW", /\d{4}W\d{2}/, false ], [ "YYYYDDD", /\d{7}/ ] ];
    var isoTimes = [ [ "HH:mm:ss.SSSS", /\d\d:\d\d:\d\d\.\d+/ ], [ "HH:mm:ss,SSSS", /\d\d:\d\d:\d\d,\d+/ ], [ "HH:mm:ss", /\d\d:\d\d:\d\d/ ], [ "HH:mm", /\d\d:\d\d/ ], [ "HHmmss.SSSS", /\d\d\d\d\d\d\.\d+/ ], [ "HHmmss,SSSS", /\d\d\d\d\d\d,\d+/ ], [ "HHmmss", /\d\d\d\d\d\d/ ], [ "HHmm", /\d\d\d\d/ ], [ "HH", /\d\d/ ] ];
    var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;
    function configFromISO(config) {
        var i, l, string = config._i, match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string), allowTime, dateFormat, timeFormat, tzFormat;
        if (match) {
            getParsingFlags(config).iso = true;
            for (i = 0, l = isoDates.length; i < l; i++) {
                if (isoDates[i][1].exec(match[1])) {
                    dateFormat = isoDates[i][0];
                    allowTime = isoDates[i][2] !== false;
                    break;
                }
            }
            if (dateFormat == null) {
                config._isValid = false;
                return;
            }
            if (match[3]) {
                for (i = 0, l = isoTimes.length; i < l; i++) {
                    if (isoTimes[i][1].exec(match[3])) {
                        timeFormat = (match[2] || " ") + isoTimes[i][0];
                        break;
                    }
                }
                if (timeFormat == null) {
                    config._isValid = false;
                    return;
                }
            }
            if (!allowTime && timeFormat != null) {
                config._isValid = false;
                return;
            }
            if (match[4]) {
                if (tzRegex.exec(match[4])) {
                    tzFormat = "Z";
                } else {
                    config._isValid = false;
                    return;
                }
            }
            config._f = dateFormat + (timeFormat || "") + (tzFormat || "");
            configFromStringAndFormat(config);
        } else {
            config._isValid = false;
        }
    }
    var rfc2822 = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;
    function extractFromRFC2822Strings(yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) {
        var result = [ untruncateYear(yearStr), defaultLocaleMonthsShort.indexOf(monthStr), parseInt(dayStr, 10), parseInt(hourStr, 10), parseInt(minuteStr, 10) ];
        if (secondStr) {
            result.push(parseInt(secondStr, 10));
        }
        return result;
    }
    function untruncateYear(yearStr) {
        var year = parseInt(yearStr, 10);
        if (year <= 49) {
            return 2e3 + year;
        } else if (year <= 999) {
            return 1900 + year;
        }
        return year;
    }
    function preprocessRFC2822(s) {
        return s.replace(/\([^)]*\)|[\n\t]/g, " ").replace(/(\s\s+)/g, " ").replace(/^\s\s*/, "").replace(/\s\s*$/, "");
    }
    function checkWeekday(weekdayStr, parsedInput, config) {
        if (weekdayStr) {
            var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr), weekdayActual = new Date(parsedInput[0], parsedInput[1], parsedInput[2]).getDay();
            if (weekdayProvided !== weekdayActual) {
                getParsingFlags(config).weekdayMismatch = true;
                config._isValid = false;
                return false;
            }
        }
        return true;
    }
    var obsOffsets = {
        UT: 0,
        GMT: 0,
        EDT: -4 * 60,
        EST: -5 * 60,
        CDT: -5 * 60,
        CST: -6 * 60,
        MDT: -6 * 60,
        MST: -7 * 60,
        PDT: -7 * 60,
        PST: -8 * 60
    };
    function calculateOffset(obsOffset, militaryOffset, numOffset) {
        if (obsOffset) {
            return obsOffsets[obsOffset];
        } else if (militaryOffset) {
            return 0;
        } else {
            var hm = parseInt(numOffset, 10);
            var m = hm % 100, h = (hm - m) / 100;
            return h * 60 + m;
        }
    }
    function configFromRFC2822(config) {
        var match = rfc2822.exec(preprocessRFC2822(config._i));
        if (match) {
            var parsedArray = extractFromRFC2822Strings(match[4], match[3], match[2], match[5], match[6], match[7]);
            if (!checkWeekday(match[1], parsedArray, config)) {
                return;
            }
            config._a = parsedArray;
            config._tzm = calculateOffset(match[8], match[9], match[10]);
            config._d = createUTCDate.apply(null, config._a);
            config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
            getParsingFlags(config).rfc2822 = true;
        } else {
            config._isValid = false;
        }
    }
    function configFromString(config) {
        var matched = aspNetJsonRegex.exec(config._i);
        if (matched !== null) {
            config._d = new Date(+matched[1]);
            return;
        }
        configFromISO(config);
        if (config._isValid === false) {
            delete config._isValid;
        } else {
            return;
        }
        configFromRFC2822(config);
        if (config._isValid === false) {
            delete config._isValid;
        } else {
            return;
        }
        hooks.createFromInputFallback(config);
    }
    hooks.createFromInputFallback = deprecate("value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), " + "which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are " + "discouraged and will be removed in an upcoming major release. Please refer to " + "http://momentjs.com/guides/#/warnings/js-date/ for more info.", function(config) {
        config._d = new Date(config._i + (config._useUTC ? " UTC" : ""));
    });
    hooks.ISO_8601 = function() {};
    hooks.RFC_2822 = function() {};
    function configFromStringAndFormat(config) {
        if (config._f === hooks.ISO_8601) {
            configFromISO(config);
            return;
        }
        if (config._f === hooks.RFC_2822) {
            configFromRFC2822(config);
            return;
        }
        config._a = [];
        getParsingFlags(config).empty = true;
        var string = "" + config._i, i, parsedInput, tokens, token, skipped, stringLength = string.length, totalParsedInputLength = 0;
        tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
        for (i = 0; i < tokens.length; i++) {
            token = tokens[i];
            parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
            if (parsedInput) {
                skipped = string.substr(0, string.indexOf(parsedInput));
                if (skipped.length > 0) {
                    getParsingFlags(config).unusedInput.push(skipped);
                }
                string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
                totalParsedInputLength += parsedInput.length;
            }
            if (formatTokenFunctions[token]) {
                if (parsedInput) {
                    getParsingFlags(config).empty = false;
                } else {
                    getParsingFlags(config).unusedTokens.push(token);
                }
                addTimeToArrayFromToken(token, parsedInput, config);
            } else if (config._strict && !parsedInput) {
                getParsingFlags(config).unusedTokens.push(token);
            }
        }
        getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
        if (string.length > 0) {
            getParsingFlags(config).unusedInput.push(string);
        }
        if (config._a[HOUR] <= 12 && getParsingFlags(config).bigHour === true && config._a[HOUR] > 0) {
            getParsingFlags(config).bigHour = undefined;
        }
        getParsingFlags(config).parsedDateParts = config._a.slice(0);
        getParsingFlags(config).meridiem = config._meridiem;
        config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);
        configFromArray(config);
        checkOverflow(config);
    }
    function meridiemFixWrap(locale, hour, meridiem) {
        var isPm;
        if (meridiem == null) {
            return hour;
        }
        if (locale.meridiemHour != null) {
            return locale.meridiemHour(hour, meridiem);
        } else if (locale.isPM != null) {
            isPm = locale.isPM(meridiem);
            if (isPm && hour < 12) {
                hour += 12;
            }
            if (!isPm && hour === 12) {
                hour = 0;
            }
            return hour;
        } else {
            return hour;
        }
    }
    function configFromStringAndArray(config) {
        var tempConfig, bestMoment, scoreToBeat, i, currentScore;
        if (config._f.length === 0) {
            getParsingFlags(config).invalidFormat = true;
            config._d = new Date(NaN);
            return;
        }
        for (i = 0; i < config._f.length; i++) {
            currentScore = 0;
            tempConfig = copyConfig({}, config);
            if (config._useUTC != null) {
                tempConfig._useUTC = config._useUTC;
            }
            tempConfig._f = config._f[i];
            configFromStringAndFormat(tempConfig);
            if (!isValid(tempConfig)) {
                continue;
            }
            currentScore += getParsingFlags(tempConfig).charsLeftOver;
            currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
            getParsingFlags(tempConfig).score = currentScore;
            if (scoreToBeat == null || currentScore < scoreToBeat) {
                scoreToBeat = currentScore;
                bestMoment = tempConfig;
            }
        }
        extend(config, bestMoment || tempConfig);
    }
    function configFromObject(config) {
        if (config._d) {
            return;
        }
        var i = normalizeObjectUnits(config._i);
        config._a = map([ i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond ], function(obj) {
            return obj && parseInt(obj, 10);
        });
        configFromArray(config);
    }
    function createFromConfig(config) {
        var res = new Moment(checkOverflow(prepareConfig(config)));
        if (res._nextDay) {
            res.add(1, "d");
            res._nextDay = undefined;
        }
        return res;
    }
    function prepareConfig(config) {
        var input = config._i, format = config._f;
        config._locale = config._locale || getLocale(config._l);
        if (input === null || format === undefined && input === "") {
            return createInvalid({
                nullInput: true
            });
        }
        if (typeof input === "string") {
            config._i = input = config._locale.preparse(input);
        }
        if (isMoment(input)) {
            return new Moment(checkOverflow(input));
        } else if (isDate(input)) {
            config._d = input;
        } else if (isArray(format)) {
            configFromStringAndArray(config);
        } else if (format) {
            configFromStringAndFormat(config);
        } else {
            configFromInput(config);
        }
        if (!isValid(config)) {
            config._d = null;
        }
        return config;
    }
    function configFromInput(config) {
        var input = config._i;
        if (isUndefined(input)) {
            config._d = new Date(hooks.now());
        } else if (isDate(input)) {
            config._d = new Date(input.valueOf());
        } else if (typeof input === "string") {
            configFromString(config);
        } else if (isArray(input)) {
            config._a = map(input.slice(0), function(obj) {
                return parseInt(obj, 10);
            });
            configFromArray(config);
        } else if (isObject(input)) {
            configFromObject(config);
        } else if (isNumber(input)) {
            config._d = new Date(input);
        } else {
            hooks.createFromInputFallback(config);
        }
    }
    function createLocalOrUTC(input, format, locale, strict, isUTC) {
        var c = {};
        if (locale === true || locale === false) {
            strict = locale;
            locale = undefined;
        }
        if (isObject(input) && isObjectEmpty(input) || isArray(input) && input.length === 0) {
            input = undefined;
        }
        c._isAMomentObject = true;
        c._useUTC = c._isUTC = isUTC;
        c._l = locale;
        c._i = input;
        c._f = format;
        c._strict = strict;
        return createFromConfig(c);
    }
    function createLocal(input, format, locale, strict) {
        return createLocalOrUTC(input, format, locale, strict, false);
    }
    var prototypeMin = deprecate("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/", function() {
        var other = createLocal.apply(null, arguments);
        if (this.isValid() && other.isValid()) {
            return other < this ? this : other;
        } else {
            return createInvalid();
        }
    });
    var prototypeMax = deprecate("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/", function() {
        var other = createLocal.apply(null, arguments);
        if (this.isValid() && other.isValid()) {
            return other > this ? this : other;
        } else {
            return createInvalid();
        }
    });
    function pickBy(fn, moments) {
        var res, i;
        if (moments.length === 1 && isArray(moments[0])) {
            moments = moments[0];
        }
        if (!moments.length) {
            return createLocal();
        }
        res = moments[0];
        for (i = 1; i < moments.length; ++i) {
            if (!moments[i].isValid() || moments[i][fn](res)) {
                res = moments[i];
            }
        }
        return res;
    }
    function min() {
        var args = [].slice.call(arguments, 0);
        return pickBy("isBefore", args);
    }
    function max() {
        var args = [].slice.call(arguments, 0);
        return pickBy("isAfter", args);
    }
    var now = function() {
        return Date.now ? Date.now() : +new Date();
    };
    var ordering = [ "year", "quarter", "month", "week", "day", "hour", "minute", "second", "millisecond" ];
    function isDurationValid(m) {
        for (var key in m) {
            if (!(indexOf.call(ordering, key) !== -1 && (m[key] == null || !isNaN(m[key])))) {
                return false;
            }
        }
        var unitHasDecimal = false;
        for (var i = 0; i < ordering.length; ++i) {
            if (m[ordering[i]]) {
                if (unitHasDecimal) {
                    return false;
                }
                if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) {
                    unitHasDecimal = true;
                }
            }
        }
        return true;
    }
    function isValid$1() {
        return this._isValid;
    }
    function createInvalid$1() {
        return createDuration(NaN);
    }
    function Duration(duration) {
        var normalizedInput = normalizeObjectUnits(duration), years = normalizedInput.year || 0, quarters = normalizedInput.quarter || 0, months = normalizedInput.month || 0, weeks = normalizedInput.week || normalizedInput.isoWeek || 0, days = normalizedInput.day || 0, hours = normalizedInput.hour || 0, minutes = normalizedInput.minute || 0, seconds = normalizedInput.second || 0, milliseconds = normalizedInput.millisecond || 0;
        this._isValid = isDurationValid(normalizedInput);
        this._milliseconds = +milliseconds + seconds * 1e3 + minutes * 6e4 + hours * 1e3 * 60 * 60;
        this._days = +days + weeks * 7;
        this._months = +months + quarters * 3 + years * 12;
        this._data = {};
        this._locale = getLocale();
        this._bubble();
    }
    function isDuration(obj) {
        return obj instanceof Duration;
    }
    function absRound(number) {
        if (number < 0) {
            return Math.round(-1 * number) * -1;
        } else {
            return Math.round(number);
        }
    }
    function offset(token, separator) {
        addFormatToken(token, 0, 0, function() {
            var offset = this.utcOffset();
            var sign = "+";
            if (offset < 0) {
                offset = -offset;
                sign = "-";
            }
            return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~offset % 60, 2);
        });
    }
    offset("Z", ":");
    offset("ZZ", "");
    addRegexToken("Z", matchShortOffset);
    addRegexToken("ZZ", matchShortOffset);
    addParseToken([ "Z", "ZZ" ], function(input, array, config) {
        config._useUTC = true;
        config._tzm = offsetFromString(matchShortOffset, input);
    });
    var chunkOffset = /([\+\-]|\d\d)/gi;
    function offsetFromString(matcher, string) {
        var matches = (string || "").match(matcher);
        if (matches === null) {
            return null;
        }
        var chunk = matches[matches.length - 1] || [];
        var parts = (chunk + "").match(chunkOffset) || [ "-", 0, 0 ];
        var minutes = +(parts[1] * 60) + toInt(parts[2]);
        return minutes === 0 ? 0 : parts[0] === "+" ? minutes : -minutes;
    }
    function cloneWithOffset(input, model) {
        var res, diff;
        if (model._isUTC) {
            res = model.clone();
            diff = (isMoment(input) || isDate(input) ? input.valueOf() : createLocal(input).valueOf()) - res.valueOf();
            res._d.setTime(res._d.valueOf() + diff);
            hooks.updateOffset(res, false);
            return res;
        } else {
            return createLocal(input).local();
        }
    }
    function getDateOffset(m) {
        return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
    }
    hooks.updateOffset = function() {};
    function getSetOffset(input, keepLocalTime, keepMinutes) {
        var offset = this._offset || 0, localAdjust;
        if (!this.isValid()) {
            return input != null ? this : NaN;
        }
        if (input != null) {
            if (typeof input === "string") {
                input = offsetFromString(matchShortOffset, input);
                if (input === null) {
                    return this;
                }
            } else if (Math.abs(input) < 16 && !keepMinutes) {
                input = input * 60;
            }
            if (!this._isUTC && keepLocalTime) {
                localAdjust = getDateOffset(this);
            }
            this._offset = input;
            this._isUTC = true;
            if (localAdjust != null) {
                this.add(localAdjust, "m");
            }
            if (offset !== input) {
                if (!keepLocalTime || this._changeInProgress) {
                    addSubtract(this, createDuration(input - offset, "m"), 1, false);
                } else if (!this._changeInProgress) {
                    this._changeInProgress = true;
                    hooks.updateOffset(this, true);
                    this._changeInProgress = null;
                }
            }
            return this;
        } else {
            return this._isUTC ? offset : getDateOffset(this);
        }
    }
    function getSetZone(input, keepLocalTime) {
        if (input != null) {
            if (typeof input !== "string") {
                input = -input;
            }
            this.utcOffset(input, keepLocalTime);
            return this;
        } else {
            return -this.utcOffset();
        }
    }
    function setOffsetToUTC(keepLocalTime) {
        return this.utcOffset(0, keepLocalTime);
    }
    function setOffsetToLocal(keepLocalTime) {
        if (this._isUTC) {
            this.utcOffset(0, keepLocalTime);
            this._isUTC = false;
            if (keepLocalTime) {
                this.subtract(getDateOffset(this), "m");
            }
        }
        return this;
    }
    function setOffsetToParsedOffset() {
        if (this._tzm != null) {
            this.utcOffset(this._tzm, false, true);
        } else if (typeof this._i === "string") {
            var tZone = offsetFromString(matchOffset, this._i);
            if (tZone != null) {
                this.utcOffset(tZone);
            } else {
                this.utcOffset(0, true);
            }
        }
        return this;
    }
    function hasAlignedHourOffset(input) {
        if (!this.isValid()) {
            return false;
        }
        input = input ? createLocal(input).utcOffset() : 0;
        return (this.utcOffset() - input) % 60 === 0;
    }
    function isDaylightSavingTime() {
        return this.utcOffset() > this.clone().month(0).utcOffset() || this.utcOffset() > this.clone().month(5).utcOffset();
    }
    function isDaylightSavingTimeShifted() {
        if (!isUndefined(this._isDSTShifted)) {
            return this._isDSTShifted;
        }
        var c = {};
        copyConfig(c, this);
        c = prepareConfig(c);
        if (c._a) {
            var other = c._isUTC ? createUTC(c._a) : createLocal(c._a);
            this._isDSTShifted = this.isValid() && compareArrays(c._a, other.toArray()) > 0;
        } else {
            this._isDSTShifted = false;
        }
        return this._isDSTShifted;
    }
    function isLocal() {
        return this.isValid() ? !this._isUTC : false;
    }
    function isUtcOffset() {
        return this.isValid() ? this._isUTC : false;
    }
    function isUtc() {
        return this.isValid() ? this._isUTC && this._offset === 0 : false;
    }
    var aspNetRegex = /^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/;
    var isoRegex = /^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;
    function createDuration(input, key) {
        var duration = input, match = null, sign, ret, diffRes;
        if (isDuration(input)) {
            duration = {
                ms: input._milliseconds,
                d: input._days,
                M: input._months
            };
        } else if (isNumber(input)) {
            duration = {};
            if (key) {
                duration[key] = input;
            } else {
                duration.milliseconds = input;
            }
        } else if (!!(match = aspNetRegex.exec(input))) {
            sign = match[1] === "-" ? -1 : 1;
            duration = {
                y: 0,
                d: toInt(match[DATE]) * sign,
                h: toInt(match[HOUR]) * sign,
                m: toInt(match[MINUTE]) * sign,
                s: toInt(match[SECOND]) * sign,
                ms: toInt(absRound(match[MILLISECOND] * 1e3)) * sign
            };
        } else if (!!(match = isoRegex.exec(input))) {
            sign = match[1] === "-" ? -1 : 1;
            duration = {
                y: parseIso(match[2], sign),
                M: parseIso(match[3], sign),
                w: parseIso(match[4], sign),
                d: parseIso(match[5], sign),
                h: parseIso(match[6], sign),
                m: parseIso(match[7], sign),
                s: parseIso(match[8], sign)
            };
        } else if (duration == null) {
            duration = {};
        } else if (typeof duration === "object" && ("from" in duration || "to" in duration)) {
            diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to));
            duration = {};
            duration.ms = diffRes.milliseconds;
            duration.M = diffRes.months;
        }
        ret = new Duration(duration);
        if (isDuration(input) && hasOwnProp(input, "_locale")) {
            ret._locale = input._locale;
        }
        return ret;
    }
    createDuration.fn = Duration.prototype;
    createDuration.invalid = createInvalid$1;
    function parseIso(inp, sign) {
        var res = inp && parseFloat(inp.replace(",", "."));
        return (isNaN(res) ? 0 : res) * sign;
    }
    function positiveMomentsDifference(base, other) {
        var res = {};
        res.months = other.month() - base.month() + (other.year() - base.year()) * 12;
        if (base.clone().add(res.months, "M").isAfter(other)) {
            --res.months;
        }
        res.milliseconds = +other - +base.clone().add(res.months, "M");
        return res;
    }
    function momentsDifference(base, other) {
        var res;
        if (!(base.isValid() && other.isValid())) {
            return {
                milliseconds: 0,
                months: 0
            };
        }
        other = cloneWithOffset(other, base);
        if (base.isBefore(other)) {
            res = positiveMomentsDifference(base, other);
        } else {
            res = positiveMomentsDifference(other, base);
            res.milliseconds = -res.milliseconds;
            res.months = -res.months;
        }
        return res;
    }
    function createAdder(direction, name) {
        return function(val, period) {
            var dur, tmp;
            if (period !== null && !isNaN(+period)) {
                deprecateSimple(name, "moment()." + name + "(period, number) is deprecated. Please use moment()." + name + "(number, period). " + "See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.");
                tmp = val;
                val = period;
                period = tmp;
            }
            val = typeof val === "string" ? +val : val;
            dur = createDuration(val, period);
            addSubtract(this, dur, direction);
            return this;
        };
    }
    function addSubtract(mom, duration, isAdding, updateOffset) {
        var milliseconds = duration._milliseconds, days = absRound(duration._days), months = absRound(duration._months);
        if (!mom.isValid()) {
            return;
        }
        updateOffset = updateOffset == null ? true : updateOffset;
        if (months) {
            setMonth(mom, get(mom, "Month") + months * isAdding);
        }
        if (days) {
            set$1(mom, "Date", get(mom, "Date") + days * isAdding);
        }
        if (milliseconds) {
            mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
        }
        if (updateOffset) {
            hooks.updateOffset(mom, days || months);
        }
    }
    var add = createAdder(1, "add");
    var subtract = createAdder(-1, "subtract");
    function getCalendarFormat(myMoment, now) {
        var diff = myMoment.diff(now, "days", true);
        return diff < -6 ? "sameElse" : diff < -1 ? "lastWeek" : diff < 0 ? "lastDay" : diff < 1 ? "sameDay" : diff < 2 ? "nextDay" : diff < 7 ? "nextWeek" : "sameElse";
    }
    function calendar$1(time, formats) {
        var now = time || createLocal(), sod = cloneWithOffset(now, this).startOf("day"), format = hooks.calendarFormat(this, sod) || "sameElse";
        var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]);
        return this.format(output || this.localeData().calendar(format, this, createLocal(now)));
    }
    function clone() {
        return new Moment(this);
    }
    function isAfter(input, units) {
        var localInput = isMoment(input) ? input : createLocal(input);
        if (!(this.isValid() && localInput.isValid())) {
            return false;
        }
        units = normalizeUnits(units) || "millisecond";
        if (units === "millisecond") {
            return this.valueOf() > localInput.valueOf();
        } else {
            return localInput.valueOf() < this.clone().startOf(units).valueOf();
        }
    }
    function isBefore(input, units) {
        var localInput = isMoment(input) ? input : createLocal(input);
        if (!(this.isValid() && localInput.isValid())) {
            return false;
        }
        units = normalizeUnits(units) || "millisecond";
        if (units === "millisecond") {
            return this.valueOf() < localInput.valueOf();
        } else {
            return this.clone().endOf(units).valueOf() < localInput.valueOf();
        }
    }
    function isBetween(from, to, units, inclusivity) {
        var localFrom = isMoment(from) ? from : createLocal(from), localTo = isMoment(to) ? to : createLocal(to);
        if (!(this.isValid() && localFrom.isValid() && localTo.isValid())) {
            return false;
        }
        inclusivity = inclusivity || "()";
        return (inclusivity[0] === "(" ? this.isAfter(localFrom, units) : !this.isBefore(localFrom, units)) && (inclusivity[1] === ")" ? this.isBefore(localTo, units) : !this.isAfter(localTo, units));
    }
    function isSame(input, units) {
        var localInput = isMoment(input) ? input : createLocal(input), inputMs;
        if (!(this.isValid() && localInput.isValid())) {
            return false;
        }
        units = normalizeUnits(units) || "millisecond";
        if (units === "millisecond") {
            return this.valueOf() === localInput.valueOf();
        } else {
            inputMs = localInput.valueOf();
            return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf();
        }
    }
    function isSameOrAfter(input, units) {
        return this.isSame(input, units) || this.isAfter(input, units);
    }
    function isSameOrBefore(input, units) {
        return this.isSame(input, units) || this.isBefore(input, units);
    }
    function diff(input, units, asFloat) {
        var that, zoneDelta, output;
        if (!this.isValid()) {
            return NaN;
        }
        that = cloneWithOffset(input, this);
        if (!that.isValid()) {
            return NaN;
        }
        zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
        units = normalizeUnits(units);
        switch (units) {
          case "year":
            output = monthDiff(this, that) / 12;
            break;

          case "month":
            output = monthDiff(this, that);
            break;

          case "quarter":
            output = monthDiff(this, that) / 3;
            break;

          case "second":
            output = (this - that) / 1e3;
            break;

          case "minute":
            output = (this - that) / 6e4;
            break;

          case "hour":
            output = (this - that) / 36e5;
            break;

          case "day":
            output = (this - that - zoneDelta) / 864e5;
            break;

          case "week":
            output = (this - that - zoneDelta) / 6048e5;
            break;

          default:
            output = this - that;
        }
        return asFloat ? output : absFloor(output);
    }
    function monthDiff(a, b) {
        var wholeMonthDiff = (b.year() - a.year()) * 12 + (b.month() - a.month()), anchor = a.clone().add(wholeMonthDiff, "months"), anchor2, adjust;
        if (b - anchor < 0) {
            anchor2 = a.clone().add(wholeMonthDiff - 1, "months");
            adjust = (b - anchor) / (anchor - anchor2);
        } else {
            anchor2 = a.clone().add(wholeMonthDiff + 1, "months");
            adjust = (b - anchor) / (anchor2 - anchor);
        }
        return -(wholeMonthDiff + adjust) || 0;
    }
    hooks.defaultFormat = "YYYY-MM-DDTHH:mm:ssZ";
    hooks.defaultFormatUtc = "YYYY-MM-DDTHH:mm:ss[Z]";
    function toString() {
        return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ");
    }
    function toISOString(keepOffset) {
        if (!this.isValid()) {
            return null;
        }
        var utc = keepOffset !== true;
        var m = utc ? this.clone().utc() : this;
        if (m.year() < 0 || m.year() > 9999) {
            return formatMoment(m, utc ? "YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]" : "YYYYYY-MM-DD[T]HH:mm:ss.SSSZ");
        }
        if (isFunction(Date.prototype.toISOString)) {
            if (utc) {
                return this.toDate().toISOString();
            } else {
                return new Date(this.valueOf() + this.utcOffset() * 60 * 1e3).toISOString().replace("Z", formatMoment(m, "Z"));
            }
        }
        return formatMoment(m, utc ? "YYYY-MM-DD[T]HH:mm:ss.SSS[Z]" : "YYYY-MM-DD[T]HH:mm:ss.SSSZ");
    }
    function inspect() {
        if (!this.isValid()) {
            return "moment.invalid(/* " + this._i + " */)";
        }
        var func = "moment";
        var zone = "";
        if (!this.isLocal()) {
            func = this.utcOffset() === 0 ? "moment.utc" : "moment.parseZone";
            zone = "Z";
        }
        var prefix = "[" + func + '("]';
        var year = 0 <= this.year() && this.year() <= 9999 ? "YYYY" : "YYYYYY";
        var datetime = "-MM-DD[T]HH:mm:ss.SSS";
        var suffix = zone + '[")]';
        return this.format(prefix + year + datetime + suffix);
    }
    function format(inputString) {
        if (!inputString) {
            inputString = this.isUtc() ? hooks.defaultFormatUtc : hooks.defaultFormat;
        }
        var output = formatMoment(this, inputString);
        return this.localeData().postformat(output);
    }
    function from(time, withoutSuffix) {
        if (this.isValid() && (isMoment(time) && time.isValid() || createLocal(time).isValid())) {
            return createDuration({
                to: this,
                from: time
            }).locale(this.locale()).humanize(!withoutSuffix);
        } else {
            return this.localeData().invalidDate();
        }
    }
    function fromNow(withoutSuffix) {
        return this.from(createLocal(), withoutSuffix);
    }
    function to(time, withoutSuffix) {
        if (this.isValid() && (isMoment(time) && time.isValid() || createLocal(time).isValid())) {
            return createDuration({
                from: this,
                to: time
            }).locale(this.locale()).humanize(!withoutSuffix);
        } else {
            return this.localeData().invalidDate();
        }
    }
    function toNow(withoutSuffix) {
        return this.to(createLocal(), withoutSuffix);
    }
    function locale(key) {
        var newLocaleData;
        if (key === undefined) {
            return this._locale._abbr;
        } else {
            newLocaleData = getLocale(key);
            if (newLocaleData != null) {
                this._locale = newLocaleData;
            }
            return this;
        }
    }
    var lang = deprecate("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.", function(key) {
        if (key === undefined) {
            return this.localeData();
        } else {
            return this.locale(key);
        }
    });
    function localeData() {
        return this._locale;
    }
    var MS_PER_SECOND = 1e3;
    var MS_PER_MINUTE = 60 * MS_PER_SECOND;
    var MS_PER_HOUR = 60 * MS_PER_MINUTE;
    var MS_PER_400_YEARS = (365 * 400 + 97) * 24 * MS_PER_HOUR;
    function mod$1(dividend, divisor) {
        return (dividend % divisor + divisor) % divisor;
    }
    function localStartOfDate(y, m, d) {
        if (y < 100 && y >= 0) {
            return new Date(y + 400, m, d) - MS_PER_400_YEARS;
        } else {
            return new Date(y, m, d).valueOf();
        }
    }
    function utcStartOfDate(y, m, d) {
        if (y < 100 && y >= 0) {
            return Date.UTC(y + 400, m, d) - MS_PER_400_YEARS;
        } else {
            return Date.UTC(y, m, d);
        }
    }
    function startOf(units) {
        var time;
        units = normalizeUnits(units);
        if (units === undefined || units === "millisecond" || !this.isValid()) {
            return this;
        }
        var startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
        switch (units) {
          case "year":
            time = startOfDate(this.year(), 0, 1);
            break;

          case "quarter":
            time = startOfDate(this.year(), this.month() - this.month() % 3, 1);
            break;

          case "month":
            time = startOfDate(this.year(), this.month(), 1);
            break;

          case "week":
            time = startOfDate(this.year(), this.month(), this.date() - this.weekday());
            break;

          case "isoWeek":
            time = startOfDate(this.year(), this.month(), this.date() - (this.isoWeekday() - 1));
            break;

          case "day":
          case "date":
            time = startOfDate(this.year(), this.month(), this.date());
            break;

          case "hour":
            time = this._d.valueOf();
            time -= mod$1(time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE), MS_PER_HOUR);
            break;

          case "minute":
            time = this._d.valueOf();
            time -= mod$1(time, MS_PER_MINUTE);
            break;

          case "second":
            time = this._d.valueOf();
            time -= mod$1(time, MS_PER_SECOND);
            break;
        }
        this._d.setTime(time);
        hooks.updateOffset(this, true);
        return this;
    }
    function endOf(units) {
        var time;
        units = normalizeUnits(units);
        if (units === undefined || units === "millisecond" || !this.isValid()) {
            return this;
        }
        var startOfDate = this._isUTC ? utcStartOfDate : localStartOfDate;
        switch (units) {
          case "year":
            time = startOfDate(this.year() + 1, 0, 1) - 1;
            break;

          case "quarter":
            time = startOfDate(this.year(), this.month() - this.month() % 3 + 3, 1) - 1;
            break;

          case "month":
            time = startOfDate(this.year(), this.month() + 1, 1) - 1;
            break;

          case "week":
            time = startOfDate(this.year(), this.month(), this.date() - this.weekday() + 7) - 1;
            break;

          case "isoWeek":
            time = startOfDate(this.year(), this.month(), this.date() - (this.isoWeekday() - 1) + 7) - 1;
            break;

          case "day":
          case "date":
            time = startOfDate(this.year(), this.month(), this.date() + 1) - 1;
            break;

          case "hour":
            time = this._d.valueOf();
            time += MS_PER_HOUR - mod$1(time + (this._isUTC ? 0 : this.utcOffset() * MS_PER_MINUTE), MS_PER_HOUR) - 1;
            break;

          case "minute":
            time = this._d.valueOf();
            time += MS_PER_MINUTE - mod$1(time, MS_PER_MINUTE) - 1;
            break;

          case "second":
            time = this._d.valueOf();
            time += MS_PER_SECOND - mod$1(time, MS_PER_SECOND) - 1;
            break;
        }
        this._d.setTime(time);
        hooks.updateOffset(this, true);
        return this;
    }
    function valueOf() {
        return this._d.valueOf() - (this._offset || 0) * 6e4;
    }
    function unix() {
        return Math.floor(this.valueOf() / 1e3);
    }
    function toDate() {
        return new Date(this.valueOf());
    }
    function toArray() {
        var m = this;
        return [ m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond() ];
    }
    function toObject() {
        var m = this;
        return {
            years: m.year(),
            months: m.month(),
            date: m.date(),
            hours: m.hours(),
            minutes: m.minutes(),
            seconds: m.seconds(),
            milliseconds: m.milliseconds()
        };
    }
    function toJSON() {
        return this.isValid() ? this.toISOString() : null;
    }
    function isValid$2() {
        return isValid(this);
    }
    function parsingFlags() {
        return extend({}, getParsingFlags(this));
    }
    function invalidAt() {
        return getParsingFlags(this).overflow;
    }
    function creationData() {
        return {
            input: this._i,
            format: this._f,
            locale: this._locale,
            isUTC: this._isUTC,
            strict: this._strict
        };
    }
    addFormatToken(0, [ "gg", 2 ], 0, function() {
        return this.weekYear() % 100;
    });
    addFormatToken(0, [ "GG", 2 ], 0, function() {
        return this.isoWeekYear() % 100;
    });
    function addWeekYearFormatToken(token, getter) {
        addFormatToken(0, [ token, token.length ], 0, getter);
    }
    addWeekYearFormatToken("gggg", "weekYear");
    addWeekYearFormatToken("ggggg", "weekYear");
    addWeekYearFormatToken("GGGG", "isoWeekYear");
    addWeekYearFormatToken("GGGGG", "isoWeekYear");
    addUnitAlias("weekYear", "gg");
    addUnitAlias("isoWeekYear", "GG");
    addUnitPriority("weekYear", 1);
    addUnitPriority("isoWeekYear", 1);
    addRegexToken("G", matchSigned);
    addRegexToken("g", matchSigned);
    addRegexToken("GG", match1to2, match2);
    addRegexToken("gg", match1to2, match2);
    addRegexToken("GGGG", match1to4, match4);
    addRegexToken("gggg", match1to4, match4);
    addRegexToken("GGGGG", match1to6, match6);
    addRegexToken("ggggg", match1to6, match6);
    addWeekParseToken([ "gggg", "ggggg", "GGGG", "GGGGG" ], function(input, week, config, token) {
        week[token.substr(0, 2)] = toInt(input);
    });
    addWeekParseToken([ "gg", "GG" ], function(input, week, config, token) {
        week[token] = hooks.parseTwoDigitYear(input);
    });
    function getSetWeekYear(input) {
        return getSetWeekYearHelper.call(this, input, this.week(), this.weekday(), this.localeData()._week.dow, this.localeData()._week.doy);
    }
    function getSetISOWeekYear(input) {
        return getSetWeekYearHelper.call(this, input, this.isoWeek(), this.isoWeekday(), 1, 4);
    }
    function getISOWeeksInYear() {
        return weeksInYear(this.year(), 1, 4);
    }
    function getWeeksInYear() {
        var weekInfo = this.localeData()._week;
        return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
    }
    function getSetWeekYearHelper(input, week, weekday, dow, doy) {
        var weeksTarget;
        if (input == null) {
            return weekOfYear(this, dow, doy).year;
        } else {
            weeksTarget = weeksInYear(input, dow, doy);
            if (week > weeksTarget) {
                week = weeksTarget;
            }
            return setWeekAll.call(this, input, week, weekday, dow, doy);
        }
    }
    function setWeekAll(weekYear, week, weekday, dow, doy) {
        var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy), date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
        this.year(date.getUTCFullYear());
        this.month(date.getUTCMonth());
        this.date(date.getUTCDate());
        return this;
    }
    addFormatToken("Q", 0, "Qo", "quarter");
    addUnitAlias("quarter", "Q");
    addUnitPriority("quarter", 7);
    addRegexToken("Q", match1);
    addParseToken("Q", function(input, array) {
        array[MONTH] = (toInt(input) - 1) * 3;
    });
    function getSetQuarter(input) {
        return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
    }
    addFormatToken("D", [ "DD", 2 ], "Do", "date");
    addUnitAlias("date", "D");
    addUnitPriority("date", 9);
    addRegexToken("D", match1to2);
    addRegexToken("DD", match1to2, match2);
    addRegexToken("Do", function(isStrict, locale) {
        return isStrict ? locale._dayOfMonthOrdinalParse || locale._ordinalParse : locale._dayOfMonthOrdinalParseLenient;
    });
    addParseToken([ "D", "DD" ], DATE);
    addParseToken("Do", function(input, array) {
        array[DATE] = toInt(input.match(match1to2)[0]);
    });
    var getSetDayOfMonth = makeGetSet("Date", true);
    addFormatToken("DDD", [ "DDDD", 3 ], "DDDo", "dayOfYear");
    addUnitAlias("dayOfYear", "DDD");
    addUnitPriority("dayOfYear", 4);
    addRegexToken("DDD", match1to3);
    addRegexToken("DDDD", match3);
    addParseToken([ "DDD", "DDDD" ], function(input, array, config) {
        config._dayOfYear = toInt(input);
    });
    function getSetDayOfYear(input) {
        var dayOfYear = Math.round((this.clone().startOf("day") - this.clone().startOf("year")) / 864e5) + 1;
        return input == null ? dayOfYear : this.add(input - dayOfYear, "d");
    }
    addFormatToken("m", [ "mm", 2 ], 0, "minute");
    addUnitAlias("minute", "m");
    addUnitPriority("minute", 14);
    addRegexToken("m", match1to2);
    addRegexToken("mm", match1to2, match2);
    addParseToken([ "m", "mm" ], MINUTE);
    var getSetMinute = makeGetSet("Minutes", false);
    addFormatToken("s", [ "ss", 2 ], 0, "second");
    addUnitAlias("second", "s");
    addUnitPriority("second", 15);
    addRegexToken("s", match1to2);
    addRegexToken("ss", match1to2, match2);
    addParseToken([ "s", "ss" ], SECOND);
    var getSetSecond = makeGetSet("Seconds", false);
    addFormatToken("S", 0, 0, function() {
        return ~~(this.millisecond() / 100);
    });
    addFormatToken(0, [ "SS", 2 ], 0, function() {
        return ~~(this.millisecond() / 10);
    });
    addFormatToken(0, [ "SSS", 3 ], 0, "millisecond");
    addFormatToken(0, [ "SSSS", 4 ], 0, function() {
        return this.millisecond() * 10;
    });
    addFormatToken(0, [ "SSSSS", 5 ], 0, function() {
        return this.millisecond() * 100;
    });
    addFormatToken(0, [ "SSSSSS", 6 ], 0, function() {
        return this.millisecond() * 1e3;
    });
    addFormatToken(0, [ "SSSSSSS", 7 ], 0, function() {
        return this.millisecond() * 1e4;
    });
    addFormatToken(0, [ "SSSSSSSS", 8 ], 0, function() {
        return this.millisecond() * 1e5;
    });
    addFormatToken(0, [ "SSSSSSSSS", 9 ], 0, function() {
        return this.millisecond() * 1e6;
    });
    addUnitAlias("millisecond", "ms");
    addUnitPriority("millisecond", 16);
    addRegexToken("S", match1to3, match1);
    addRegexToken("SS", match1to3, match2);
    addRegexToken("SSS", match1to3, match3);
    var token;
    for (token = "SSSS"; token.length <= 9; token += "S") {
        addRegexToken(token, matchUnsigned);
    }
    function parseMs(input, array) {
        array[MILLISECOND] = toInt(("0." + input) * 1e3);
    }
    for (token = "S"; token.length <= 9; token += "S") {
        addParseToken(token, parseMs);
    }
    var getSetMillisecond = makeGetSet("Milliseconds", false);
    addFormatToken("z", 0, 0, "zoneAbbr");
    addFormatToken("zz", 0, 0, "zoneName");
    function getZoneAbbr() {
        return this._isUTC ? "UTC" : "";
    }
    function getZoneName() {
        return this._isUTC ? "Coordinated Universal Time" : "";
    }
    var proto = Moment.prototype;
    proto.add = add;
    proto.calendar = calendar$1;
    proto.clone = clone;
    proto.diff = diff;
    proto.endOf = endOf;
    proto.format = format;
    proto.from = from;
    proto.fromNow = fromNow;
    proto.to = to;
    proto.toNow = toNow;
    proto.get = stringGet;
    proto.invalidAt = invalidAt;
    proto.isAfter = isAfter;
    proto.isBefore = isBefore;
    proto.isBetween = isBetween;
    proto.isSame = isSame;
    proto.isSameOrAfter = isSameOrAfter;
    proto.isSameOrBefore = isSameOrBefore;
    proto.isValid = isValid$2;
    proto.lang = lang;
    proto.locale = locale;
    proto.localeData = localeData;
    proto.max = prototypeMax;
    proto.min = prototypeMin;
    proto.parsingFlags = parsingFlags;
    proto.set = stringSet;
    proto.startOf = startOf;
    proto.subtract = subtract;
    proto.toArray = toArray;
    proto.toObject = toObject;
    proto.toDate = toDate;
    proto.toISOString = toISOString;
    proto.inspect = inspect;
    proto.toJSON = toJSON;
    proto.toString = toString;
    proto.unix = unix;
    proto.valueOf = valueOf;
    proto.creationData = creationData;
    proto.year = getSetYear;
    proto.isLeapYear = getIsLeapYear;
    proto.weekYear = getSetWeekYear;
    proto.isoWeekYear = getSetISOWeekYear;
    proto.quarter = proto.quarters = getSetQuarter;
    proto.month = getSetMonth;
    proto.daysInMonth = getDaysInMonth;
    proto.week = proto.weeks = getSetWeek;
    proto.isoWeek = proto.isoWeeks = getSetISOWeek;
    proto.weeksInYear = getWeeksInYear;
    proto.isoWeeksInYear = getISOWeeksInYear;
    proto.date = getSetDayOfMonth;
    proto.day = proto.days = getSetDayOfWeek;
    proto.weekday = getSetLocaleDayOfWeek;
    proto.isoWeekday = getSetISODayOfWeek;
    proto.dayOfYear = getSetDayOfYear;
    proto.hour = proto.hours = getSetHour;
    proto.minute = proto.minutes = getSetMinute;
    proto.second = proto.seconds = getSetSecond;
    proto.millisecond = proto.milliseconds = getSetMillisecond;
    proto.utcOffset = getSetOffset;
    proto.utc = setOffsetToUTC;
    proto.local = setOffsetToLocal;
    proto.parseZone = setOffsetToParsedOffset;
    proto.hasAlignedHourOffset = hasAlignedHourOffset;
    proto.isDST = isDaylightSavingTime;
    proto.isLocal = isLocal;
    proto.isUtcOffset = isUtcOffset;
    proto.isUtc = isUtc;
    proto.isUTC = isUtc;
    proto.zoneAbbr = getZoneAbbr;
    proto.zoneName = getZoneName;
    proto.dates = deprecate("dates accessor is deprecated. Use date instead.", getSetDayOfMonth);
    proto.months = deprecate("months accessor is deprecated. Use month instead", getSetMonth);
    proto.years = deprecate("years accessor is deprecated. Use year instead", getSetYear);
    proto.zone = deprecate("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/", getSetZone);
    proto.isDSTShifted = deprecate("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information", isDaylightSavingTimeShifted);
    function createUnix(input) {
        return createLocal(input * 1e3);
    }
    function createInZone() {
        return createLocal.apply(null, arguments).parseZone();
    }
    function preParsePostFormat(string) {
        return string;
    }
    var proto$1 = Locale.prototype;
    proto$1.calendar = calendar;
    proto$1.longDateFormat = longDateFormat;
    proto$1.invalidDate = invalidDate;
    proto$1.ordinal = ordinal;
    proto$1.preparse = preParsePostFormat;
    proto$1.postformat = preParsePostFormat;
    proto$1.relativeTime = relativeTime;
    proto$1.pastFuture = pastFuture;
    proto$1.set = set;
    proto$1.months = localeMonths;
    proto$1.monthsShort = localeMonthsShort;
    proto$1.monthsParse = localeMonthsParse;
    proto$1.monthsRegex = monthsRegex;
    proto$1.monthsShortRegex = monthsShortRegex;
    proto$1.week = localeWeek;
    proto$1.firstDayOfYear = localeFirstDayOfYear;
    proto$1.firstDayOfWeek = localeFirstDayOfWeek;
    proto$1.weekdays = localeWeekdays;
    proto$1.weekdaysMin = localeWeekdaysMin;
    proto$1.weekdaysShort = localeWeekdaysShort;
    proto$1.weekdaysParse = localeWeekdaysParse;
    proto$1.weekdaysRegex = weekdaysRegex;
    proto$1.weekdaysShortRegex = weekdaysShortRegex;
    proto$1.weekdaysMinRegex = weekdaysMinRegex;
    proto$1.isPM = localeIsPM;
    proto$1.meridiem = localeMeridiem;
    function get$1(format, index, field, setter) {
        var locale = getLocale();
        var utc = createUTC().set(setter, index);
        return locale[field](utc, format);
    }
    function listMonthsImpl(format, index, field) {
        if (isNumber(format)) {
            index = format;
            format = undefined;
        }
        format = format || "";
        if (index != null) {
            return get$1(format, index, field, "month");
        }
        var i;
        var out = [];
        for (i = 0; i < 12; i++) {
            out[i] = get$1(format, i, field, "month");
        }
        return out;
    }
    function listWeekdaysImpl(localeSorted, format, index, field) {
        if (typeof localeSorted === "boolean") {
            if (isNumber(format)) {
                index = format;
                format = undefined;
            }
            format = format || "";
        } else {
            format = localeSorted;
            index = format;
            localeSorted = false;
            if (isNumber(format)) {
                index = format;
                format = undefined;
            }
            format = format || "";
        }
        var locale = getLocale(), shift = localeSorted ? locale._week.dow : 0;
        if (index != null) {
            return get$1(format, (index + shift) % 7, field, "day");
        }
        var i;
        var out = [];
        for (i = 0; i < 7; i++) {
            out[i] = get$1(format, (i + shift) % 7, field, "day");
        }
        return out;
    }
    function listMonths(format, index) {
        return listMonthsImpl(format, index, "months");
    }
    function listMonthsShort(format, index) {
        return listMonthsImpl(format, index, "monthsShort");
    }
    function listWeekdays(localeSorted, format, index) {
        return listWeekdaysImpl(localeSorted, format, index, "weekdays");
    }
    function listWeekdaysShort(localeSorted, format, index) {
        return listWeekdaysImpl(localeSorted, format, index, "weekdaysShort");
    }
    function listWeekdaysMin(localeSorted, format, index) {
        return listWeekdaysImpl(localeSorted, format, index, "weekdaysMin");
    }
    getSetGlobalLocale("en", {
        dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/,
        ordinal: function(number) {
            var b = number % 10, output = toInt(number % 100 / 10) === 1 ? "th" : b === 1 ? "st" : b === 2 ? "nd" : b === 3 ? "rd" : "th";
            return number + output;
        }
    });
    hooks.lang = deprecate("moment.lang is deprecated. Use moment.locale instead.", getSetGlobalLocale);
    hooks.langData = deprecate("moment.langData is deprecated. Use moment.localeData instead.", getLocale);
    var mathAbs = Math.abs;
    function abs() {
        var data = this._data;
        this._milliseconds = mathAbs(this._milliseconds);
        this._days = mathAbs(this._days);
        this._months = mathAbs(this._months);
        data.milliseconds = mathAbs(data.milliseconds);
        data.seconds = mathAbs(data.seconds);
        data.minutes = mathAbs(data.minutes);
        data.hours = mathAbs(data.hours);
        data.months = mathAbs(data.months);
        data.years = mathAbs(data.years);
        return this;
    }
    function addSubtract$1(duration, input, value, direction) {
        var other = createDuration(input, value);
        duration._milliseconds += direction * other._milliseconds;
        duration._days += direction * other._days;
        duration._months += direction * other._months;
        return duration._bubble();
    }
    function add$1(input, value) {
        return addSubtract$1(this, input, value, 1);
    }
    function subtract$1(input, value) {
        return addSubtract$1(this, input, value, -1);
    }
    function absCeil(number) {
        if (number < 0) {
            return Math.floor(number);
        } else {
            return Math.ceil(number);
        }
    }
    function bubble() {
        var milliseconds = this._milliseconds;
        var days = this._days;
        var months = this._months;
        var data = this._data;
        var seconds, minutes, hours, years, monthsFromDays;
        if (!(milliseconds >= 0 && days >= 0 && months >= 0 || milliseconds <= 0 && days <= 0 && months <= 0)) {
            milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
            days = 0;
            months = 0;
        }
        data.milliseconds = milliseconds % 1e3;
        seconds = absFloor(milliseconds / 1e3);
        data.seconds = seconds % 60;
        minutes = absFloor(seconds / 60);
        data.minutes = minutes % 60;
        hours = absFloor(minutes / 60);
        data.hours = hours % 24;
        days += absFloor(hours / 24);
        monthsFromDays = absFloor(daysToMonths(days));
        months += monthsFromDays;
        days -= absCeil(monthsToDays(monthsFromDays));
        years = absFloor(months / 12);
        months %= 12;
        data.days = days;
        data.months = months;
        data.years = years;
        return this;
    }
    function daysToMonths(days) {
        return days * 4800 / 146097;
    }
    function monthsToDays(months) {
        return months * 146097 / 4800;
    }
    function as(units) {
        if (!this.isValid()) {
            return NaN;
        }
        var days;
        var months;
        var milliseconds = this._milliseconds;
        units = normalizeUnits(units);
        if (units === "month" || units === "quarter" || units === "year") {
            days = this._days + milliseconds / 864e5;
            months = this._months + daysToMonths(days);
            switch (units) {
              case "month":
                return months;

              case "quarter":
                return months / 3;

              case "year":
                return months / 12;
            }
        } else {
            days = this._days + Math.round(monthsToDays(this._months));
            switch (units) {
              case "week":
                return days / 7 + milliseconds / 6048e5;

              case "day":
                return days + milliseconds / 864e5;

              case "hour":
                return days * 24 + milliseconds / 36e5;

              case "minute":
                return days * 1440 + milliseconds / 6e4;

              case "second":
                return days * 86400 + milliseconds / 1e3;

              case "millisecond":
                return Math.floor(days * 864e5) + milliseconds;

              default:
                throw new Error("Unknown unit " + units);
            }
        }
    }
    function valueOf$1() {
        if (!this.isValid()) {
            return NaN;
        }
        return this._milliseconds + this._days * 864e5 + this._months % 12 * 2592e6 + toInt(this._months / 12) * 31536e6;
    }
    function makeAs(alias) {
        return function() {
            return this.as(alias);
        };
    }
    var asMilliseconds = makeAs("ms");
    var asSeconds = makeAs("s");
    var asMinutes = makeAs("m");
    var asHours = makeAs("h");
    var asDays = makeAs("d");
    var asWeeks = makeAs("w");
    var asMonths = makeAs("M");
    var asQuarters = makeAs("Q");
    var asYears = makeAs("y");
    function clone$1() {
        return createDuration(this);
    }
    function get$2(units) {
        units = normalizeUnits(units);
        return this.isValid() ? this[units + "s"]() : NaN;
    }
    function makeGetter(name) {
        return function() {
            return this.isValid() ? this._data[name] : NaN;
        };
    }
    var milliseconds = makeGetter("milliseconds");
    var seconds = makeGetter("seconds");
    var minutes = makeGetter("minutes");
    var hours = makeGetter("hours");
    var days = makeGetter("days");
    var months = makeGetter("months");
    var years = makeGetter("years");
    function weeks() {
        return absFloor(this.days() / 7);
    }
    var round = Math.round;
    var thresholds = {
        ss: 44,
        s: 45,
        m: 45,
        h: 22,
        d: 26,
        M: 11
    };
    function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
        return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
    }
    function relativeTime$1(posNegDuration, withoutSuffix, locale) {
        var duration = createDuration(posNegDuration).abs();
        var seconds = round(duration.as("s"));
        var minutes = round(duration.as("m"));
        var hours = round(duration.as("h"));
        var days = round(duration.as("d"));
        var months = round(duration.as("M"));
        var years = round(duration.as("y"));
        var a = seconds <= thresholds.ss && [ "s", seconds ] || seconds < thresholds.s && [ "ss", seconds ] || minutes <= 1 && [ "m" ] || minutes < thresholds.m && [ "mm", minutes ] || hours <= 1 && [ "h" ] || hours < thresholds.h && [ "hh", hours ] || days <= 1 && [ "d" ] || days < thresholds.d && [ "dd", days ] || months <= 1 && [ "M" ] || months < thresholds.M && [ "MM", months ] || years <= 1 && [ "y" ] || [ "yy", years ];
        a[2] = withoutSuffix;
        a[3] = +posNegDuration > 0;
        a[4] = locale;
        return substituteTimeAgo.apply(null, a);
    }
    function getSetRelativeTimeRounding(roundingFunction) {
        if (roundingFunction === undefined) {
            return round;
        }
        if (typeof roundingFunction === "function") {
            round = roundingFunction;
            return true;
        }
        return false;
    }
    function getSetRelativeTimeThreshold(threshold, limit) {
        if (thresholds[threshold] === undefined) {
            return false;
        }
        if (limit === undefined) {
            return thresholds[threshold];
        }
        thresholds[threshold] = limit;
        if (threshold === "s") {
            thresholds.ss = limit - 1;
        }
        return true;
    }
    function humanize(withSuffix) {
        if (!this.isValid()) {
            return this.localeData().invalidDate();
        }
        var locale = this.localeData();
        var output = relativeTime$1(this, !withSuffix, locale);
        if (withSuffix) {
            output = locale.pastFuture(+this, output);
        }
        return locale.postformat(output);
    }
    var abs$1 = Math.abs;
    function sign(x) {
        return (x > 0) - (x < 0) || +x;
    }
    function toISOString$1() {
        if (!this.isValid()) {
            return this.localeData().invalidDate();
        }
        var seconds = abs$1(this._milliseconds) / 1e3;
        var days = abs$1(this._days);
        var months = abs$1(this._months);
        var minutes, hours, years;
        minutes = absFloor(seconds / 60);
        hours = absFloor(minutes / 60);
        seconds %= 60;
        minutes %= 60;
        years = absFloor(months / 12);
        months %= 12;
        var Y = years;
        var M = months;
        var D = days;
        var h = hours;
        var m = minutes;
        var s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, "") : "";
        var total = this.asSeconds();
        if (!total) {
            return "P0D";
        }
        var totalSign = total < 0 ? "-" : "";
        var ymSign = sign(this._months) !== sign(total) ? "-" : "";
        var daysSign = sign(this._days) !== sign(total) ? "-" : "";
        var hmsSign = sign(this._milliseconds) !== sign(total) ? "-" : "";
        return totalSign + "P" + (Y ? ymSign + Y + "Y" : "") + (M ? ymSign + M + "M" : "") + (D ? daysSign + D + "D" : "") + (h || m || s ? "T" : "") + (h ? hmsSign + h + "H" : "") + (m ? hmsSign + m + "M" : "") + (s ? hmsSign + s + "S" : "");
    }
    var proto$2 = Duration.prototype;
    proto$2.isValid = isValid$1;
    proto$2.abs = abs;
    proto$2.add = add$1;
    proto$2.subtract = subtract$1;
    proto$2.as = as;
    proto$2.asMilliseconds = asMilliseconds;
    proto$2.asSeconds = asSeconds;
    proto$2.asMinutes = asMinutes;
    proto$2.asHours = asHours;
    proto$2.asDays = asDays;
    proto$2.asWeeks = asWeeks;
    proto$2.asMonths = asMonths;
    proto$2.asQuarters = asQuarters;
    proto$2.asYears = asYears;
    proto$2.valueOf = valueOf$1;
    proto$2._bubble = bubble;
    proto$2.clone = clone$1;
    proto$2.get = get$2;
    proto$2.milliseconds = milliseconds;
    proto$2.seconds = seconds;
    proto$2.minutes = minutes;
    proto$2.hours = hours;
    proto$2.days = days;
    proto$2.weeks = weeks;
    proto$2.months = months;
    proto$2.years = years;
    proto$2.humanize = humanize;
    proto$2.toISOString = toISOString$1;
    proto$2.toString = toISOString$1;
    proto$2.toJSON = toISOString$1;
    proto$2.locale = locale;
    proto$2.localeData = localeData;
    proto$2.toIsoString = deprecate("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)", toISOString$1);
    proto$2.lang = lang;
    addFormatToken("X", 0, 0, "unix");
    addFormatToken("x", 0, 0, "valueOf");
    addRegexToken("x", matchSigned);
    addRegexToken("X", matchTimestamp);
    addParseToken("X", function(input, array, config) {
        config._d = new Date(parseFloat(input, 10) * 1e3);
    });
    addParseToken("x", function(input, array, config) {
        config._d = new Date(toInt(input));
    });
    hooks.version = "2.24.0";
    setHookCallback(createLocal);
    hooks.fn = proto;
    hooks.min = min;
    hooks.max = max;
    hooks.now = now;
    hooks.utc = createUTC;
    hooks.unix = createUnix;
    hooks.months = listMonths;
    hooks.isDate = isDate;
    hooks.locale = getSetGlobalLocale;
    hooks.invalid = createInvalid;
    hooks.duration = createDuration;
    hooks.isMoment = isMoment;
    hooks.weekdays = listWeekdays;
    hooks.parseZone = createInZone;
    hooks.localeData = getLocale;
    hooks.isDuration = isDuration;
    hooks.monthsShort = listMonthsShort;
    hooks.weekdaysMin = listWeekdaysMin;
    hooks.defineLocale = defineLocale;
    hooks.updateLocale = updateLocale;
    hooks.locales = listLocales;
    hooks.weekdaysShort = listWeekdaysShort;
    hooks.normalizeUnits = normalizeUnits;
    hooks.relativeTimeRounding = getSetRelativeTimeRounding;
    hooks.relativeTimeThreshold = getSetRelativeTimeThreshold;
    hooks.calendarFormat = getCalendarFormat;
    hooks.prototype = proto;
    hooks.HTML5_FMT = {
        DATETIME_LOCAL: "YYYY-MM-DDTHH:mm",
        DATETIME_LOCAL_SECONDS: "YYYY-MM-DDTHH:mm:ss",
        DATETIME_LOCAL_MS: "YYYY-MM-DDTHH:mm:ss.SSS",
        DATE: "YYYY-MM-DD",
        TIME: "HH:mm",
        TIME_SECONDS: "HH:mm:ss",
        TIME_MS: "HH:mm:ss.SSS",
        WEEK: "GGGG-[W]WW",
        MONTH: "YYYY-MM"
    };
    return hooks;
});

(function(root, factory) {
    "use strict";
    if (typeof module === "object" && module.exports) {
        module.exports = factory(require("moment"));
    } else if (typeof define === "function" && define.amd) {
        define([ "moment" ], factory);
    } else {
        factory(root.moment);
    }
})(this, function(moment) {
    "use strict";
    var VERSION = "0.5.25", zones = {}, links = {}, names = {}, guesses = {}, cachedGuess;
    if (!moment || typeof moment.version !== "string") {
        logError("Moment Timezone requires Moment.js. See https://momentjs.com/timezone/docs/#/use-it/browser/");
    }
    var momentVersion = moment.version.split("."), major = +momentVersion[0], minor = +momentVersion[1];
    if (major < 2 || major === 2 && minor < 6) {
        logError("Moment Timezone requires Moment.js >= 2.6.0. You are using Moment.js " + moment.version + ". See momentjs.com");
    }
    function charCodeToInt(charCode) {
        if (charCode > 96) {
            return charCode - 87;
        } else if (charCode > 64) {
            return charCode - 29;
        }
        return charCode - 48;
    }
    function unpackBase60(string) {
        var i = 0, parts = string.split("."), whole = parts[0], fractional = parts[1] || "", multiplier = 1, num, out = 0, sign = 1;
        if (string.charCodeAt(0) === 45) {
            i = 1;
            sign = -1;
        }
        for (i; i < whole.length; i++) {
            num = charCodeToInt(whole.charCodeAt(i));
            out = 60 * out + num;
        }
        for (i = 0; i < fractional.length; i++) {
            multiplier = multiplier / 60;
            num = charCodeToInt(fractional.charCodeAt(i));
            out += num * multiplier;
        }
        return out * sign;
    }
    function arrayToInt(array) {
        for (var i = 0; i < array.length; i++) {
            array[i] = unpackBase60(array[i]);
        }
    }
    function intToUntil(array, length) {
        for (var i = 0; i < length; i++) {
            array[i] = Math.round((array[i - 1] || 0) + array[i] * 6e4);
        }
        array[length - 1] = Infinity;
    }
    function mapIndices(source, indices) {
        var out = [], i;
        for (i = 0; i < indices.length; i++) {
            out[i] = source[indices[i]];
        }
        return out;
    }
    function unpack(string) {
        var data = string.split("|"), offsets = data[2].split(" "), indices = data[3].split(""), untils = data[4].split(" ");
        arrayToInt(offsets);
        arrayToInt(indices);
        arrayToInt(untils);
        intToUntil(untils, indices.length);
        return {
            name: data[0],
            abbrs: mapIndices(data[1].split(" "), indices),
            offsets: mapIndices(offsets, indices),
            untils: untils,
            population: data[5] | 0
        };
    }
    function Zone(packedString) {
        if (packedString) {
            this._set(unpack(packedString));
        }
    }
    Zone.prototype = {
        _set: function(unpacked) {
            this.name = unpacked.name;
            this.abbrs = unpacked.abbrs;
            this.untils = unpacked.untils;
            this.offsets = unpacked.offsets;
            this.population = unpacked.population;
        },
        _index: function(timestamp) {
            var target = +timestamp, untils = this.untils, i;
            for (i = 0; i < untils.length; i++) {
                if (target < untils[i]) {
                    return i;
                }
            }
        },
        parse: function(timestamp) {
            var target = +timestamp, offsets = this.offsets, untils = this.untils, max = untils.length - 1, offset, offsetNext, offsetPrev, i;
            for (i = 0; i < max; i++) {
                offset = offsets[i];
                offsetNext = offsets[i + 1];
                offsetPrev = offsets[i ? i - 1 : i];
                if (offset < offsetNext && tz.moveAmbiguousForward) {
                    offset = offsetNext;
                } else if (offset > offsetPrev && tz.moveInvalidForward) {
                    offset = offsetPrev;
                }
                if (target < untils[i] - offset * 6e4) {
                    return offsets[i];
                }
            }
            return offsets[max];
        },
        abbr: function(mom) {
            return this.abbrs[this._index(mom)];
        },
        offset: function(mom) {
            logError("zone.offset has been deprecated in favor of zone.utcOffset");
            return this.offsets[this._index(mom)];
        },
        utcOffset: function(mom) {
            return this.offsets[this._index(mom)];
        }
    };
    function OffsetAt(at) {
        var timeString = at.toTimeString();
        var abbr = timeString.match(/\([a-z ]+\)/i);
        if (abbr && abbr[0]) {
            abbr = abbr[0].match(/[A-Z]/g);
            abbr = abbr ? abbr.join("") : undefined;
        } else {
            abbr = timeString.match(/[A-Z]{3,5}/g);
            abbr = abbr ? abbr[0] : undefined;
        }
        if (abbr === "GMT") {
            abbr = undefined;
        }
        this.at = +at;
        this.abbr = abbr;
        this.offset = at.getTimezoneOffset();
    }
    function ZoneScore(zone) {
        this.zone = zone;
        this.offsetScore = 0;
        this.abbrScore = 0;
    }
    ZoneScore.prototype.scoreOffsetAt = function(offsetAt) {
        this.offsetScore += Math.abs(this.zone.utcOffset(offsetAt.at) - offsetAt.offset);
        if (this.zone.abbr(offsetAt.at).replace(/[^A-Z]/g, "") !== offsetAt.abbr) {
            this.abbrScore++;
        }
    };
    function findChange(low, high) {
        var mid, diff;
        while (diff = ((high.at - low.at) / 12e4 | 0) * 6e4) {
            mid = new OffsetAt(new Date(low.at + diff));
            if (mid.offset === low.offset) {
                low = mid;
            } else {
                high = mid;
            }
        }
        return low;
    }
    function userOffsets() {
        var startYear = new Date().getFullYear() - 2, last = new OffsetAt(new Date(startYear, 0, 1)), offsets = [ last ], change, next, i;
        for (i = 1; i < 48; i++) {
            next = new OffsetAt(new Date(startYear, i, 1));
            if (next.offset !== last.offset) {
                change = findChange(last, next);
                offsets.push(change);
                offsets.push(new OffsetAt(new Date(change.at + 6e4)));
            }
            last = next;
        }
        for (i = 0; i < 4; i++) {
            offsets.push(new OffsetAt(new Date(startYear + i, 0, 1)));
            offsets.push(new OffsetAt(new Date(startYear + i, 6, 1)));
        }
        return offsets;
    }
    function sortZoneScores(a, b) {
        if (a.offsetScore !== b.offsetScore) {
            return a.offsetScore - b.offsetScore;
        }
        if (a.abbrScore !== b.abbrScore) {
            return a.abbrScore - b.abbrScore;
        }
        return b.zone.population - a.zone.population;
    }
    function addToGuesses(name, offsets) {
        var i, offset;
        arrayToInt(offsets);
        for (i = 0; i < offsets.length; i++) {
            offset = offsets[i];
            guesses[offset] = guesses[offset] || {};
            guesses[offset][name] = true;
        }
    }
    function guessesForUserOffsets(offsets) {
        var offsetsLength = offsets.length, filteredGuesses = {}, out = [], i, j, guessesOffset;
        for (i = 0; i < offsetsLength; i++) {
            guessesOffset = guesses[offsets[i].offset] || {};
            for (j in guessesOffset) {
                if (guessesOffset.hasOwnProperty(j)) {
                    filteredGuesses[j] = true;
                }
            }
        }
        for (i in filteredGuesses) {
            if (filteredGuesses.hasOwnProperty(i)) {
                out.push(names[i]);
            }
        }
        return out;
    }
    function rebuildGuess() {
        try {
            var intlName = Intl.DateTimeFormat().resolvedOptions().timeZone;
            if (intlName && intlName.length > 3) {
                var name = names[normalizeName(intlName)];
                if (name) {
                    return name;
                }
                logError("Moment Timezone found " + intlName + " from the Intl api, but did not have that data loaded.");
            }
        } catch (e) {}
        var offsets = userOffsets(), offsetsLength = offsets.length, guesses = guessesForUserOffsets(offsets), zoneScores = [], zoneScore, i, j;
        for (i = 0; i < guesses.length; i++) {
            zoneScore = new ZoneScore(getZone(guesses[i]), offsetsLength);
            for (j = 0; j < offsetsLength; j++) {
                zoneScore.scoreOffsetAt(offsets[j]);
            }
            zoneScores.push(zoneScore);
        }
        zoneScores.sort(sortZoneScores);
        return zoneScores.length > 0 ? zoneScores[0].zone.name : undefined;
    }
    function guess(ignoreCache) {
        if (!cachedGuess || ignoreCache) {
            cachedGuess = rebuildGuess();
        }
        return cachedGuess;
    }
    function normalizeName(name) {
        return (name || "").toLowerCase().replace(/\//g, "_");
    }
    function addZone(packed) {
        var i, name, split, normalized;
        if (typeof packed === "string") {
            packed = [ packed ];
        }
        for (i = 0; i < packed.length; i++) {
            split = packed[i].split("|");
            name = split[0];
            normalized = normalizeName(name);
            zones[normalized] = packed[i];
            names[normalized] = name;
            addToGuesses(normalized, split[2].split(" "));
        }
    }
    function getZone(name, caller) {
        name = normalizeName(name);
        var zone = zones[name];
        var link;
        if (zone instanceof Zone) {
            return zone;
        }
        if (typeof zone === "string") {
            zone = new Zone(zone);
            zones[name] = zone;
            return zone;
        }
        if (links[name] && caller !== getZone && (link = getZone(links[name], getZone))) {
            zone = zones[name] = new Zone();
            zone._set(link);
            zone.name = names[name];
            return zone;
        }
        return null;
    }
    function getNames() {
        var i, out = [];
        for (i in names) {
            if (names.hasOwnProperty(i) && (zones[i] || zones[links[i]]) && names[i]) {
                out.push(names[i]);
            }
        }
        return out.sort();
    }
    function addLink(aliases) {
        var i, alias, normal0, normal1;
        if (typeof aliases === "string") {
            aliases = [ aliases ];
        }
        for (i = 0; i < aliases.length; i++) {
            alias = aliases[i].split("|");
            normal0 = normalizeName(alias[0]);
            normal1 = normalizeName(alias[1]);
            links[normal0] = normal1;
            names[normal0] = alias[0];
            links[normal1] = normal0;
            names[normal1] = alias[1];
        }
    }
    function loadData(data) {
        addZone(data.zones);
        addLink(data.links);
        tz.dataVersion = data.version;
    }
    function zoneExists(name) {
        if (!zoneExists.didShowError) {
            zoneExists.didShowError = true;
            logError("moment.tz.zoneExists('" + name + "') has been deprecated in favor of !moment.tz.zone('" + name + "')");
        }
        return !!getZone(name);
    }
    function needsOffset(m) {
        var isUnixTimestamp = m._f === "X" || m._f === "x";
        return !!(m._a && m._tzm === undefined && !isUnixTimestamp);
    }
    function logError(message) {
        if (typeof console !== "undefined" && typeof console.error === "function") {
            console.error(message);
        }
    }
    function tz(input) {
        var args = Array.prototype.slice.call(arguments, 0, -1), name = arguments[arguments.length - 1], zone = getZone(name), out = moment.utc.apply(null, args);
        if (zone && !moment.isMoment(input) && needsOffset(out)) {
            out.add(zone.parse(out), "minutes");
        }
        out.tz(name);
        return out;
    }
    tz.version = VERSION;
    tz.dataVersion = "";
    tz._zones = zones;
    tz._links = links;
    tz._names = names;
    tz.add = addZone;
    tz.link = addLink;
    tz.load = loadData;
    tz.zone = getZone;
    tz.zoneExists = zoneExists;
    tz.guess = guess;
    tz.names = getNames;
    tz.Zone = Zone;
    tz.unpack = unpack;
    tz.unpackBase60 = unpackBase60;
    tz.needsOffset = needsOffset;
    tz.moveInvalidForward = true;
    tz.moveAmbiguousForward = false;
    var fn = moment.fn;
    moment.tz = tz;
    moment.defaultZone = null;
    moment.updateOffset = function(mom, keepTime) {
        var zone = moment.defaultZone, offset;
        if (mom._z === undefined) {
            if (zone && needsOffset(mom) && !mom._isUTC) {
                mom._d = moment.utc(mom._a)._d;
                mom.utc().add(zone.parse(mom), "minutes");
            }
            mom._z = zone;
        }
        if (mom._z) {
            offset = mom._z.utcOffset(mom);
            if (Math.abs(offset) < 16) {
                offset = offset / 60;
            }
            if (mom.utcOffset !== undefined) {
                var z = mom._z;
                mom.utcOffset(-offset, keepTime);
                mom._z = z;
            } else {
                mom.zone(offset, keepTime);
            }
        }
    };
    fn.tz = function(name, keepTime) {
        if (name) {
            if (typeof name !== "string") {
                throw new Error("Time zone name must be a string, got " + name + " [" + typeof name + "]");
            }
            this._z = getZone(name);
            if (this._z) {
                moment.updateOffset(this, keepTime);
            } else {
                logError("Moment Timezone has no data for " + name + ". See http://momentjs.com/timezone/docs/#/data-loading/.");
            }
            return this;
        }
        if (this._z) {
            return this._z.name;
        }
    };
    function abbrWrap(old) {
        return function() {
            if (this._z) {
                return this._z.abbr(this);
            }
            return old.call(this);
        };
    }
    function resetZoneWrap(old) {
        return function() {
            this._z = null;
            return old.apply(this, arguments);
        };
    }
    function resetZoneWrap2(old) {
        return function() {
            if (arguments.length > 0) this._z = null;
            return old.apply(this, arguments);
        };
    }
    fn.zoneName = abbrWrap(fn.zoneName);
    fn.zoneAbbr = abbrWrap(fn.zoneAbbr);
    fn.utc = resetZoneWrap(fn.utc);
    fn.local = resetZoneWrap(fn.local);
    fn.utcOffset = resetZoneWrap2(fn.utcOffset);
    moment.tz.setDefault = function(name) {
        if (major < 2 || major === 2 && minor < 9) {
            logError("Moment Timezone setDefault() requires Moment.js >= 2.9.0. You are using Moment.js " + moment.version + ".");
        }
        moment.defaultZone = name ? getZone(name) : null;
        return moment;
    };
    var momentProperties = moment.momentProperties;
    if (Object.prototype.toString.call(momentProperties) === "[object Array]") {
        momentProperties.push("_z");
        momentProperties.push("_a");
    } else if (momentProperties) {
        momentProperties._z = null;
    }
    loadData({
        version: "2019a",
        zones: [ "Africa/Abidjan|GMT|0|0||48e5", "Africa/Nairobi|EAT|-30|0||47e5", "Africa/Algiers|CET|-10|0||26e5", "Africa/Lagos|WAT|-10|0||17e6", "Africa/Maputo|CAT|-20|0||26e5", "Africa/Cairo|EET EEST|-20 -30|01010|1M2m0 gL0 e10 mn0|15e6", "Africa/Casablanca|+00 +01|0 -10|01010101010101010101010101010101|1LHC0 A00 e00 y00 11A0 uM0 e00 Dc0 11A0 s00 e00 IM0 WM0 mo0 gM0 LA0 WM0 jA0 e00 28M0 e00 2600 e00 28M0 e00 2600 gM0 2600 e00 28M0 e00|32e5", "Europe/Paris|CET CEST|-10 -20|01010101010101010101010|1LHB0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00|11e6", "Africa/Johannesburg|SAST|-20|0||84e5", "Africa/Khartoum|EAT CAT|-30 -20|01|1Usl0|51e5", "Africa/Sao_Tome|GMT WAT|0 -10|010|1UQN0 2q00", "Africa/Tripoli|EET|-20|0||11e5", "Africa/Windhoek|CAT WAT|-20 -10|010101010|1LKo0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0|32e4", "America/Adak|HST HDT|a0 90|01010101010101010101010|1Lzo0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|326", "America/Anchorage|AKST AKDT|90 80|01010101010101010101010|1Lzn0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|30e4", "America/Santo_Domingo|AST|40|0||29e5", "America/Fortaleza|-03|30|0||34e5", "America/Asuncion|-03 -04|30 40|01010101010101010101010|1LEP0 1ip0 17b0 1ip0 19X0 1fB0 19X0 1fB0 19X0 1ip0 17b0 1ip0 17b0 1ip0 19X0 1fB0 19X0 1fB0 19X0 1fB0 19X0 1ip0|28e5", "America/Panama|EST|50|0||15e5", "America/Mexico_City|CST CDT|60 50|01010101010101010101010|1LKw0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0|20e6", "America/Managua|CST|60|0||22e5", "America/La_Paz|-04|40|0||19e5", "America/Lima|-05|50|0||11e6", "America/Denver|MST MDT|70 60|01010101010101010101010|1Lzl0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|26e5", "America/Campo_Grande|-03 -04|30 40|01010101010101010101010|1LqP0 1C10 On0 1zd0 On0 1zd0 On0 1zd0 On0 1HB0 FX0 1HB0 FX0 1HB0 IL0 1HB0 FX0 1HB0 IL0 1EN0 FX0 1HB0|77e4", "America/Cancun|CST CDT EST|60 50 50|0102|1LKw0 1lb0 Dd0|63e4", "America/Caracas|-0430 -04|4u 40|01|1QMT0|29e5", "America/Chicago|CST CDT|60 50|01010101010101010101010|1Lzk0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|92e5", "America/Chihuahua|MST MDT|70 60|01010101010101010101010|1LKx0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0 14p0 1lb0 14p0 1nX0 11B0 1nX0 11B0 1nX0 14p0 1lb0|81e4", "America/Phoenix|MST|70|0||42e5", "America/Los_Angeles|PST PDT|80 70|01010101010101010101010|1Lzm0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|15e6", "America/New_York|EST EDT|50 40|01010101010101010101010|1Lzj0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|21e6", "America/Fort_Nelson|PST PDT MST|80 70 70|0102|1Lzm0 1zb0 Op0|39e2", "America/Halifax|AST ADT|40 30|01010101010101010101010|1Lzi0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|39e4", "America/Godthab|-03 -02|30 20|01010101010101010101010|1LHB0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00|17e3", "America/Grand_Turk|EST EDT AST|50 40 40|0101210101010101010|1Lzj0 1zb0 Op0 1zb0 5Ip0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|37e2", "America/Havana|CST CDT|50 40|01010101010101010101010|1Lzh0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0|21e5", "America/Metlakatla|PST AKST AKDT|80 90 80|012121201212121212121|1PAa0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 uM0 jB0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|14e2", "America/Miquelon|-03 -02|30 20|01010101010101010101010|1Lzh0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|61e2", "America/Montevideo|-02 -03|20 30|0101|1Lzg0 1o10 11z0|17e5", "America/Noronha|-02|20|0||30e2", "America/Port-au-Prince|EST EDT|50 40|010101010101010101010|1Lzj0 1zb0 Op0 1zb0 3iN0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|23e5", "Antarctica/Palmer|-03 -04|30 40|01010|1LSP0 Rd0 46n0 Ap0|40", "America/Santiago|-03 -04|30 40|010101010101010101010|1LSP0 Rd0 46n0 Ap0 1Nb0 Ap0 1Nb0 Ap0 1zb0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 11B0|62e5", "America/Sao_Paulo|-02 -03|20 30|01010101010101010101010|1LqO0 1C10 On0 1zd0 On0 1zd0 On0 1zd0 On0 1HB0 FX0 1HB0 FX0 1HB0 IL0 1HB0 FX0 1HB0 IL0 1EN0 FX0 1HB0|20e6", "Atlantic/Azores|-01 +00|10 0|01010101010101010101010|1LHB0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00|25e4", "America/St_Johns|NST NDT|3u 2u|01010101010101010101010|1Lzhu 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0 Rd0 1zb0 Op0 1zb0 Op0 1zb0 Op0 1zb0|11e4", "Antarctica/Casey|+08 +11|-80 -b0|010|1RWg0 3m10|10", "Asia/Bangkok|+07|-70|0||15e6", "Pacific/Port_Moresby|+10|-a0|0||25e4", "Pacific/Guadalcanal|+11|-b0|0||11e4", "Asia/Tashkent|+05|-50|0||23e5", "Pacific/Auckland|NZDT NZST|-d0 -c0|01010101010101010101010|1LKe0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1io0 1a00|14e5", "Asia/Baghdad|+03|-30|0||66e5", "Antarctica/Troll|+00 +02|0 -20|01010101010101010101010|1LHB0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00|40", "Asia/Dhaka|+06|-60|0||16e6", "Asia/Amman|EET EEST|-20 -30|01010101010101010101010|1LGK0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00|25e5", "Asia/Kamchatka|+12|-c0|0||18e4", "Asia/Baku|+04 +05|-40 -50|01010|1LHA0 1o00 11A0 1o00|27e5", "Asia/Barnaul|+07 +06|-70 -60|010|1N7v0 3rd0", "Asia/Beirut|EET EEST|-20 -30|01010101010101010101010|1LHy0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0|22e5", "Asia/Kuala_Lumpur|+08|-80|0||71e5", "Asia/Kolkata|IST|-5u|0||15e6", "Asia/Chita|+10 +08 +09|-a0 -80 -90|012|1N7s0 3re0|33e4", "Asia/Ulaanbaatar|+08 +09|-80 -90|01010|1O8G0 1cJ0 1cP0 1cJ0|12e5", "Asia/Shanghai|CST|-80|0||23e6", "Asia/Colombo|+0530|-5u|0||22e5", "Asia/Damascus|EET EEST|-20 -30|01010101010101010101010|1LGK0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1nX0|26e5", "Asia/Dili|+09|-90|0||19e4", "Asia/Dubai|+04|-40|0||39e5", "Asia/Famagusta|EET EEST +03|-20 -30 -30|0101012010101010101010|1LHB0 1o00 11A0 1o00 11A0 15U0 2Ks0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00", "Asia/Gaza|EET EEST|-20 -30|01010101010101010101010|1LGK0 1nX0 1210 1nz0 1220 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0 11B0 1qL0 WN0 1qL0 WN0 1qL0 WN0 1qL0 11B0 1nX0|18e5", "Asia/Hong_Kong|HKT|-80|0||73e5", "Asia/Hovd|+07 +08|-70 -80|01010|1O8H0 1cJ0 1cP0 1cJ0|81e3", "Asia/Irkutsk|+09 +08|-90 -80|01|1N7t0|60e4", "Europe/Istanbul|EET EEST +03|-20 -30 -30|0101012|1LI10 1nA0 11A0 1tA0 U00 15w0|13e6", "Asia/Jakarta|WIB|-70|0||31e6", "Asia/Jayapura|WIT|-90|0||26e4", "Asia/Jerusalem|IST IDT|-20 -30|01010101010101010101010|1LGM0 1oL0 10N0 1oL0 10N0 1rz0 W10 1rz0 W10 1rz0 10N0 1oL0 10N0 1oL0 10N0 1rz0 W10 1rz0 W10 1rz0 10N0 1oL0|81e4", "Asia/Kabul|+0430|-4u|0||46e5", "Asia/Karachi|PKT|-50|0||24e6", "Asia/Kathmandu|+0545|-5J|0||12e5", "Asia/Yakutsk|+10 +09|-a0 -90|01|1N7s0|28e4", "Asia/Krasnoyarsk|+08 +07|-80 -70|01|1N7u0|10e5", "Asia/Magadan|+12 +10 +11|-c0 -a0 -b0|012|1N7q0 3Cq0|95e3", "Asia/Makassar|WITA|-80|0||15e5", "Asia/Manila|PST|-80|0||24e6", "Europe/Athens|EET EEST|-20 -30|01010101010101010101010|1LHB0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00|35e5", "Asia/Novosibirsk|+07 +06|-70 -60|010|1N7v0 4eN0|15e5", "Asia/Omsk|+07 +06|-70 -60|01|1N7v0|12e5", "Asia/Pyongyang|KST KST|-90 -8u|010|1P4D0 6BA0|29e5", "Asia/Qyzylorda|+06 +05|-60 -50|01|1Xei0|73e4", "Asia/Rangoon|+0630|-6u|0||48e5", "Asia/Sakhalin|+11 +10|-b0 -a0|010|1N7r0 3rd0|58e4", "Asia/Seoul|KST|-90|0||23e6", "Asia/Srednekolymsk|+12 +11|-c0 -b0|01|1N7q0|35e2", "Asia/Tehran|+0330 +0430|-3u -4u|01010101010101010101010|1LEku 1dz0 1cp0 1dz0 1cp0 1dz0 1cN0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0 1cN0 1dz0 1cp0 1dz0 1cp0 1dz0 1cp0 1dz0|14e6", "Asia/Tokyo|JST|-90|0||38e6", "Asia/Tomsk|+07 +06|-70 -60|010|1N7v0 3Qp0|10e5", "Asia/Vladivostok|+11 +10|-b0 -a0|01|1N7r0|60e4", "Asia/Yekaterinburg|+06 +05|-60 -50|01|1N7w0|14e5", "Europe/Lisbon|WET WEST|0 -10|01010101010101010101010|1LHB0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00|27e5", "Atlantic/Cape_Verde|-01|10|0||50e4", "Australia/Sydney|AEDT AEST|-b0 -a0|01010101010101010101010|1LKg0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0|40e5", "Australia/Adelaide|ACDT ACST|-au -9u|01010101010101010101010|1LKgu 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0|11e5", "Australia/Brisbane|AEST|-a0|0||20e5", "Australia/Darwin|ACST|-9u|0||12e4", "Australia/Eucla|+0845|-8J|0||368", "Australia/Lord_Howe|+11 +1030|-b0 -au|01010101010101010101010|1LKf0 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1fAu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1fzu 1cMu|347", "Australia/Perth|AWST|-80|0||18e5", "Pacific/Easter|-05 -06|50 60|010101010101010101010|1LSP0 Rd0 46n0 Ap0 1Nb0 Ap0 1Nb0 Ap0 1zb0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1nX0 11B0 1qL0 11B0|30e2", "Europe/Dublin|GMT IST|0 -10|01010101010101010101010|1LHB0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00|12e5", "Etc/GMT-1|+01|-10|0|", "Pacific/Fakaofo|+13|-d0|0||483", "Pacific/Kiritimati|+14|-e0|0||51e2", "Etc/GMT-2|+02|-20|0|", "Pacific/Tahiti|-10|a0|0||18e4", "Pacific/Niue|-11|b0|0||12e2", "Etc/GMT+12|-12|c0|0|", "Pacific/Galapagos|-06|60|0||25e3", "Etc/GMT+7|-07|70|0|", "Pacific/Pitcairn|-08|80|0||56", "Pacific/Gambier|-09|90|0||125", "Etc/UTC|UTC|0|0|", "Europe/Ulyanovsk|+04 +03|-40 -30|010|1N7y0 3rd0|13e5", "Europe/London|GMT BST|0 -10|01010101010101010101010|1LHB0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00|10e6", "Europe/Chisinau|EET EEST|-20 -30|01010101010101010101010|1LHA0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00|67e4", "Europe/Kaliningrad|+03 EET|-30 -20|01|1N7z0|44e4", "Europe/Kirov|+04 +03|-40 -30|01|1N7y0|48e4", "Europe/Moscow|MSK MSK|-40 -30|01|1N7y0|16e6", "Europe/Saratov|+04 +03|-40 -30|010|1N7y0 5810", "Europe/Simferopol|EET MSK MSK|-20 -40 -30|012|1LHA0 1nW0|33e4", "Europe/Volgograd|+04 +03|-40 -30|010|1N7y0 9Jd0|10e5", "Pacific/Honolulu|HST|a0|0||37e4", "MET|MET MEST|-10 -20|01010101010101010101010|1LHB0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00", "Pacific/Chatham|+1345 +1245|-dJ -cJ|01010101010101010101010|1LKe0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1io0 1a00|600", "Pacific/Apia|+14 +13|-e0 -d0|01010101010101010101010|1LKe0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1io0 1a00|37e3", "Pacific/Bougainville|+10 +11|-a0 -b0|01|1NwE0|18e4", "Pacific/Fiji|+13 +12|-d0 -c0|01010101010101010101010|1Lfp0 1SN0 uM0 1SM0 uM0 1VA0 s00 1VA0 s00 1VA0 s00 1VA0 uM0 1SM0 uM0 1VA0 s00 1VA0 s00 1VA0 s00 1VA0|88e4", "Pacific/Guam|ChST|-a0|0||17e4", "Pacific/Marquesas|-0930|9u|0||86e2", "Pacific/Pago_Pago|SST|b0|0||37e2", "Pacific/Norfolk|+1130 +11|-bu -b0|01|1PoCu|25e4", "Pacific/Tongatapu|+13 +14|-d0 -e0|010|1S4d0 s00|75e3" ],
        links: [ "Africa/Abidjan|Africa/Accra", "Africa/Abidjan|Africa/Bamako", "Africa/Abidjan|Africa/Banjul", "Africa/Abidjan|Africa/Bissau", "Africa/Abidjan|Africa/Conakry", "Africa/Abidjan|Africa/Dakar", "Africa/Abidjan|Africa/Freetown", "Africa/Abidjan|Africa/Lome", "Africa/Abidjan|Africa/Monrovia", "Africa/Abidjan|Africa/Nouakchott", "Africa/Abidjan|Africa/Ouagadougou", "Africa/Abidjan|Africa/Timbuktu", "Africa/Abidjan|America/Danmarkshavn", "Africa/Abidjan|Atlantic/Reykjavik", "Africa/Abidjan|Atlantic/St_Helena", "Africa/Abidjan|Etc/GMT", "Africa/Abidjan|Etc/GMT+0", "Africa/Abidjan|Etc/GMT-0", "Africa/Abidjan|Etc/GMT0", "Africa/Abidjan|Etc/Greenwich", "Africa/Abidjan|GMT", "Africa/Abidjan|GMT+0", "Africa/Abidjan|GMT-0", "Africa/Abidjan|GMT0", "Africa/Abidjan|Greenwich", "Africa/Abidjan|Iceland", "Africa/Algiers|Africa/Tunis", "Africa/Cairo|Egypt", "Africa/Casablanca|Africa/El_Aaiun", "Africa/Johannesburg|Africa/Maseru", "Africa/Johannesburg|Africa/Mbabane", "Africa/Lagos|Africa/Bangui", "Africa/Lagos|Africa/Brazzaville", "Africa/Lagos|Africa/Douala", "Africa/Lagos|Africa/Kinshasa", "Africa/Lagos|Africa/Libreville", "Africa/Lagos|Africa/Luanda", "Africa/Lagos|Africa/Malabo", "Africa/Lagos|Africa/Ndjamena", "Africa/Lagos|Africa/Niamey", "Africa/Lagos|Africa/Porto-Novo", "Africa/Maputo|Africa/Blantyre", "Africa/Maputo|Africa/Bujumbura", "Africa/Maputo|Africa/Gaborone", "Africa/Maputo|Africa/Harare", "Africa/Maputo|Africa/Kigali", "Africa/Maputo|Africa/Lubumbashi", "Africa/Maputo|Africa/Lusaka", "Africa/Nairobi|Africa/Addis_Ababa", "Africa/Nairobi|Africa/Asmara", "Africa/Nairobi|Africa/Asmera", "Africa/Nairobi|Africa/Dar_es_Salaam", "Africa/Nairobi|Africa/Djibouti", "Africa/Nairobi|Africa/Juba", "Africa/Nairobi|Africa/Kampala", "Africa/Nairobi|Africa/Mogadishu", "Africa/Nairobi|Indian/Antananarivo", "Africa/Nairobi|Indian/Comoro", "Africa/Nairobi|Indian/Mayotte", "Africa/Tripoli|Libya", "America/Adak|America/Atka", "America/Adak|US/Aleutian", "America/Anchorage|America/Juneau", "America/Anchorage|America/Nome", "America/Anchorage|America/Sitka", "America/Anchorage|America/Yakutat", "America/Anchorage|US/Alaska", "America/Campo_Grande|America/Cuiaba", "America/Chicago|America/Indiana/Knox", "America/Chicago|America/Indiana/Tell_City", "America/Chicago|America/Knox_IN", "America/Chicago|America/Matamoros", "America/Chicago|America/Menominee", "America/Chicago|America/North_Dakota/Beulah", "America/Chicago|America/North_Dakota/Center", "America/Chicago|America/North_Dakota/New_Salem", "America/Chicago|America/Rainy_River", "America/Chicago|America/Rankin_Inlet", "America/Chicago|America/Resolute", "America/Chicago|America/Winnipeg", "America/Chicago|CST6CDT", "America/Chicago|Canada/Central", "America/Chicago|US/Central", "America/Chicago|US/Indiana-Starke", "America/Chihuahua|America/Mazatlan", "America/Chihuahua|Mexico/BajaSur", "America/Denver|America/Boise", "America/Denver|America/Cambridge_Bay", "America/Denver|America/Edmonton", "America/Denver|America/Inuvik", "America/Denver|America/Ojinaga", "America/Denver|America/Shiprock", "America/Denver|America/Yellowknife", "America/Denver|Canada/Mountain", "America/Denver|MST7MDT", "America/Denver|Navajo", "America/Denver|US/Mountain", "America/Fortaleza|America/Araguaina", "America/Fortaleza|America/Argentina/Buenos_Aires", "America/Fortaleza|America/Argentina/Catamarca", "America/Fortaleza|America/Argentina/ComodRivadavia", "America/Fortaleza|America/Argentina/Cordoba", "America/Fortaleza|America/Argentina/Jujuy", "America/Fortaleza|America/Argentina/La_Rioja", "America/Fortaleza|America/Argentina/Mendoza", "America/Fortaleza|America/Argentina/Rio_Gallegos", "America/Fortaleza|America/Argentina/Salta", "America/Fortaleza|America/Argentina/San_Juan", "America/Fortaleza|America/Argentina/San_Luis", "America/Fortaleza|America/Argentina/Tucuman", "America/Fortaleza|America/Argentina/Ushuaia", "America/Fortaleza|America/Bahia", "America/Fortaleza|America/Belem", "America/Fortaleza|America/Buenos_Aires", "America/Fortaleza|America/Catamarca", "America/Fortaleza|America/Cayenne", "America/Fortaleza|America/Cordoba", "America/Fortaleza|America/Jujuy", "America/Fortaleza|America/Maceio", "America/Fortaleza|America/Mendoza", "America/Fortaleza|America/Paramaribo", "America/Fortaleza|America/Recife", "America/Fortaleza|America/Rosario", "America/Fortaleza|America/Santarem", "America/Fortaleza|Antarctica/Rothera", "America/Fortaleza|Atlantic/Stanley", "America/Fortaleza|Etc/GMT+3", "America/Halifax|America/Glace_Bay", "America/Halifax|America/Goose_Bay", "America/Halifax|America/Moncton", "America/Halifax|America/Thule", "America/Halifax|Atlantic/Bermuda", "America/Halifax|Canada/Atlantic", "America/Havana|Cuba", "America/La_Paz|America/Boa_Vista", "America/La_Paz|America/Guyana", "America/La_Paz|America/Manaus", "America/La_Paz|America/Porto_Velho", "America/La_Paz|Brazil/West", "America/La_Paz|Etc/GMT+4", "America/Lima|America/Bogota", "America/Lima|America/Eirunepe", "America/Lima|America/Guayaquil", "America/Lima|America/Porto_Acre", "America/Lima|America/Rio_Branco", "America/Lima|Brazil/Acre", "America/Lima|Etc/GMT+5", "America/Los_Angeles|America/Dawson", "America/Los_Angeles|America/Ensenada", "America/Los_Angeles|America/Santa_Isabel", "America/Los_Angeles|America/Tijuana", "America/Los_Angeles|America/Vancouver", "America/Los_Angeles|America/Whitehorse", "America/Los_Angeles|Canada/Pacific", "America/Los_Angeles|Canada/Yukon", "America/Los_Angeles|Mexico/BajaNorte", "America/Los_Angeles|PST8PDT", "America/Los_Angeles|US/Pacific", "America/Los_Angeles|US/Pacific-New", "America/Managua|America/Belize", "America/Managua|America/Costa_Rica", "America/Managua|America/El_Salvador", "America/Managua|America/Guatemala", "America/Managua|America/Regina", "America/Managua|America/Swift_Current", "America/Managua|America/Tegucigalpa", "America/Managua|Canada/Saskatchewan", "America/Mexico_City|America/Bahia_Banderas", "America/Mexico_City|America/Merida", "America/Mexico_City|America/Monterrey", "America/Mexico_City|Mexico/General", "America/New_York|America/Detroit", "America/New_York|America/Fort_Wayne", "America/New_York|America/Indiana/Indianapolis", "America/New_York|America/Indiana/Marengo", "America/New_York|America/Indiana/Petersburg", "America/New_York|America/Indiana/Vevay", "America/New_York|America/Indiana/Vincennes", "America/New_York|America/Indiana/Winamac", "America/New_York|America/Indianapolis", "America/New_York|America/Iqaluit", "America/New_York|America/Kentucky/Louisville", "America/New_York|America/Kentucky/Monticello", "America/New_York|America/Louisville", "America/New_York|America/Montreal", "America/New_York|America/Nassau", "America/New_York|America/Nipigon", "America/New_York|America/Pangnirtung", "America/New_York|America/Thunder_Bay", "America/New_York|America/Toronto", "America/New_York|Canada/Eastern", "America/New_York|EST5EDT", "America/New_York|US/East-Indiana", "America/New_York|US/Eastern", "America/New_York|US/Michigan", "America/Noronha|Atlantic/South_Georgia", "America/Noronha|Brazil/DeNoronha", "America/Noronha|Etc/GMT+2", "America/Panama|America/Atikokan", "America/Panama|America/Cayman", "America/Panama|America/Coral_Harbour", "America/Panama|America/Jamaica", "America/Panama|EST", "America/Panama|Jamaica", "America/Phoenix|America/Creston", "America/Phoenix|America/Dawson_Creek", "America/Phoenix|America/Hermosillo", "America/Phoenix|MST", "America/Phoenix|US/Arizona", "America/Santiago|Chile/Continental", "America/Santo_Domingo|America/Anguilla", "America/Santo_Domingo|America/Antigua", "America/Santo_Domingo|America/Aruba", "America/Santo_Domingo|America/Barbados", "America/Santo_Domingo|America/Blanc-Sablon", "America/Santo_Domingo|America/Curacao", "America/Santo_Domingo|America/Dominica", "America/Santo_Domingo|America/Grenada", "America/Santo_Domingo|America/Guadeloupe", "America/Santo_Domingo|America/Kralendijk", "America/Santo_Domingo|America/Lower_Princes", "America/Santo_Domingo|America/Marigot", "America/Santo_Domingo|America/Martinique", "America/Santo_Domingo|America/Montserrat", "America/Santo_Domingo|America/Port_of_Spain", "America/Santo_Domingo|America/Puerto_Rico", "America/Santo_Domingo|America/St_Barthelemy", "America/Santo_Domingo|America/St_Kitts", "America/Santo_Domingo|America/St_Lucia", "America/Santo_Domingo|America/St_Thomas", "America/Santo_Domingo|America/St_Vincent", "America/Santo_Domingo|America/Tortola", "America/Santo_Domingo|America/Virgin", "America/Sao_Paulo|Brazil/East", "America/St_Johns|Canada/Newfoundland", "Antarctica/Palmer|America/Punta_Arenas", "Asia/Baghdad|Antarctica/Syowa", "Asia/Baghdad|Asia/Aden", "Asia/Baghdad|Asia/Bahrain", "Asia/Baghdad|Asia/Kuwait", "Asia/Baghdad|Asia/Qatar", "Asia/Baghdad|Asia/Riyadh", "Asia/Baghdad|Etc/GMT-3", "Asia/Baghdad|Europe/Minsk", "Asia/Bangkok|Antarctica/Davis", "Asia/Bangkok|Asia/Ho_Chi_Minh", "Asia/Bangkok|Asia/Novokuznetsk", "Asia/Bangkok|Asia/Phnom_Penh", "Asia/Bangkok|Asia/Saigon", "Asia/Bangkok|Asia/Vientiane", "Asia/Bangkok|Etc/GMT-7", "Asia/Bangkok|Indian/Christmas", "Asia/Dhaka|Antarctica/Vostok", "Asia/Dhaka|Asia/Almaty", "Asia/Dhaka|Asia/Bishkek", "Asia/Dhaka|Asia/Dacca", "Asia/Dhaka|Asia/Kashgar", "Asia/Dhaka|Asia/Qostanay", "Asia/Dhaka|Asia/Thimbu", "Asia/Dhaka|Asia/Thimphu", "Asia/Dhaka|Asia/Urumqi", "Asia/Dhaka|Etc/GMT-6", "Asia/Dhaka|Indian/Chagos", "Asia/Dili|Etc/GMT-9", "Asia/Dili|Pacific/Palau", "Asia/Dubai|Asia/Muscat", "Asia/Dubai|Asia/Tbilisi", "Asia/Dubai|Asia/Yerevan", "Asia/Dubai|Etc/GMT-4", "Asia/Dubai|Europe/Samara", "Asia/Dubai|Indian/Mahe", "Asia/Dubai|Indian/Mauritius", "Asia/Dubai|Indian/Reunion", "Asia/Gaza|Asia/Hebron", "Asia/Hong_Kong|Hongkong", "Asia/Jakarta|Asia/Pontianak", "Asia/Jerusalem|Asia/Tel_Aviv", "Asia/Jerusalem|Israel", "Asia/Kamchatka|Asia/Anadyr", "Asia/Kamchatka|Etc/GMT-12", "Asia/Kamchatka|Kwajalein", "Asia/Kamchatka|Pacific/Funafuti", "Asia/Kamchatka|Pacific/Kwajalein", "Asia/Kamchatka|Pacific/Majuro", "Asia/Kamchatka|Pacific/Nauru", "Asia/Kamchatka|Pacific/Tarawa", "Asia/Kamchatka|Pacific/Wake", "Asia/Kamchatka|Pacific/Wallis", "Asia/Kathmandu|Asia/Katmandu", "Asia/Kolkata|Asia/Calcutta", "Asia/Kuala_Lumpur|Asia/Brunei", "Asia/Kuala_Lumpur|Asia/Kuching", "Asia/Kuala_Lumpur|Asia/Singapore", "Asia/Kuala_Lumpur|Etc/GMT-8", "Asia/Kuala_Lumpur|Singapore", "Asia/Makassar|Asia/Ujung_Pandang", "Asia/Rangoon|Asia/Yangon", "Asia/Rangoon|Indian/Cocos", "Asia/Seoul|ROK", "Asia/Shanghai|Asia/Chongqing", "Asia/Shanghai|Asia/Chungking", "Asia/Shanghai|Asia/Harbin", "Asia/Shanghai|Asia/Macao", "Asia/Shanghai|Asia/Macau", "Asia/Shanghai|Asia/Taipei", "Asia/Shanghai|PRC", "Asia/Shanghai|ROC", "Asia/Tashkent|Antarctica/Mawson", "Asia/Tashkent|Asia/Aqtau", "Asia/Tashkent|Asia/Aqtobe", "Asia/Tashkent|Asia/Ashgabat", "Asia/Tashkent|Asia/Ashkhabad", "Asia/Tashkent|Asia/Atyrau", "Asia/Tashkent|Asia/Dushanbe", "Asia/Tashkent|Asia/Oral", "Asia/Tashkent|Asia/Samarkand", "Asia/Tashkent|Etc/GMT-5", "Asia/Tashkent|Indian/Kerguelen", "Asia/Tashkent|Indian/Maldives", "Asia/Tehran|Iran", "Asia/Tokyo|Japan", "Asia/Ulaanbaatar|Asia/Choibalsan", "Asia/Ulaanbaatar|Asia/Ulan_Bator", "Asia/Vladivostok|Asia/Ust-Nera", "Asia/Yakutsk|Asia/Khandyga", "Atlantic/Azores|America/Scoresbysund", "Atlantic/Cape_Verde|Etc/GMT+1", "Australia/Adelaide|Australia/Broken_Hill", "Australia/Adelaide|Australia/South", "Australia/Adelaide|Australia/Yancowinna", "Australia/Brisbane|Australia/Lindeman", "Australia/Brisbane|Australia/Queensland", "Australia/Darwin|Australia/North", "Australia/Lord_Howe|Australia/LHI", "Australia/Perth|Australia/West", "Australia/Sydney|Australia/ACT", "Australia/Sydney|Australia/Canberra", "Australia/Sydney|Australia/Currie", "Australia/Sydney|Australia/Hobart", "Australia/Sydney|Australia/Melbourne", "Australia/Sydney|Australia/NSW", "Australia/Sydney|Australia/Tasmania", "Australia/Sydney|Australia/Victoria", "Etc/UTC|Etc/UCT", "Etc/UTC|Etc/Universal", "Etc/UTC|Etc/Zulu", "Etc/UTC|UCT", "Etc/UTC|UTC", "Etc/UTC|Universal", "Etc/UTC|Zulu", "Europe/Athens|Asia/Nicosia", "Europe/Athens|EET", "Europe/Athens|Europe/Bucharest", "Europe/Athens|Europe/Helsinki", "Europe/Athens|Europe/Kiev", "Europe/Athens|Europe/Mariehamn", "Europe/Athens|Europe/Nicosia", "Europe/Athens|Europe/Riga", "Europe/Athens|Europe/Sofia", "Europe/Athens|Europe/Tallinn", "Europe/Athens|Europe/Uzhgorod", "Europe/Athens|Europe/Vilnius", "Europe/Athens|Europe/Zaporozhye", "Europe/Chisinau|Europe/Tiraspol", "Europe/Dublin|Eire", "Europe/Istanbul|Asia/Istanbul", "Europe/Istanbul|Turkey", "Europe/Lisbon|Atlantic/Canary", "Europe/Lisbon|Atlantic/Faeroe", "Europe/Lisbon|Atlantic/Faroe", "Europe/Lisbon|Atlantic/Madeira", "Europe/Lisbon|Portugal", "Europe/Lisbon|WET", "Europe/London|Europe/Belfast", "Europe/London|Europe/Guernsey", "Europe/London|Europe/Isle_of_Man", "Europe/London|Europe/Jersey", "Europe/London|GB", "Europe/London|GB-Eire", "Europe/Moscow|W-SU", "Europe/Paris|Africa/Ceuta", "Europe/Paris|Arctic/Longyearbyen", "Europe/Paris|Atlantic/Jan_Mayen", "Europe/Paris|CET", "Europe/Paris|Europe/Amsterdam", "Europe/Paris|Europe/Andorra", "Europe/Paris|Europe/Belgrade", "Europe/Paris|Europe/Berlin", "Europe/Paris|Europe/Bratislava", "Europe/Paris|Europe/Brussels", "Europe/Paris|Europe/Budapest", "Europe/Paris|Europe/Busingen", "Europe/Paris|Europe/Copenhagen", "Europe/Paris|Europe/Gibraltar", "Europe/Paris|Europe/Ljubljana", "Europe/Paris|Europe/Luxembourg", "Europe/Paris|Europe/Madrid", "Europe/Paris|Europe/Malta", "Europe/Paris|Europe/Monaco", "Europe/Paris|Europe/Oslo", "Europe/Paris|Europe/Podgorica", "Europe/Paris|Europe/Prague", "Europe/Paris|Europe/Rome", "Europe/Paris|Europe/San_Marino", "Europe/Paris|Europe/Sarajevo", "Europe/Paris|Europe/Skopje", "Europe/Paris|Europe/Stockholm", "Europe/Paris|Europe/Tirane", "Europe/Paris|Europe/Vaduz", "Europe/Paris|Europe/Vatican", "Europe/Paris|Europe/Vienna", "Europe/Paris|Europe/Warsaw", "Europe/Paris|Europe/Zagreb", "Europe/Paris|Europe/Zurich", "Europe/Paris|Poland", "Europe/Ulyanovsk|Europe/Astrakhan", "Pacific/Auckland|Antarctica/McMurdo", "Pacific/Auckland|Antarctica/South_Pole", "Pacific/Auckland|NZ", "Pacific/Chatham|NZ-CHAT", "Pacific/Easter|Chile/EasterIsland", "Pacific/Fakaofo|Etc/GMT-13", "Pacific/Fakaofo|Pacific/Enderbury", "Pacific/Galapagos|Etc/GMT+6", "Pacific/Gambier|Etc/GMT+9", "Pacific/Guadalcanal|Antarctica/Macquarie", "Pacific/Guadalcanal|Etc/GMT-11", "Pacific/Guadalcanal|Pacific/Efate", "Pacific/Guadalcanal|Pacific/Kosrae", "Pacific/Guadalcanal|Pacific/Noumea", "Pacific/Guadalcanal|Pacific/Pohnpei", "Pacific/Guadalcanal|Pacific/Ponape", "Pacific/Guam|Pacific/Saipan", "Pacific/Honolulu|HST", "Pacific/Honolulu|Pacific/Johnston", "Pacific/Honolulu|US/Hawaii", "Pacific/Kiritimati|Etc/GMT-14", "Pacific/Niue|Etc/GMT+11", "Pacific/Pago_Pago|Pacific/Midway", "Pacific/Pago_Pago|Pacific/Samoa", "Pacific/Pago_Pago|US/Samoa", "Pacific/Pitcairn|Etc/GMT+8", "Pacific/Port_Moresby|Antarctica/DumontDUrville", "Pacific/Port_Moresby|Etc/GMT-10", "Pacific/Port_Moresby|Pacific/Chuuk", "Pacific/Port_Moresby|Pacific/Truk", "Pacific/Port_Moresby|Pacific/Yap", "Pacific/Tahiti|Etc/GMT+10", "Pacific/Tahiti|Pacific/Rarotonga" ]
    });
    return moment;
});

(function(factory) {
    if (typeof define == "function" && define.amd) define("picker", [ "jquery" ], factory); else if (typeof exports == "object") module.exports = factory(require("jquery")); else this.Picker = factory(jQuery);
})(function($) {
    var $window = $(window);
    var $document = $(document);
    var $html = $(document.documentElement);
    var supportsTransitions = document.documentElement.style.transition != null;
    function PickerConstructor(ELEMENT, NAME, COMPONENT, OPTIONS) {
        if (!ELEMENT) return PickerConstructor;
        var IS_DEFAULT_THEME = false, STATE = {
            id: ELEMENT.id || "P" + Math.abs(~~(Math.random() * new Date()))
        }, SETTINGS = COMPONENT ? $.extend(true, {}, COMPONENT.defaults, OPTIONS) : OPTIONS || {}, CLASSES = $.extend({}, PickerConstructor.klasses(), SETTINGS.klass), $ELEMENT = $(ELEMENT), PickerInstance = function() {
            return this.start();
        }, P = PickerInstance.prototype = {
            constructor: PickerInstance,
            $node: $ELEMENT,
            start: function() {
                if (STATE && STATE.start) return P;
                STATE.methods = {};
                STATE.start = true;
                STATE.open = false;
                STATE.type = ELEMENT.type;
                ELEMENT.autofocus = ELEMENT == getActiveElement();
                ELEMENT.readOnly = !SETTINGS.editable;
                ELEMENT.id = ELEMENT.id || STATE.id;
                if (ELEMENT.type != "text") {
                    ELEMENT.type = "text";
                }
                P.component = new COMPONENT(P, SETTINGS);
                P.$root = $('<div class="' + CLASSES.picker + '" id="' + ELEMENT.id + '_root" />');
                prepareElementRoot();
                P.$holder = $(createWrappedComponent()).appendTo(P.$root);
                prepareElementHolder();
                if (SETTINGS.formatSubmit) {
                    prepareElementHidden();
                }
                prepareElement();
                if (SETTINGS.containerHidden) $(SETTINGS.containerHidden).append(P._hidden); else $ELEMENT.after(P._hidden);
                if (SETTINGS.container) $(SETTINGS.container).append(P.$root); else $ELEMENT.after(P.$root);
                P.on({
                    start: P.component.onStart,
                    render: P.component.onRender,
                    stop: P.component.onStop,
                    open: P.component.onOpen,
                    close: P.component.onClose,
                    set: P.component.onSet
                }).on({
                    start: SETTINGS.onStart,
                    render: SETTINGS.onRender,
                    stop: SETTINGS.onStop,
                    open: SETTINGS.onOpen,
                    close: SETTINGS.onClose,
                    set: SETTINGS.onSet
                });
                IS_DEFAULT_THEME = isUsingDefaultTheme(P.$holder[0]);
                if (ELEMENT.autofocus) {
                    P.open();
                }
                return P.trigger("start").trigger("render");
            },
            render: function(entireComponent) {
                if (entireComponent) {
                    P.$holder = $(createWrappedComponent());
                    prepareElementHolder();
                    P.$root.html(P.$holder);
                } else P.$root.find("." + CLASSES.box).html(P.component.nodes(STATE.open));
                return P.trigger("render");
            },
            stop: function() {
                if (!STATE.start) return P;
                P.close();
                if (P._hidden) {
                    P._hidden.parentNode.removeChild(P._hidden);
                }
                P.$root.remove();
                $ELEMENT.removeClass(CLASSES.input).removeData(NAME);
                setTimeout(function() {
                    $ELEMENT.off("." + STATE.id);
                }, 0);
                ELEMENT.type = STATE.type;
                ELEMENT.readOnly = false;
                P.trigger("stop");
                STATE.methods = {};
                STATE.start = false;
                return P;
            },
            open: function(dontGiveFocus) {
                if (STATE.open) return P;
                $ELEMENT.addClass(CLASSES.active);
                aria(ELEMENT, "expanded", true);
                setTimeout(function() {
                    P.$root.addClass(CLASSES.opened);
                    aria(P.$root[0], "hidden", false);
                }, 0);
                if (dontGiveFocus !== false) {
                    STATE.open = true;
                    if (IS_DEFAULT_THEME) {
                        $html.css("overflow", "hidden").css("padding-right", "+=" + getScrollbarWidth());
                    }
                    focusPickerOnceOpened();
                    $document.on("click." + STATE.id + " focusin." + STATE.id, function(event) {
                        var target = event.target;
                        if (target != ELEMENT && target != document && event.which != 3) {
                            P.close(target === P.$holder[0]);
                        }
                    }).on("keydown." + STATE.id, function(event) {
                        var keycode = event.keyCode, keycodeToMove = P.component.key[keycode], target = event.target;
                        if (keycode == 27) {
                            P.close(true);
                        } else if (target == P.$holder[0] && (keycodeToMove || keycode == 13)) {
                            event.preventDefault();
                            if (keycodeToMove) {
                                PickerConstructor._.trigger(P.component.key.go, P, [ PickerConstructor._.trigger(keycodeToMove) ]);
                            } else if (!P.$root.find("." + CLASSES.highlighted).hasClass(CLASSES.disabled)) {
                                P.set("select", P.component.item.highlight);
                                if (SETTINGS.closeOnSelect) {
                                    P.close(true);
                                }
                            }
                        } else if ($.contains(P.$root[0], target) && keycode == 13) {
                            event.preventDefault();
                            target.click();
                        }
                    });
                }
                return P.trigger("open");
            },
            close: function(giveFocus) {
                if (giveFocus) {
                    if (SETTINGS.editable) {
                        ELEMENT.focus();
                    } else {
                        P.$holder.off("focus.toOpen").focus();
                        setTimeout(function() {
                            P.$holder.on("focus.toOpen", handleFocusToOpenEvent);
                        }, 0);
                    }
                }
                $ELEMENT.removeClass(CLASSES.active);
                aria(ELEMENT, "expanded", false);
                setTimeout(function() {
                    P.$root.removeClass(CLASSES.opened + " " + CLASSES.focused);
                    aria(P.$root[0], "hidden", true);
                }, 0);
                if (!STATE.open) return P;
                STATE.open = false;
                if (IS_DEFAULT_THEME) {
                    $html.css("overflow", "").css("padding-right", "-=" + getScrollbarWidth());
                }
                $document.off("." + STATE.id);
                return P.trigger("close");
            },
            clear: function(options) {
                return P.set("clear", null, options);
            },
            set: function(thing, value, options) {
                var thingItem, thingValue, thingIsObject = $.isPlainObject(thing), thingObject = thingIsObject ? thing : {};
                options = thingIsObject && $.isPlainObject(value) ? value : options || {};
                if (thing) {
                    if (!thingIsObject) {
                        thingObject[thing] = value;
                    }
                    for (thingItem in thingObject) {
                        thingValue = thingObject[thingItem];
                        if (thingItem in P.component.item) {
                            if (thingValue === undefined) thingValue = null;
                            P.component.set(thingItem, thingValue, options);
                        }
                        if (thingItem == "select" || thingItem == "clear") {
                            $ELEMENT.val(thingItem == "clear" ? "" : P.get(thingItem, SETTINGS.format)).trigger("change");
                        }
                    }
                    P.render();
                }
                return options.muted ? P : P.trigger("set", thingObject);
            },
            get: function(thing, format) {
                thing = thing || "value";
                if (STATE[thing] != null) {
                    return STATE[thing];
                }
                if (thing == "valueSubmit") {
                    if (P._hidden) {
                        return P._hidden.value;
                    }
                    thing = "value";
                }
                if (thing == "value") {
                    return ELEMENT.value;
                }
                if (thing in P.component.item) {
                    if (typeof format == "string") {
                        var thingValue = P.component.get(thing);
                        return thingValue ? PickerConstructor._.trigger(P.component.formats.toString, P.component, [ format, thingValue ]) : "";
                    }
                    return P.component.get(thing);
                }
            },
            on: function(thing, method, internal) {
                var thingName, thingMethod, thingIsObject = $.isPlainObject(thing), thingObject = thingIsObject ? thing : {};
                if (thing) {
                    if (!thingIsObject) {
                        thingObject[thing] = method;
                    }
                    for (thingName in thingObject) {
                        thingMethod = thingObject[thingName];
                        if (internal) {
                            thingName = "_" + thingName;
                        }
                        STATE.methods[thingName] = STATE.methods[thingName] || [];
                        STATE.methods[thingName].push(thingMethod);
                    }
                }
                return P;
            },
            off: function() {
                var i, thingName, names = arguments;
                for (i = 0, namesCount = names.length; i < namesCount; i += 1) {
                    thingName = names[i];
                    if (thingName in STATE.methods) {
                        delete STATE.methods[thingName];
                    }
                }
                return P;
            },
            trigger: function(name, data) {
                var _trigger = function(name) {
                    var methodList = STATE.methods[name];
                    if (methodList) {
                        methodList.map(function(method) {
                            PickerConstructor._.trigger(method, P, [ data ]);
                        });
                    }
                };
                _trigger("_" + name);
                _trigger(name);
                return P;
            }
        };
        function createWrappedComponent() {
            return PickerConstructor._.node("div", PickerConstructor._.node("div", PickerConstructor._.node("div", PickerConstructor._.node("div", P.component.nodes(STATE.open), CLASSES.box), CLASSES.wrap), CLASSES.frame), CLASSES.holder, 'tabindex="-1"');
        }
        function prepareElement() {
            $ELEMENT.data(NAME, P).addClass(CLASSES.input).val($ELEMENT.data("value") ? P.get("select", SETTINGS.format) : ELEMENT.value);
            if (!SETTINGS.editable) {
                $ELEMENT.on("focus." + STATE.id + " click." + STATE.id, function(event) {
                    event.preventDefault();
                    P.open();
                }).on("keydown." + STATE.id, handleKeydownEvent);
            }
            aria(ELEMENT, {
                haspopup: true,
                expanded: false,
                readonly: false,
                owns: ELEMENT.id + "_root"
            });
        }
        function prepareElementRoot() {
            aria(P.$root[0], "hidden", true);
        }
        function prepareElementHolder() {
            P.$holder.on({
                keydown: handleKeydownEvent,
                "focus.toOpen": handleFocusToOpenEvent,
                blur: function() {
                    $ELEMENT.removeClass(CLASSES.target);
                },
                focusin: function(event) {
                    P.$root.removeClass(CLASSES.focused);
                    event.stopPropagation();
                },
                "mousedown click": function(event) {
                    var target = event.target;
                    if (target != P.$holder[0]) {
                        event.stopPropagation();
                        if (event.type == "mousedown" && !$(target).is("input, select, textarea, button, option")) {
                            event.preventDefault();
                            P.$holder[0].focus();
                        }
                    }
                }
            }).on("click", "[data-pick], [data-nav], [data-clear], [data-close]", function() {
                var $target = $(this), targetData = $target.data(), targetDisabled = $target.hasClass(CLASSES.navDisabled) || $target.hasClass(CLASSES.disabled), activeElement = getActiveElement();
                activeElement = activeElement && (activeElement.type || activeElement.href);
                if (targetDisabled || activeElement && !$.contains(P.$root[0], activeElement)) {
                    P.$holder[0].focus();
                }
                if (!targetDisabled && targetData.nav) {
                    P.set("highlight", P.component.item.highlight, {
                        nav: targetData.nav
                    });
                } else if (!targetDisabled && "pick" in targetData) {
                    P.set("select", targetData.pick);
                    if (SETTINGS.closeOnSelect) {
                        P.close(true);
                    }
                } else if (targetData.clear) {
                    P.clear();
                    if (SETTINGS.closeOnClear) {
                        P.close(true);
                    }
                } else if (targetData.close) {
                    P.close(true);
                }
            });
        }
        function prepareElementHidden() {
            var name;
            if (SETTINGS.hiddenName === true) {
                name = ELEMENT.name;
                ELEMENT.name = "";
            } else {
                name = [ typeof SETTINGS.hiddenPrefix == "string" ? SETTINGS.hiddenPrefix : "", typeof SETTINGS.hiddenSuffix == "string" ? SETTINGS.hiddenSuffix : "_submit" ];
                name = name[0] + ELEMENT.name + name[1];
            }
            P._hidden = $("<input " + "type=hidden " + 'name="' + name + '"' + ($ELEMENT.data("value") || ELEMENT.value ? ' value="' + P.get("select", SETTINGS.formatSubmit) + '"' : "") + ">")[0];
            $ELEMENT.on("change." + STATE.id, function() {
                P._hidden.value = ELEMENT.value ? P.get("select", SETTINGS.formatSubmit) : "";
            });
        }
        function focusPickerOnceOpened() {
            if (IS_DEFAULT_THEME && supportsTransitions) {
                P.$holder.find("." + CLASSES.frame).one("transitionend", function() {
                    P.$holder[0].focus();
                });
            } else {
                P.$holder[0].focus();
            }
        }
        function handleFocusToOpenEvent(event) {
            event.stopPropagation();
            $ELEMENT.addClass(CLASSES.target);
            P.$root.addClass(CLASSES.focused);
            P.open();
        }
        function handleKeydownEvent(event) {
            var keycode = event.keyCode, isKeycodeDelete = /^(8|46)$/.test(keycode);
            if (keycode == 27) {
                P.close(true);
                return false;
            }
            if (keycode == 32 || isKeycodeDelete || !STATE.open && P.component.key[keycode]) {
                event.preventDefault();
                event.stopPropagation();
                if (isKeycodeDelete) {
                    P.clear().close();
                } else {
                    P.open();
                }
            }
        }
        return new PickerInstance();
    }
    PickerConstructor.klasses = function(prefix) {
        prefix = prefix || "picker";
        return {
            picker: prefix,
            opened: prefix + "--opened",
            focused: prefix + "--focused",
            input: prefix + "__input",
            active: prefix + "__input--active",
            target: prefix + "__input--target",
            holder: prefix + "__holder",
            frame: prefix + "__frame",
            wrap: prefix + "__wrap",
            box: prefix + "__box"
        };
    };
    function isUsingDefaultTheme(element) {
        var theme, prop = "position";
        if (element.currentStyle) {
            theme = element.currentStyle[prop];
        } else if (window.getComputedStyle) {
            theme = getComputedStyle(element)[prop];
        }
        return theme == "fixed";
    }
    function getScrollbarWidth() {
        if ($html.height() <= $window.height()) {
            return 0;
        }
        var $outer = $('<div style="visibility:hidden;width:100px" />').appendTo("body");
        var widthWithoutScroll = $outer[0].offsetWidth;
        $outer.css("overflow", "scroll");
        var $inner = $('<div style="width:100%" />').appendTo($outer);
        var widthWithScroll = $inner[0].offsetWidth;
        $outer.remove();
        return widthWithoutScroll - widthWithScroll;
    }
    PickerConstructor._ = {
        group: function(groupObject) {
            var loopObjectScope, nodesList = "", counter = PickerConstructor._.trigger(groupObject.min, groupObject);
            for (;counter <= PickerConstructor._.trigger(groupObject.max, groupObject, [ counter ]); counter += groupObject.i) {
                loopObjectScope = PickerConstructor._.trigger(groupObject.item, groupObject, [ counter ]);
                nodesList += PickerConstructor._.node(groupObject.node, loopObjectScope[0], loopObjectScope[1], loopObjectScope[2]);
            }
            return nodesList;
        },
        node: function(wrapper, item, klass, attribute) {
            if (!item) return "";
            item = $.isArray(item) ? item.join("") : item;
            klass = klass ? ' class="' + klass + '"' : "";
            attribute = attribute ? " " + attribute : "";
            return "<" + wrapper + klass + attribute + ">" + item + "</" + wrapper + ">";
        },
        lead: function(number) {
            return (number < 10 ? "0" : "") + number;
        },
        trigger: function(callback, scope, args) {
            return typeof callback == "function" ? callback.apply(scope, args || []) : callback;
        },
        digits: function(string) {
            return /\d/.test(string[1]) ? 2 : 1;
        },
        isDate: function(value) {
            return {}.toString.call(value).indexOf("Date") > -1 && this.isInteger(value.getDate());
        },
        isInteger: function(value) {
            return {}.toString.call(value).indexOf("Number") > -1 && value % 1 === 0;
        },
        ariaAttr: ariaAttr
    };
    PickerConstructor.extend = function(name, Component) {
        $.fn[name] = function(options, action) {
            var componentData = this.data(name);
            if (options == "picker") {
                return componentData;
            }
            if (componentData && typeof options == "string") {
                return PickerConstructor._.trigger(componentData[options], componentData, [ action ]);
            }
            return this.each(function() {
                var $this = $(this);
                if (!$this.data(name)) {
                    new PickerConstructor(this, name, Component, options);
                }
            });
        };
        $.fn[name].defaults = Component.defaults;
    };
    function aria(element, attribute, value) {
        if ($.isPlainObject(attribute)) {
            for (var key in attribute) {
                ariaSet(element, key, attribute[key]);
            }
        } else {
            ariaSet(element, attribute, value);
        }
    }
    function ariaSet(element, attribute, value) {
        element.setAttribute((attribute == "role" ? "" : "aria-") + attribute, value);
    }
    function ariaAttr(attribute, data) {
        if (!$.isPlainObject(attribute)) {
            attribute = {
                attribute: data
            };
        }
        data = "";
        for (var key in attribute) {
            var attr = (key == "role" ? "" : "aria-") + key, attrVal = attribute[key];
            data += attrVal == null ? "" : attr + '="' + attribute[key] + '"';
        }
        return data;
    }
    function getActiveElement() {
        try {
            return document.activeElement;
        } catch (err) {}
    }
    return PickerConstructor;
});

(function(factory) {
    if (typeof define == "function" && define.amd) define([ "picker", "jquery" ], factory); else if (typeof exports == "object") module.exports = factory(require("./picker.js"), require("jquery")); else factory(Picker, jQuery);
})(function(Picker, $) {
    var DAYS_IN_WEEK = 7, WEEKS_IN_CALENDAR = 6, _ = Picker._;
    function DatePicker(picker, settings) {
        var calendar = this, element = picker.$node[0], elementValue = element.value, elementDataValue = picker.$node.data("value"), valueString = elementDataValue || elementValue, formatString = elementDataValue ? settings.formatSubmit : settings.format, isRTL = function() {
            return element.currentStyle ? element.currentStyle.direction == "rtl" : getComputedStyle(picker.$root[0]).direction == "rtl";
        };
        calendar.settings = settings;
        calendar.$node = picker.$node;
        calendar.queue = {
            min: "measure create",
            max: "measure create",
            now: "now create",
            select: "parse create validate",
            highlight: "parse navigate create validate",
            view: "parse create validate viewset",
            disable: "deactivate",
            enable: "activate"
        };
        calendar.item = {};
        calendar.item.clear = null;
        calendar.item.disable = (settings.disable || []).slice(0);
        calendar.item.enable = -function(collectionDisabled) {
            return collectionDisabled[0] === true ? collectionDisabled.shift() : -1;
        }(calendar.item.disable);
        calendar.set("min", settings.min).set("max", settings.max).set("now");
        if (valueString) {
            calendar.set("select", valueString, {
                format: formatString,
                defaultValue: true
            });
        } else {
            calendar.set("select", null).set("highlight", calendar.item.now);
        }
        calendar.key = {
            40: 7,
            38: -7,
            39: function() {
                return isRTL() ? -1 : 1;
            },
            37: function() {
                return isRTL() ? 1 : -1;
            },
            go: function(timeChange) {
                var highlightedObject = calendar.item.highlight, targetDate = new Date(highlightedObject.year, highlightedObject.month, highlightedObject.date + timeChange);
                calendar.set("highlight", targetDate, {
                    interval: timeChange
                });
                this.render();
            }
        };
        picker.on("render", function() {
            picker.$root.find("." + settings.klass.selectMonth).on("change", function() {
                var value = this.value;
                if (value) {
                    picker.set("highlight", [ picker.get("view").year, value, picker.get("highlight").date ]);
                    picker.$root.find("." + settings.klass.selectMonth).trigger("focus");
                }
            });
            picker.$root.find("." + settings.klass.selectYear).on("change", function() {
                var value = this.value;
                if (value) {
                    picker.set("highlight", [ value, picker.get("view").month, picker.get("highlight").date ]);
                    picker.$root.find("." + settings.klass.selectYear).trigger("focus");
                }
            });
        }, 1).on("open", function() {
            var includeToday = "";
            if (calendar.disabled(calendar.get("now"))) {
                includeToday = ":not(." + settings.klass.buttonToday + ")";
            }
            picker.$root.find("button" + includeToday + ", select").attr("disabled", false);
        }, 1).on("close", function() {
            picker.$root.find("button, select").attr("disabled", true);
        }, 1);
    }
    DatePicker.prototype.set = function(type, value, options) {
        var calendar = this, calendarItem = calendar.item;
        if (value === null) {
            if (type == "clear") type = "select";
            calendarItem[type] = value;
            return calendar;
        }
        calendarItem[type == "enable" ? "disable" : type == "flip" ? "enable" : type] = calendar.queue[type].split(" ").map(function(method) {
            value = calendar[method](type, value, options);
            return value;
        }).pop();
        if (type == "select") {
            calendar.set("highlight", calendarItem.select, options);
        } else if (type == "highlight") {
            calendar.set("view", calendarItem.highlight, options);
        } else if (type.match(/^(flip|min|max|disable|enable)$/)) {
            if (calendarItem.select && calendar.disabled(calendarItem.select)) {
                calendar.set("select", calendarItem.select, options);
            }
            if (calendarItem.highlight && calendar.disabled(calendarItem.highlight)) {
                calendar.set("highlight", calendarItem.highlight, options);
            }
        }
        return calendar;
    };
    DatePicker.prototype.get = function(type) {
        return this.item[type];
    };
    DatePicker.prototype.create = function(type, value, options) {
        var isInfiniteValue, calendar = this;
        value = value === undefined ? type : value;
        if (value == -Infinity || value == Infinity) {
            isInfiniteValue = value;
        } else if ($.isPlainObject(value) && _.isInteger(value.pick)) {
            value = value.obj;
        } else if ($.isArray(value)) {
            value = new Date(value[0], value[1], value[2]);
            value = _.isDate(value) ? value : calendar.create().obj;
        } else if (_.isInteger(value) || _.isDate(value)) {
            value = calendar.normalize(new Date(value), options);
        } else {
            value = calendar.now(type, value, options);
        }
        return {
            year: isInfiniteValue || value.getFullYear(),
            month: isInfiniteValue || value.getMonth(),
            date: isInfiniteValue || value.getDate(),
            day: isInfiniteValue || value.getDay(),
            obj: isInfiniteValue || value,
            pick: isInfiniteValue || value.getTime()
        };
    };
    DatePicker.prototype.createRange = function(from, to) {
        var calendar = this, createDate = function(date) {
            if (date === true || $.isArray(date) || _.isDate(date)) {
                return calendar.create(date);
            }
            return date;
        };
        if (!_.isInteger(from)) {
            from = createDate(from);
        }
        if (!_.isInteger(to)) {
            to = createDate(to);
        }
        if (_.isInteger(from) && $.isPlainObject(to)) {
            from = [ to.year, to.month, to.date + from ];
        } else if (_.isInteger(to) && $.isPlainObject(from)) {
            to = [ from.year, from.month, from.date + to ];
        }
        return {
            from: createDate(from),
            to: createDate(to)
        };
    };
    DatePicker.prototype.withinRange = function(range, dateUnit) {
        range = this.createRange(range.from, range.to);
        return dateUnit.pick >= range.from.pick && dateUnit.pick <= range.to.pick;
    };
    DatePicker.prototype.overlapRanges = function(one, two) {
        var calendar = this;
        one = calendar.createRange(one.from, one.to);
        two = calendar.createRange(two.from, two.to);
        return calendar.withinRange(one, two.from) || calendar.withinRange(one, two.to) || calendar.withinRange(two, one.from) || calendar.withinRange(two, one.to);
    };
    DatePicker.prototype.now = function(type, value, options) {
        value = new Date();
        if (options && options.rel) {
            value.setDate(value.getDate() + options.rel);
        }
        return this.normalize(value, options);
    };
    DatePicker.prototype.navigate = function(type, value, options) {
        var targetDateObject, targetYear, targetMonth, targetDate, isTargetArray = $.isArray(value), isTargetObject = $.isPlainObject(value), viewsetObject = this.item.view;
        if (isTargetArray || isTargetObject) {
            if (isTargetObject) {
                targetYear = value.year;
                targetMonth = value.month;
                targetDate = value.date;
            } else {
                targetYear = +value[0];
                targetMonth = +value[1];
                targetDate = +value[2];
            }
            if (options && options.nav && viewsetObject && viewsetObject.month !== targetMonth) {
                targetYear = viewsetObject.year;
                targetMonth = viewsetObject.month;
            }
            targetDateObject = new Date(targetYear, targetMonth + (options && options.nav ? options.nav : 0), 1);
            targetYear = targetDateObject.getFullYear();
            targetMonth = targetDateObject.getMonth();
            while (new Date(targetYear, targetMonth, targetDate).getMonth() !== targetMonth) {
                targetDate -= 1;
            }
            value = [ targetYear, targetMonth, targetDate ];
        }
        return value;
    };
    DatePicker.prototype.normalize = function(value) {
        value.setHours(0, 0, 0, 0);
        return value;
    };
    DatePicker.prototype.measure = function(type, value) {
        var calendar = this;
        if (!value) {
            value = type == "min" ? -Infinity : Infinity;
        } else if (typeof value == "string") {
            value = calendar.parse(type, value);
        } else if (_.isInteger(value)) {
            value = calendar.now(type, value, {
                rel: value
            });
        }
        return value;
    };
    DatePicker.prototype.viewset = function(type, dateObject) {
        return this.create([ dateObject.year, dateObject.month, 1 ]);
    };
    DatePicker.prototype.validate = function(type, dateObject, options) {
        var calendar = this, originalDateObject = dateObject, interval = options && options.interval ? options.interval : 1, isFlippedBase = calendar.item.enable === -1, hasEnabledBeforeTarget, hasEnabledAfterTarget, minLimitObject = calendar.item.min, maxLimitObject = calendar.item.max, reachedMin, reachedMax, hasEnabledWeekdays = isFlippedBase && calendar.item.disable.filter(function(value) {
            if ($.isArray(value)) {
                var dateTime = calendar.create(value).pick;
                if (dateTime < dateObject.pick) hasEnabledBeforeTarget = true; else if (dateTime > dateObject.pick) hasEnabledAfterTarget = true;
            }
            return _.isInteger(value);
        }).length;
        if (!options || !options.nav && !options.defaultValue) if (!isFlippedBase && calendar.disabled(dateObject) || isFlippedBase && calendar.disabled(dateObject) && (hasEnabledWeekdays || hasEnabledBeforeTarget || hasEnabledAfterTarget) || !isFlippedBase && (dateObject.pick <= minLimitObject.pick || dateObject.pick >= maxLimitObject.pick)) {
            if (isFlippedBase && !hasEnabledWeekdays && (!hasEnabledAfterTarget && interval > 0 || !hasEnabledBeforeTarget && interval < 0)) {
                interval *= -1;
            }
            while (calendar.disabled(dateObject)) {
                if (Math.abs(interval) > 1 && (dateObject.month < originalDateObject.month || dateObject.month > originalDateObject.month)) {
                    dateObject = originalDateObject;
                    interval = interval > 0 ? 1 : -1;
                }
                if (dateObject.pick <= minLimitObject.pick) {
                    reachedMin = true;
                    interval = 1;
                    dateObject = calendar.create([ minLimitObject.year, minLimitObject.month, minLimitObject.date + (dateObject.pick === minLimitObject.pick ? 0 : -1) ]);
                } else if (dateObject.pick >= maxLimitObject.pick) {
                    reachedMax = true;
                    interval = -1;
                    dateObject = calendar.create([ maxLimitObject.year, maxLimitObject.month, maxLimitObject.date + (dateObject.pick === maxLimitObject.pick ? 0 : 1) ]);
                }
                if (reachedMin && reachedMax) {
                    break;
                }
                dateObject = calendar.create([ dateObject.year, dateObject.month, dateObject.date + interval ]);
            }
        }
        return dateObject;
    };
    DatePicker.prototype.disabled = function(dateToVerify) {
        var calendar = this, isDisabledMatch = calendar.item.disable.filter(function(dateToDisable) {
            if (_.isInteger(dateToDisable)) {
                return dateToVerify.day === (calendar.settings.firstDay ? dateToDisable : dateToDisable - 1) % 7;
            }
            if ($.isArray(dateToDisable) || _.isDate(dateToDisable)) {
                return dateToVerify.pick === calendar.create(dateToDisable).pick;
            }
            if ($.isPlainObject(dateToDisable)) {
                return calendar.withinRange(dateToDisable, dateToVerify);
            }
        });
        isDisabledMatch = isDisabledMatch.length && !isDisabledMatch.filter(function(dateToDisable) {
            return $.isArray(dateToDisable) && dateToDisable[3] == "inverted" || $.isPlainObject(dateToDisable) && dateToDisable.inverted;
        }).length;
        return calendar.item.enable === -1 ? !isDisabledMatch : isDisabledMatch || dateToVerify.pick < calendar.item.min.pick || dateToVerify.pick > calendar.item.max.pick;
    };
    DatePicker.prototype.parse = function(type, value, options) {
        var calendar = this, parsingObject = {};
        if (!value || typeof value != "string") {
            return value;
        }
        if (!(options && options.format)) {
            options = options || {};
            options.format = calendar.settings.format;
        }
        calendar.formats.toArray(options.format).map(function(label) {
            var formattingLabel = calendar.formats[label], formatLength = formattingLabel ? _.trigger(formattingLabel, calendar, [ value, parsingObject ]) : label.replace(/^!/, "").length;
            if (formattingLabel) {
                parsingObject[label] = value.substr(0, formatLength);
            }
            value = value.substr(formatLength);
        });
        return [ parsingObject.yyyy || parsingObject.yy, +(parsingObject.mm || parsingObject.m) - 1, parsingObject.dd || parsingObject.d ];
    };
    DatePicker.prototype.formats = function() {
        function getWordLengthFromCollection(string, collection, dateObject) {
            var word = string.match(/[^\x00-\x7F]+|\w+/)[0];
            if (!dateObject.mm && !dateObject.m) {
                dateObject.m = collection.indexOf(word) + 1;
            }
            return word.length;
        }
        function getFirstWordLength(string) {
            return string.match(/\w+/)[0].length;
        }
        return {
            d: function(string, dateObject) {
                return string ? _.digits(string) : dateObject.date;
            },
            dd: function(string, dateObject) {
                return string ? 2 : _.lead(dateObject.date);
            },
            ddd: function(string, dateObject) {
                return string ? getFirstWordLength(string) : this.settings.weekdaysShort[dateObject.day];
            },
            dddd: function(string, dateObject) {
                return string ? getFirstWordLength(string) : this.settings.weekdaysFull[dateObject.day];
            },
            m: function(string, dateObject) {
                return string ? _.digits(string) : dateObject.month + 1;
            },
            mm: function(string, dateObject) {
                return string ? 2 : _.lead(dateObject.month + 1);
            },
            mmm: function(string, dateObject) {
                var collection = this.settings.monthsShort;
                return string ? getWordLengthFromCollection(string, collection, dateObject) : collection[dateObject.month];
            },
            mmmm: function(string, dateObject) {
                var collection = this.settings.monthsFull;
                return string ? getWordLengthFromCollection(string, collection, dateObject) : collection[dateObject.month];
            },
            yy: function(string, dateObject) {
                return string ? 2 : ("" + dateObject.year).slice(2);
            },
            yyyy: function(string, dateObject) {
                return string ? 4 : dateObject.year;
            },
            toArray: function(formatString) {
                return formatString.split(/(d{1,4}|m{1,4}|y{4}|yy|!.)/g);
            },
            toString: function(formatString, itemObject) {
                var calendar = this;
                return calendar.formats.toArray(formatString).map(function(label) {
                    return _.trigger(calendar.formats[label], calendar, [ 0, itemObject ]) || label.replace(/^!/, "");
                }).join("");
            }
        };
    }();
    DatePicker.prototype.isDateExact = function(one, two) {
        var calendar = this;
        if (_.isInteger(one) && _.isInteger(two) || typeof one == "boolean" && typeof two == "boolean") {
            return one === two;
        }
        if ((_.isDate(one) || $.isArray(one)) && (_.isDate(two) || $.isArray(two))) {
            return calendar.create(one).pick === calendar.create(two).pick;
        }
        if ($.isPlainObject(one) && $.isPlainObject(two)) {
            return calendar.isDateExact(one.from, two.from) && calendar.isDateExact(one.to, two.to);
        }
        return false;
    };
    DatePicker.prototype.isDateOverlap = function(one, two) {
        var calendar = this, firstDay = calendar.settings.firstDay ? 1 : 0;
        if (_.isInteger(one) && (_.isDate(two) || $.isArray(two))) {
            one = one % 7 + firstDay;
            return one === calendar.create(two).day + 1;
        }
        if (_.isInteger(two) && (_.isDate(one) || $.isArray(one))) {
            two = two % 7 + firstDay;
            return two === calendar.create(one).day + 1;
        }
        if ($.isPlainObject(one) && $.isPlainObject(two)) {
            return calendar.overlapRanges(one, two);
        }
        return false;
    };
    DatePicker.prototype.flipEnable = function(val) {
        var itemObject = this.item;
        itemObject.enable = val || (itemObject.enable == -1 ? 1 : -1);
    };
    DatePicker.prototype.deactivate = function(type, datesToDisable) {
        var calendar = this, disabledItems = calendar.item.disable.slice(0);
        if (datesToDisable == "flip") {
            calendar.flipEnable();
        } else if (datesToDisable === false) {
            calendar.flipEnable(1);
            disabledItems = [];
        } else if (datesToDisable === true) {
            calendar.flipEnable(-1);
            disabledItems = [];
        } else {
            datesToDisable.map(function(unitToDisable) {
                var matchFound;
                for (var index = 0; index < disabledItems.length; index += 1) {
                    if (calendar.isDateExact(unitToDisable, disabledItems[index])) {
                        matchFound = true;
                        break;
                    }
                }
                if (!matchFound) {
                    if (_.isInteger(unitToDisable) || _.isDate(unitToDisable) || $.isArray(unitToDisable) || $.isPlainObject(unitToDisable) && unitToDisable.from && unitToDisable.to) {
                        disabledItems.push(unitToDisable);
                    }
                }
            });
        }
        return disabledItems;
    };
    DatePicker.prototype.activate = function(type, datesToEnable) {
        var calendar = this, disabledItems = calendar.item.disable, disabledItemsCount = disabledItems.length;
        if (datesToEnable == "flip") {
            calendar.flipEnable();
        } else if (datesToEnable === true) {
            calendar.flipEnable(1);
            disabledItems = [];
        } else if (datesToEnable === false) {
            calendar.flipEnable(-1);
            disabledItems = [];
        } else {
            datesToEnable.map(function(unitToEnable) {
                var matchFound, disabledUnit, index, isExactRange;
                for (index = 0; index < disabledItemsCount; index += 1) {
                    disabledUnit = disabledItems[index];
                    if (calendar.isDateExact(disabledUnit, unitToEnable)) {
                        matchFound = disabledItems[index] = null;
                        isExactRange = true;
                        break;
                    } else if (calendar.isDateOverlap(disabledUnit, unitToEnable)) {
                        if ($.isPlainObject(unitToEnable)) {
                            unitToEnable.inverted = true;
                            matchFound = unitToEnable;
                        } else if ($.isArray(unitToEnable)) {
                            matchFound = unitToEnable;
                            if (!matchFound[3]) matchFound.push("inverted");
                        } else if (_.isDate(unitToEnable)) {
                            matchFound = [ unitToEnable.getFullYear(), unitToEnable.getMonth(), unitToEnable.getDate(), "inverted" ];
                        }
                        break;
                    }
                }
                if (matchFound) for (index = 0; index < disabledItemsCount; index += 1) {
                    if (calendar.isDateExact(disabledItems[index], unitToEnable)) {
                        disabledItems[index] = null;
                        break;
                    }
                }
                if (isExactRange) for (index = 0; index < disabledItemsCount; index += 1) {
                    if (calendar.isDateOverlap(disabledItems[index], unitToEnable)) {
                        disabledItems[index] = null;
                        break;
                    }
                }
                if (matchFound) {
                    disabledItems.push(matchFound);
                }
            });
        }
        return disabledItems.filter(function(val) {
            return val != null;
        });
    };
    DatePicker.prototype.nodes = function(isOpen) {
        var calendar = this, settings = calendar.settings, calendarItem = calendar.item, nowObject = calendarItem.now, selectedObject = calendarItem.select, highlightedObject = calendarItem.highlight, viewsetObject = calendarItem.view, disabledCollection = calendarItem.disable, minLimitObject = calendarItem.min, maxLimitObject = calendarItem.max, tableHead = function(collection, fullCollection) {
            if (settings.firstDay) {
                collection.push(collection.shift());
                fullCollection.push(fullCollection.shift());
            }
            return _.node("thead", _.node("tr", _.group({
                min: 0,
                max: DAYS_IN_WEEK - 1,
                i: 1,
                node: "th",
                item: function(counter) {
                    return [ collection[counter], settings.klass.weekdays, 'scope=col title="' + fullCollection[counter] + '"' ];
                }
            })));
        }((settings.showWeekdaysFull ? settings.weekdaysFull : settings.weekdaysShort).slice(0), settings.weekdaysFull.slice(0)), createMonthNav = function(next) {
            return _.node("div", " ", settings.klass["nav" + (next ? "Next" : "Prev")] + (next && viewsetObject.year >= maxLimitObject.year && viewsetObject.month >= maxLimitObject.month || !next && viewsetObject.year <= minLimitObject.year && viewsetObject.month <= minLimitObject.month ? " " + settings.klass.navDisabled : ""), "data-nav=" + (next || -1) + " " + _.ariaAttr({
                role: "button",
                controls: calendar.$node[0].id + "_table"
            }) + " " + 'title="' + (next ? settings.labelMonthNext : settings.labelMonthPrev) + '"');
        }, createMonthLabel = function() {
            var monthsCollection = settings.showMonthsShort ? settings.monthsShort : settings.monthsFull;
            if (settings.selectMonths) {
                return _.node("select", _.group({
                    min: 0,
                    max: 11,
                    i: 1,
                    node: "option",
                    item: function(loopedMonth) {
                        return [ monthsCollection[loopedMonth], 0, "value=" + loopedMonth + (viewsetObject.month == loopedMonth ? " selected" : "") + (viewsetObject.year == minLimitObject.year && loopedMonth < minLimitObject.month || viewsetObject.year == maxLimitObject.year && loopedMonth > maxLimitObject.month ? " disabled" : "") ];
                    }
                }), settings.klass.selectMonth, (isOpen ? "" : "disabled") + " " + _.ariaAttr({
                    controls: calendar.$node[0].id + "_table"
                }) + " " + 'title="' + settings.labelMonthSelect + '"');
            }
            return _.node("div", monthsCollection[viewsetObject.month], settings.klass.month);
        }, createYearLabel = function() {
            var focusedYear = viewsetObject.year, numberYears = settings.selectYears === true ? 5 : ~~(settings.selectYears / 2);
            if (numberYears) {
                var minYear = minLimitObject.year, maxYear = maxLimitObject.year, lowestYear = focusedYear - numberYears, highestYear = focusedYear + numberYears;
                if (minYear > lowestYear) {
                    highestYear += minYear - lowestYear;
                    lowestYear = minYear;
                }
                if (maxYear < highestYear) {
                    var availableYears = lowestYear - minYear, neededYears = highestYear - maxYear;
                    lowestYear -= availableYears > neededYears ? neededYears : availableYears;
                    highestYear = maxYear;
                }
                return _.node("select", _.group({
                    min: lowestYear,
                    max: highestYear,
                    i: 1,
                    node: "option",
                    item: function(loopedYear) {
                        return [ loopedYear, 0, "value=" + loopedYear + (focusedYear == loopedYear ? " selected" : "") ];
                    }
                }), settings.klass.selectYear, (isOpen ? "" : "disabled") + " " + _.ariaAttr({
                    controls: calendar.$node[0].id + "_table"
                }) + " " + 'title="' + settings.labelYearSelect + '"');
            }
            return _.node("div", focusedYear, settings.klass.year);
        };
        return _.node("div", (settings.selectYears ? createYearLabel() + createMonthLabel() : createMonthLabel() + createYearLabel()) + createMonthNav() + createMonthNav(1), settings.klass.header) + _.node("table", tableHead + _.node("tbody", _.group({
            min: 0,
            max: WEEKS_IN_CALENDAR - 1,
            i: 1,
            node: "tr",
            item: function(rowCounter) {
                var shiftDateBy = settings.firstDay && calendar.create([ viewsetObject.year, viewsetObject.month, 1 ]).day === 0 ? -7 : 0;
                return [ _.group({
                    min: DAYS_IN_WEEK * rowCounter - viewsetObject.day + shiftDateBy + 1,
                    max: function() {
                        return this.min + DAYS_IN_WEEK - 1;
                    },
                    i: 1,
                    node: "td",
                    item: function(targetDate) {
                        targetDate = calendar.create([ viewsetObject.year, viewsetObject.month, targetDate + (settings.firstDay ? 1 : 0) ]);
                        var isSelected = selectedObject && selectedObject.pick == targetDate.pick, isHighlighted = highlightedObject && highlightedObject.pick == targetDate.pick, isDisabled = disabledCollection && calendar.disabled(targetDate) || targetDate.pick < minLimitObject.pick || targetDate.pick > maxLimitObject.pick, formattedDate = _.trigger(calendar.formats.toString, calendar, [ settings.format, targetDate ]);
                        return [ _.node("div", targetDate.date, function(klasses) {
                            klasses.push(viewsetObject.month == targetDate.month ? settings.klass.infocus : settings.klass.outfocus);
                            if (nowObject.pick == targetDate.pick) {
                                klasses.push(settings.klass.now);
                            }
                            if (isSelected) {
                                klasses.push(settings.klass.selected);
                            }
                            if (isHighlighted) {
                                klasses.push(settings.klass.highlighted);
                            }
                            if (isDisabled) {
                                klasses.push(settings.klass.disabled);
                            }
                            return klasses.join(" ");
                        }([ settings.klass.day ]), "data-pick=" + targetDate.pick + " " + _.ariaAttr({
                            role: "gridcell",
                            label: formattedDate,
                            selected: isSelected && calendar.$node.val() === formattedDate ? true : null,
                            activedescendant: isHighlighted ? true : null,
                            disabled: isDisabled ? true : null
                        })), "", _.ariaAttr({
                            role: "presentation"
                        }) ];
                    }
                }) ];
            }
        })), settings.klass.table, 'id="' + calendar.$node[0].id + "_table" + '" ' + _.ariaAttr({
            role: "grid",
            controls: calendar.$node[0].id,
            readonly: true
        })) + _.node("div", _.node("button", settings.today, settings.klass.buttonToday, "type=button data-pick=" + nowObject.pick + (isOpen && !calendar.disabled(nowObject) ? "" : " disabled") + " " + _.ariaAttr({
            controls: calendar.$node[0].id
        })) + _.node("button", settings.clear, settings.klass.buttonClear, "type=button data-clear=1" + (isOpen ? "" : " disabled") + " " + _.ariaAttr({
            controls: calendar.$node[0].id
        })) + _.node("button", settings.close, settings.klass.buttonClose, "type=button data-close=true " + (isOpen ? "" : " disabled") + " " + _.ariaAttr({
            controls: calendar.$node[0].id
        })), settings.klass.footer);
    };
    DatePicker.defaults = function(prefix) {
        return {
            labelMonthNext: "Next month",
            labelMonthPrev: "Previous month",
            labelMonthSelect: "Select a month",
            labelYearSelect: "Select a year",
            monthsFull: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ],
            monthsShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ],
            weekdaysFull: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ],
            weekdaysShort: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ],
            today: "Today",
            clear: "Clear",
            close: "Close",
            closeOnSelect: true,
            closeOnClear: true,
            format: "d mmmm, yyyy",
            klass: {
                table: prefix + "table",
                header: prefix + "header",
                navPrev: prefix + "nav--prev",
                navNext: prefix + "nav--next",
                navDisabled: prefix + "nav--disabled",
                month: prefix + "month",
                year: prefix + "year",
                selectMonth: prefix + "select--month",
                selectYear: prefix + "select--year",
                weekdays: prefix + "weekday",
                day: prefix + "day",
                disabled: prefix + "day--disabled",
                selected: prefix + "day--selected",
                highlighted: prefix + "day--highlighted",
                now: prefix + "day--today",
                infocus: prefix + "day--infocus",
                outfocus: prefix + "day--outfocus",
                footer: prefix + "footer",
                buttonClear: prefix + "button--clear",
                buttonToday: prefix + "button--today",
                buttonClose: prefix + "button--close"
            }
        };
    }(Picker.klasses().picker + "__");
    Picker.extend("pickadate", DatePicker);
});

(function(factory) {
    if (typeof define == "function" && define.amd) define([ "picker", "jquery" ], factory); else if (typeof exports == "object") module.exports = factory(require("./picker.js"), require("jquery")); else factory(Picker, jQuery);
})(function(Picker, $) {
    var HOURS_IN_DAY = 24, MINUTES_IN_HOUR = 60, HOURS_TO_NOON = 12, MINUTES_IN_DAY = HOURS_IN_DAY * MINUTES_IN_HOUR, _ = Picker._;
    function TimePicker(picker, settings) {
        var clock = this, elementValue = picker.$node[0].value, elementDataValue = picker.$node.data("value"), valueString = elementDataValue || elementValue, formatString = elementDataValue ? settings.formatSubmit : settings.format;
        clock.settings = settings;
        clock.$node = picker.$node;
        clock.queue = {
            interval: "i",
            min: "measure create",
            max: "measure create",
            now: "now create",
            select: "parse create validate",
            highlight: "parse create validate",
            view: "parse create validate",
            disable: "deactivate",
            enable: "activate"
        };
        clock.item = {};
        clock.item.clear = null;
        clock.item.interval = settings.interval || 30;
        clock.item.disable = (settings.disable || []).slice(0);
        clock.item.enable = -function(collectionDisabled) {
            return collectionDisabled[0] === true ? collectionDisabled.shift() : -1;
        }(clock.item.disable);
        clock.set("min", settings.min).set("max", settings.max).set("now");
        if (valueString) {
            clock.set("select", valueString, {
                format: formatString
            });
        } else {
            clock.set("select", null).set("highlight", clock.item.now);
        }
        clock.key = {
            40: 1,
            38: -1,
            39: 1,
            37: -1,
            go: function(timeChange) {
                clock.set("highlight", clock.item.highlight.pick + timeChange * clock.item.interval, {
                    interval: timeChange * clock.item.interval
                });
                this.render();
            }
        };
        picker.on("render", function() {
            var $pickerHolder = picker.$root.children(), $viewset = $pickerHolder.find("." + settings.klass.viewset), vendors = function(prop) {
                return [ "webkit", "moz", "ms", "o", "" ].map(function(vendor) {
                    return (vendor ? "-" + vendor + "-" : "") + prop;
                });
            }, animations = function($el, state) {
                vendors("transform").map(function(prop) {
                    $el.css(prop, state);
                });
                vendors("transition").map(function(prop) {
                    $el.css(prop, state);
                });
            };
            if ($viewset.length) {
                animations($pickerHolder, "none");
                $pickerHolder[0].scrollTop = ~~$viewset.position().top - $viewset[0].clientHeight * 2;
                animations($pickerHolder, "");
            }
        }, 1).on("open", function() {
            picker.$root.find("button").attr("disabled", false);
        }, 1).on("close", function() {
            picker.$root.find("button").attr("disabled", true);
        }, 1);
    }
    TimePicker.prototype.set = function(type, value, options) {
        var clock = this, clockItem = clock.item;
        if (value === null) {
            if (type == "clear") type = "select";
            clockItem[type] = value;
            return clock;
        }
        clockItem[type == "enable" ? "disable" : type == "flip" ? "enable" : type] = clock.queue[type].split(" ").map(function(method) {
            value = clock[method](type, value, options);
            return value;
        }).pop();
        if (type == "select") {
            clock.set("highlight", clockItem.select, options);
        } else if (type == "highlight") {
            clock.set("view", clockItem.highlight, options);
        } else if (type == "interval") {
            clock.set("min", clockItem.min, options).set("max", clockItem.max, options);
        } else if (type.match(/^(flip|min|max|disable|enable)$/)) {
            if (clockItem.select && clock.disabled(clockItem.select)) {
                clock.set("select", value, options);
            }
            if (clockItem.highlight && clock.disabled(clockItem.highlight)) {
                clock.set("highlight", value, options);
            }
            if (type == "min") {
                clock.set("max", clockItem.max, options);
            }
        }
        return clock;
    };
    TimePicker.prototype.get = function(type) {
        return this.item[type];
    };
    TimePicker.prototype.create = function(type, value, options) {
        var clock = this;
        value = value === undefined ? type : value;
        if (_.isDate(value)) {
            value = [ value.getHours(), value.getMinutes() ];
        }
        if ($.isPlainObject(value) && _.isInteger(value.pick)) {
            value = value.pick;
        } else if ($.isArray(value)) {
            value = +value[0] * MINUTES_IN_HOUR + +value[1];
        } else if (!_.isInteger(value)) {
            value = clock.now(type, value, options);
        }
        if (type == "max" && value < clock.item.min.pick) {
            value += MINUTES_IN_DAY;
        }
        if (type != "min" && type != "max" && (value - clock.item.min.pick) % clock.item.interval !== 0) {
            value += clock.item.interval;
        }
        value = clock.normalize(type, value, options);
        return {
            hour: ~~(HOURS_IN_DAY + value / MINUTES_IN_HOUR) % HOURS_IN_DAY,
            mins: (MINUTES_IN_HOUR + value % MINUTES_IN_HOUR) % MINUTES_IN_HOUR,
            time: (MINUTES_IN_DAY + value) % MINUTES_IN_DAY,
            pick: value % MINUTES_IN_DAY
        };
    };
    TimePicker.prototype.createRange = function(from, to) {
        var clock = this, createTime = function(time) {
            if (time === true || $.isArray(time) || _.isDate(time)) {
                return clock.create(time);
            }
            return time;
        };
        if (!_.isInteger(from)) {
            from = createTime(from);
        }
        if (!_.isInteger(to)) {
            to = createTime(to);
        }
        if (_.isInteger(from) && $.isPlainObject(to)) {
            from = [ to.hour, to.mins + from * clock.settings.interval ];
        } else if (_.isInteger(to) && $.isPlainObject(from)) {
            to = [ from.hour, from.mins + to * clock.settings.interval ];
        }
        return {
            from: createTime(from),
            to: createTime(to)
        };
    };
    TimePicker.prototype.withinRange = function(range, timeUnit) {
        range = this.createRange(range.from, range.to);
        return timeUnit.pick >= range.from.pick && timeUnit.pick <= range.to.pick;
    };
    TimePicker.prototype.overlapRanges = function(one, two) {
        var clock = this;
        one = clock.createRange(one.from, one.to);
        two = clock.createRange(two.from, two.to);
        return clock.withinRange(one, two.from) || clock.withinRange(one, two.to) || clock.withinRange(two, one.from) || clock.withinRange(two, one.to);
    };
    TimePicker.prototype.now = function(type, value) {
        var interval = this.item.interval, date = new Date(), nowMinutes = date.getHours() * MINUTES_IN_HOUR + date.getMinutes(), isValueInteger = _.isInteger(value), isBelowInterval;
        nowMinutes -= nowMinutes % interval;
        isBelowInterval = value < 0 && interval * value + nowMinutes <= -interval;
        nowMinutes += type == "min" && isBelowInterval ? 0 : interval;
        if (isValueInteger) {
            nowMinutes += interval * (isBelowInterval && type != "max" ? value + 1 : value);
        }
        return nowMinutes;
    };
    TimePicker.prototype.normalize = function(type, value) {
        var interval = this.item.interval, minTime = this.item.min && this.item.min.pick || 0;
        value -= type == "min" ? 0 : (value - minTime) % interval;
        return value;
    };
    TimePicker.prototype.measure = function(type, value, options) {
        var clock = this;
        if (!value) {
            value = type == "min" ? [ 0, 0 ] : [ HOURS_IN_DAY - 1, MINUTES_IN_HOUR - 1 ];
        }
        if (typeof value == "string") {
            value = clock.parse(type, value);
        } else if (value === true || _.isInteger(value)) {
            value = clock.now(type, value, options);
        } else if ($.isPlainObject(value) && _.isInteger(value.pick)) {
            value = clock.normalize(type, value.pick, options);
        }
        return value;
    };
    TimePicker.prototype.validate = function(type, timeObject, options) {
        var clock = this, interval = options && options.interval ? options.interval : clock.item.interval;
        if (clock.disabled(timeObject)) {
            timeObject = clock.shift(timeObject, interval);
        }
        timeObject = clock.scope(timeObject);
        if (clock.disabled(timeObject)) {
            timeObject = clock.shift(timeObject, interval * -1);
        }
        return timeObject;
    };
    TimePicker.prototype.disabled = function(timeToVerify) {
        var clock = this, isDisabledMatch = clock.item.disable.filter(function(timeToDisable) {
            if (_.isInteger(timeToDisable)) {
                return timeToVerify.hour == timeToDisable;
            }
            if ($.isArray(timeToDisable) || _.isDate(timeToDisable)) {
                return timeToVerify.pick == clock.create(timeToDisable).pick;
            }
            if ($.isPlainObject(timeToDisable)) {
                return clock.withinRange(timeToDisable, timeToVerify);
            }
        });
        isDisabledMatch = isDisabledMatch.length && !isDisabledMatch.filter(function(timeToDisable) {
            return $.isArray(timeToDisable) && timeToDisable[2] == "inverted" || $.isPlainObject(timeToDisable) && timeToDisable.inverted;
        }).length;
        return clock.item.enable === -1 ? !isDisabledMatch : isDisabledMatch || timeToVerify.pick < clock.item.min.pick || timeToVerify.pick > clock.item.max.pick;
    };
    TimePicker.prototype.shift = function(timeObject, interval) {
        var clock = this, minLimit = clock.item.min.pick, maxLimit = clock.item.max.pick;
        interval = interval || clock.item.interval;
        while (clock.disabled(timeObject)) {
            timeObject = clock.create(timeObject.pick += interval);
            if (timeObject.pick <= minLimit || timeObject.pick >= maxLimit) {
                break;
            }
        }
        return timeObject;
    };
    TimePicker.prototype.scope = function(timeObject) {
        var minLimit = this.item.min.pick, maxLimit = this.item.max.pick;
        return this.create(timeObject.pick > maxLimit ? maxLimit : timeObject.pick < minLimit ? minLimit : timeObject);
    };
    TimePicker.prototype.parse = function(type, value, options) {
        var hour, minutes, isPM, item, parseValue, clock = this, parsingObject = {};
        if (!value || typeof value != "string") {
            return value;
        }
        if (!(options && options.format)) {
            options = options || {};
            options.format = clock.settings.format;
        }
        clock.formats.toArray(options.format).map(function(label) {
            var substring, formattingLabel = clock.formats[label], formatLength = formattingLabel ? _.trigger(formattingLabel, clock, [ value, parsingObject ]) : label.replace(/^!/, "").length;
            if (formattingLabel) {
                substring = value.substr(0, formatLength);
                parsingObject[label] = substring.match(/^\d+$/) ? +substring : substring;
            }
            value = value.substr(formatLength);
        });
        for (item in parsingObject) {
            parseValue = parsingObject[item];
            if (_.isInteger(parseValue)) {
                if (item.match(/^(h|hh)$/i)) {
                    hour = parseValue;
                    if (item == "h" || item == "hh") {
                        hour %= 12;
                    }
                } else if (item == "i") {
                    minutes = parseValue;
                }
            } else if (item.match(/^a$/i) && parseValue.match(/^p/i) && ("h" in parsingObject || "hh" in parsingObject)) {
                isPM = true;
            }
        }
        return (isPM ? hour + 12 : hour) * MINUTES_IN_HOUR + minutes;
    };
    TimePicker.prototype.formats = {
        h: function(string, timeObject) {
            return string ? _.digits(string) : timeObject.hour % HOURS_TO_NOON || HOURS_TO_NOON;
        },
        hh: function(string, timeObject) {
            return string ? 2 : _.lead(timeObject.hour % HOURS_TO_NOON || HOURS_TO_NOON);
        },
        H: function(string, timeObject) {
            return string ? _.digits(string) : "" + timeObject.hour % 24;
        },
        HH: function(string, timeObject) {
            return string ? _.digits(string) : _.lead(timeObject.hour % 24);
        },
        i: function(string, timeObject) {
            return string ? 2 : _.lead(timeObject.mins);
        },
        a: function(string, timeObject) {
            return string ? 4 : MINUTES_IN_DAY / 2 > timeObject.time % MINUTES_IN_DAY ? "a.m." : "p.m.";
        },
        A: function(string, timeObject) {
            return string ? 2 : MINUTES_IN_DAY / 2 > timeObject.time % MINUTES_IN_DAY ? "AM" : "PM";
        },
        toArray: function(formatString) {
            return formatString.split(/(h{1,2}|H{1,2}|i|a|A|!.)/g);
        },
        toString: function(formatString, itemObject) {
            var clock = this;
            return clock.formats.toArray(formatString).map(function(label) {
                return _.trigger(clock.formats[label], clock, [ 0, itemObject ]) || label.replace(/^!/, "");
            }).join("");
        }
    };
    TimePicker.prototype.isTimeExact = function(one, two) {
        var clock = this;
        if (_.isInteger(one) && _.isInteger(two) || typeof one == "boolean" && typeof two == "boolean") {
            return one === two;
        }
        if ((_.isDate(one) || $.isArray(one)) && (_.isDate(two) || $.isArray(two))) {
            return clock.create(one).pick === clock.create(two).pick;
        }
        if ($.isPlainObject(one) && $.isPlainObject(two)) {
            return clock.isTimeExact(one.from, two.from) && clock.isTimeExact(one.to, two.to);
        }
        return false;
    };
    TimePicker.prototype.isTimeOverlap = function(one, two) {
        var clock = this;
        if (_.isInteger(one) && (_.isDate(two) || $.isArray(two))) {
            return one === clock.create(two).hour;
        }
        if (_.isInteger(two) && (_.isDate(one) || $.isArray(one))) {
            return two === clock.create(one).hour;
        }
        if ($.isPlainObject(one) && $.isPlainObject(two)) {
            return clock.overlapRanges(one, two);
        }
        return false;
    };
    TimePicker.prototype.flipEnable = function(val) {
        var itemObject = this.item;
        itemObject.enable = val || (itemObject.enable == -1 ? 1 : -1);
    };
    TimePicker.prototype.deactivate = function(type, timesToDisable) {
        var clock = this, disabledItems = clock.item.disable.slice(0);
        if (timesToDisable == "flip") {
            clock.flipEnable();
        } else if (timesToDisable === false) {
            clock.flipEnable(1);
            disabledItems = [];
        } else if (timesToDisable === true) {
            clock.flipEnable(-1);
            disabledItems = [];
        } else {
            timesToDisable.map(function(unitToDisable) {
                var matchFound;
                for (var index = 0; index < disabledItems.length; index += 1) {
                    if (clock.isTimeExact(unitToDisable, disabledItems[index])) {
                        matchFound = true;
                        break;
                    }
                }
                if (!matchFound) {
                    if (_.isInteger(unitToDisable) || _.isDate(unitToDisable) || $.isArray(unitToDisable) || $.isPlainObject(unitToDisable) && unitToDisable.from && unitToDisable.to) {
                        disabledItems.push(unitToDisable);
                    }
                }
            });
        }
        return disabledItems;
    };
    TimePicker.prototype.activate = function(type, timesToEnable) {
        var clock = this, disabledItems = clock.item.disable, disabledItemsCount = disabledItems.length;
        if (timesToEnable == "flip") {
            clock.flipEnable();
        } else if (timesToEnable === true) {
            clock.flipEnable(1);
            disabledItems = [];
        } else if (timesToEnable === false) {
            clock.flipEnable(-1);
            disabledItems = [];
        } else {
            timesToEnable.map(function(unitToEnable) {
                var matchFound, disabledUnit, index, isRangeMatched;
                for (index = 0; index < disabledItemsCount; index += 1) {
                    disabledUnit = disabledItems[index];
                    if (clock.isTimeExact(disabledUnit, unitToEnable)) {
                        matchFound = disabledItems[index] = null;
                        isRangeMatched = true;
                        break;
                    } else if (clock.isTimeOverlap(disabledUnit, unitToEnable)) {
                        if ($.isPlainObject(unitToEnable)) {
                            unitToEnable.inverted = true;
                            matchFound = unitToEnable;
                        } else if ($.isArray(unitToEnable)) {
                            matchFound = unitToEnable;
                            if (!matchFound[2]) matchFound.push("inverted");
                        } else if (_.isDate(unitToEnable)) {
                            matchFound = [ unitToEnable.getFullYear(), unitToEnable.getMonth(), unitToEnable.getDate(), "inverted" ];
                        }
                        break;
                    }
                }
                if (matchFound) for (index = 0; index < disabledItemsCount; index += 1) {
                    if (clock.isTimeExact(disabledItems[index], unitToEnable)) {
                        disabledItems[index] = null;
                        break;
                    }
                }
                if (isRangeMatched) for (index = 0; index < disabledItemsCount; index += 1) {
                    if (clock.isTimeOverlap(disabledItems[index], unitToEnable)) {
                        disabledItems[index] = null;
                        break;
                    }
                }
                if (matchFound) {
                    disabledItems.push(matchFound);
                }
            });
        }
        return disabledItems.filter(function(val) {
            return val != null;
        });
    };
    TimePicker.prototype.i = function(type, value) {
        return _.isInteger(value) && value > 0 ? value : this.item.interval;
    };
    TimePicker.prototype.nodes = function(isOpen) {
        var clock = this, settings = clock.settings, selectedObject = clock.item.select, highlightedObject = clock.item.highlight, viewsetObject = clock.item.view, disabledCollection = clock.item.disable;
        return _.node("ul", _.group({
            min: clock.item.min.pick,
            max: clock.item.max.pick,
            i: clock.item.interval,
            node: "li",
            item: function(loopedTime) {
                loopedTime = clock.create(loopedTime);
                var timeMinutes = loopedTime.pick, isSelected = selectedObject && selectedObject.pick == timeMinutes, isHighlighted = highlightedObject && highlightedObject.pick == timeMinutes, isDisabled = disabledCollection && clock.disabled(loopedTime), formattedTime = _.trigger(clock.formats.toString, clock, [ settings.format, loopedTime ]);
                return [ _.trigger(clock.formats.toString, clock, [ _.trigger(settings.formatLabel, clock, [ loopedTime ]) || settings.format, loopedTime ]), function(klasses) {
                    if (isSelected) {
                        klasses.push(settings.klass.selected);
                    }
                    if (isHighlighted) {
                        klasses.push(settings.klass.highlighted);
                    }
                    if (viewsetObject && viewsetObject.pick == timeMinutes) {
                        klasses.push(settings.klass.viewset);
                    }
                    if (isDisabled) {
                        klasses.push(settings.klass.disabled);
                    }
                    return klasses.join(" ");
                }([ settings.klass.listItem ]), "data-pick=" + loopedTime.pick + " " + _.ariaAttr({
                    role: "option",
                    label: formattedTime,
                    selected: isSelected && clock.$node.val() === formattedTime ? true : null,
                    activedescendant: isHighlighted ? true : null,
                    disabled: isDisabled ? true : null
                }) ];
            }
        }) + _.node("li", _.node("button", settings.clear, settings.klass.buttonClear, "type=button data-clear=1" + (isOpen ? "" : " disabled") + " " + _.ariaAttr({
            controls: clock.$node[0].id
        })), "", _.ariaAttr({
            role: "presentation"
        })), settings.klass.list, _.ariaAttr({
            role: "listbox",
            controls: clock.$node[0].id
        }));
    };
    TimePicker.defaults = function(prefix) {
        return {
            clear: "Clear",
            format: "h:i A",
            interval: 30,
            closeOnSelect: true,
            closeOnClear: true,
            klass: {
                picker: prefix + " " + prefix + "--time",
                holder: prefix + "__holder",
                list: prefix + "__list",
                listItem: prefix + "__list-item",
                disabled: prefix + "__list-item--disabled",
                selected: prefix + "__list-item--selected",
                highlighted: prefix + "__list-item--highlighted",
                viewset: prefix + "__list-item--viewset",
                now: prefix + "__list-item--now",
                buttonClear: prefix + "__button--clear"
            }
        };
    }(Picker.klasses().picker);
    Picker.extend("pickatime", TimePicker);
});

if (![].map) {
    Array.prototype.map = function(callback, self) {
        var array = this, len = array.length, newArray = new Array(len);
        for (var i = 0; i < len; i++) {
            if (i in array) {
                newArray[i] = callback.call(self, array[i], i, array);
            }
        }
        return newArray;
    };
}

if (![].filter) {
    Array.prototype.filter = function(callback) {
        if (this == null) throw new TypeError();
        var t = Object(this), len = t.length >>> 0;
        if (typeof callback != "function") throw new TypeError();
        var newArray = [], thisp = arguments[1];
        for (var i = 0; i < len; i++) {
            if (i in t) {
                var val = t[i];
                if (callback.call(thisp, val, i, t)) newArray.push(val);
            }
        }
        return newArray;
    };
}

if (![].indexOf) {
    Array.prototype.indexOf = function(searchElement) {
        if (this == null) throw new TypeError();
        var t = Object(this), len = t.length >>> 0;
        if (len === 0) return -1;
        var n = 0;
        if (arguments.length > 1) {
            n = Number(arguments[1]);
            if (n != n) {
                n = 0;
            } else if (n !== 0 && n != Infinity && n != -Infinity) {
                n = (n > 0 || -1) * Math.floor(Math.abs(n));
            }
        }
        if (n >= len) return -1;
        var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
        for (;k < len; k++) {
            if (k in t && t[k] === searchElement) return k;
        }
        return -1;
    };
}

var nativeSplit = String.prototype.split, compliantExecNpcg = /()??/.exec("")[1] === undefined;

String.prototype.split = function(separator, limit) {
    var str = this;
    if (Object.prototype.toString.call(separator) !== "[object RegExp]") {
        return nativeSplit.call(str, separator, limit);
    }
    var output = [], flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.extended ? "x" : "") + (separator.sticky ? "y" : ""), lastLastIndex = 0, separator2, match, lastIndex, lastLength;
    separator = new RegExp(separator.source, flags + "g");
    str += "";
    if (!compliantExecNpcg) {
        separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags);
    }
    limit = limit === undefined ? -1 >>> 0 : limit >>> 0;
    while (match = separator.exec(str)) {
        lastIndex = match.index + match[0].length;
        if (lastIndex > lastLastIndex) {
            output.push(str.slice(lastLastIndex, match.index));
            if (!compliantExecNpcg && match.length > 1) {
                match[0].replace(separator2, function() {
                    for (var i = 1; i < arguments.length - 2; i++) {
                        if (arguments[i] === undefined) {
                            match[i] = undefined;
                        }
                    }
                });
            }
            if (match.length > 1 && match.index < str.length) {
                Array.prototype.push.apply(output, match.slice(1));
            }
            lastLength = match[0].length;
            lastLastIndex = lastIndex;
            if (output.length >= limit) {
                break;
            }
        }
        if (separator.lastIndex === match.index) {
            separator.lastIndex++;
        }
    }
    if (lastLastIndex === str.length) {
        if (lastLength || !separator.test("")) {
            output.push("");
        }
    } else {
        output.push(str.slice(lastLastIndex));
    }
    return output.length > limit ? output.slice(0, limit) : output;
};

(function(factory) {
    "use strict";
    if (typeof define === "function" && define.amd) {
        define([ "jquery" ], factory);
    } else if (typeof exports === "object") {
        factory(require("jquery"));
    } else {
        factory(jQuery);
    }
})(function($) {
    "use strict";
    function int(x) {
        if (typeof x === "string") {
            return parseInt(x, 10);
        } else {
            return ~~x;
        }
    }
    var defaultSettings = {
        wheelSpeed: 1,
        wheelPropagation: false,
        minScrollbarLength: null,
        maxScrollbarLength: null,
        useBothWheelAxes: false,
        useKeyboard: true,
        suppressScrollX: false,
        suppressScrollY: false,
        scrollXMarginOffset: 0,
        scrollYMarginOffset: 0,
        includePadding: false
    };
    var incrementingId = 0;
    var eventClassFactory = function() {
        var id = incrementingId++;
        return function(eventName) {
            var className = ".perfect-scrollbar-" + id;
            if (typeof eventName === "undefined") {
                return className;
            } else {
                return eventName + className;
            }
        };
    };
    $.fn.perfectScrollbar = function(suppliedSettings, option) {
        return this.each(function() {
            var settings = $.extend(true, {}, defaultSettings);
            var $this = $(this);
            var isPluginAlive = function() {
                return !!$this;
            };
            if (typeof suppliedSettings === "object") {
                $.extend(true, settings, suppliedSettings);
            } else {
                option = suppliedSettings;
            }
            if (option === "update") {
                if ($this.data("perfect-scrollbar-update")) {
                    $this.data("perfect-scrollbar-update")();
                }
                return $this;
            } else if (option === "destroy") {
                if ($this.data("perfect-scrollbar-destroy")) {
                    $this.data("perfect-scrollbar-destroy")();
                }
                return $this;
            }
            if ($this.data("perfect-scrollbar")) {
                return $this.data("perfect-scrollbar");
            }
            $this.addClass("ps-container");
            var containerWidth;
            var containerHeight;
            var contentWidth;
            var contentHeight;
            var isRtl = $this.css("direction") === "rtl";
            var eventClass = eventClassFactory();
            var ownerDocument = this.ownerDocument || document;
            var $scrollbarXRail = $("<div class='ps-scrollbar-x-rail'>").appendTo($this);
            var $scrollbarX = $("<div class='ps-scrollbar-x'>").appendTo($scrollbarXRail);
            var scrollbarXActive;
            var scrollbarXWidth;
            var scrollbarXLeft;
            var scrollbarXBottom = int($scrollbarXRail.css("bottom"));
            var isScrollbarXUsingBottom = scrollbarXBottom === scrollbarXBottom;
            var scrollbarXTop = isScrollbarXUsingBottom ? null : int($scrollbarXRail.css("top"));
            var railBorderXWidth = int($scrollbarXRail.css("borderLeftWidth")) + int($scrollbarXRail.css("borderRightWidth"));
            var $scrollbarYRail = $("<div class='ps-scrollbar-y-rail'>").appendTo($this);
            var $scrollbarY = $("<div class='ps-scrollbar-y'>").appendTo($scrollbarYRail);
            var scrollbarYActive;
            var scrollbarYHeight;
            var scrollbarYTop;
            var scrollbarYRight = int($scrollbarYRail.css("right"));
            var isScrollbarYUsingRight = scrollbarYRight === scrollbarYRight;
            var scrollbarYLeft = isScrollbarYUsingRight ? null : int($scrollbarYRail.css("left"));
            var railBorderYWidth = int($scrollbarYRail.css("borderTopWidth")) + int($scrollbarYRail.css("borderBottomWidth"));
            function updateScrollTop(currentTop, deltaY) {
                var newTop = currentTop + deltaY;
                var maxTop = containerHeight - scrollbarYHeight;
                if (newTop < 0) {
                    scrollbarYTop = 0;
                } else if (newTop > maxTop) {
                    scrollbarYTop = maxTop;
                } else {
                    scrollbarYTop = newTop;
                }
                var scrollTop = int(scrollbarYTop * (contentHeight - containerHeight) / (containerHeight - scrollbarYHeight));
                $this.scrollTop(scrollTop);
            }
            function updateScrollLeft(currentLeft, deltaX) {
                var newLeft = currentLeft + deltaX;
                var maxLeft = containerWidth - scrollbarXWidth;
                if (newLeft < 0) {
                    scrollbarXLeft = 0;
                } else if (newLeft > maxLeft) {
                    scrollbarXLeft = maxLeft;
                } else {
                    scrollbarXLeft = newLeft;
                }
                var scrollLeft = int(scrollbarXLeft * (contentWidth - containerWidth) / (containerWidth - scrollbarXWidth));
                $this.scrollLeft(scrollLeft);
            }
            function getThumbSize(thumbSize) {
                if (settings.minScrollbarLength) {
                    thumbSize = Math.max(thumbSize, settings.minScrollbarLength);
                }
                if (settings.maxScrollbarLength) {
                    thumbSize = Math.min(thumbSize, settings.maxScrollbarLength);
                }
                return thumbSize;
            }
            function updateCss() {
                var xRailOffset = {
                    width: containerWidth
                };
                if (isRtl) {
                    xRailOffset.left = $this.scrollLeft() + containerWidth - contentWidth;
                } else {
                    xRailOffset.left = $this.scrollLeft();
                }
                if (isScrollbarXUsingBottom) {
                    xRailOffset.bottom = scrollbarXBottom - $this.scrollTop();
                } else {
                    xRailOffset.top = scrollbarXTop + $this.scrollTop();
                }
                $scrollbarXRail.css(xRailOffset);
                var railYOffset = {
                    top: $this.scrollTop(),
                    height: containerHeight
                };
                if (isScrollbarYUsingRight) {
                    if (isRtl) {
                        railYOffset.right = contentWidth - $this.scrollLeft() - scrollbarYRight - $scrollbarY.outerWidth();
                    } else {
                        railYOffset.right = scrollbarYRight - $this.scrollLeft();
                    }
                } else {
                    if (isRtl) {
                        railYOffset.left = $this.scrollLeft() + containerWidth * 2 - contentWidth - scrollbarYLeft - $scrollbarY.outerWidth();
                    } else {
                        railYOffset.left = scrollbarYLeft + $this.scrollLeft();
                    }
                }
                $scrollbarYRail.css(railYOffset);
                $scrollbarX.css({
                    left: scrollbarXLeft,
                    width: scrollbarXWidth - railBorderXWidth
                });
                $scrollbarY.css({
                    top: scrollbarYTop,
                    height: scrollbarYHeight - railBorderYWidth
                });
            }
            function updateGeometry() {
                $this.removeClass("ps-active-x");
                $this.removeClass("ps-active-y");
                containerWidth = settings.includePadding ? $this.innerWidth() : $this.width();
                containerHeight = settings.includePadding ? $this.innerHeight() : $this.height();
                contentWidth = $this.prop("scrollWidth");
                contentHeight = $this.prop("scrollHeight");
                if (!settings.suppressScrollX && containerWidth + settings.scrollXMarginOffset < contentWidth) {
                    scrollbarXActive = true;
                    scrollbarXWidth = getThumbSize(int(containerWidth * containerWidth / contentWidth));
                    scrollbarXLeft = int($this.scrollLeft() * (containerWidth - scrollbarXWidth) / (contentWidth - containerWidth));
                } else {
                    scrollbarXActive = false;
                    scrollbarXWidth = 0;
                    scrollbarXLeft = 0;
                    $this.scrollLeft(0);
                }
                if (!settings.suppressScrollY && containerHeight + settings.scrollYMarginOffset < contentHeight) {
                    scrollbarYActive = true;
                    scrollbarYHeight = getThumbSize(int(containerHeight * containerHeight / contentHeight));
                    scrollbarYTop = int($this.scrollTop() * (containerHeight - scrollbarYHeight) / (contentHeight - containerHeight));
                } else {
                    scrollbarYActive = false;
                    scrollbarYHeight = 0;
                    scrollbarYTop = 0;
                    $this.scrollTop(0);
                }
                if (scrollbarXLeft >= containerWidth - scrollbarXWidth) {
                    scrollbarXLeft = containerWidth - scrollbarXWidth;
                }
                if (scrollbarYTop >= containerHeight - scrollbarYHeight) {
                    scrollbarYTop = containerHeight - scrollbarYHeight;
                }
                updateCss();
                if (scrollbarXActive) {
                    $this.addClass("ps-active-x");
                }
                if (scrollbarYActive) {
                    $this.addClass("ps-active-y");
                }
            }
            function bindMouseScrollXHandler() {
                var currentLeft;
                var currentPageX;
                var inScrolling = false;
                $scrollbarX.bind(eventClass("mousedown"), function(e) {
                    currentPageX = e.pageX;
                    currentLeft = $scrollbarX.position().left;
                    $scrollbarXRail.addClass("in-scrolling");
                    inScrolling = true;
                    e.stopPropagation();
                    e.preventDefault();
                });
                $(ownerDocument).bind(eventClass("mousemove"), function(e) {
                    if (inScrolling) {
                        updateScrollLeft(currentLeft, e.pageX - currentPageX);
                        updateGeometry();
                        e.stopPropagation();
                        e.preventDefault();
                    }
                });
                $(ownerDocument).bind(eventClass("mouseup"), function(e) {
                    if (inScrolling) {
                        inScrolling = false;
                        $scrollbarXRail.removeClass("in-scrolling");
                    }
                });
                currentLeft = currentPageX = null;
            }
            function bindMouseScrollYHandler() {
                var currentTop;
                var currentPageY;
                var inScrolling = false;
                $scrollbarY.bind(eventClass("mousedown"), function(e) {
                    currentPageY = e.pageY;
                    currentTop = $scrollbarY.position().top;
                    inScrolling = true;
                    $scrollbarYRail.addClass("in-scrolling");
                    e.stopPropagation();
                    e.preventDefault();
                });
                $(ownerDocument).bind(eventClass("mousemove"), function(e) {
                    if (inScrolling) {
                        updateScrollTop(currentTop, e.pageY - currentPageY);
                        updateGeometry();
                        e.stopPropagation();
                        e.preventDefault();
                    }
                });
                $(ownerDocument).bind(eventClass("mouseup"), function(e) {
                    if (inScrolling) {
                        inScrolling = false;
                        $scrollbarYRail.removeClass("in-scrolling");
                    }
                });
                currentTop = currentPageY = null;
            }
            function shouldPreventDefault(deltaX, deltaY) {
                var scrollTop = $this.scrollTop();
                if (deltaX === 0) {
                    if (!scrollbarYActive) {
                        return false;
                    }
                    if (scrollTop === 0 && deltaY > 0 || scrollTop >= contentHeight - containerHeight && deltaY < 0) {
                        return !settings.wheelPropagation;
                    }
                }
                var scrollLeft = $this.scrollLeft();
                if (deltaY === 0) {
                    if (!scrollbarXActive) {
                        return false;
                    }
                    if (scrollLeft === 0 && deltaX < 0 || scrollLeft >= contentWidth - containerWidth && deltaX > 0) {
                        return !settings.wheelPropagation;
                    }
                }
                return true;
            }
            function bindMouseWheelHandler() {
                var shouldPrevent = false;
                function getDeltaFromEvent(e) {
                    var deltaX = e.originalEvent.deltaX;
                    var deltaY = -1 * e.originalEvent.deltaY;
                    if (typeof deltaX === "undefined" || typeof deltaY === "undefined") {
                        deltaX = -1 * e.originalEvent.wheelDeltaX / 6;
                        deltaY = e.originalEvent.wheelDeltaY / 6;
                    }
                    if (e.originalEvent.deltaMode && e.originalEvent.deltaMode === 1) {
                        deltaX *= 10;
                        deltaY *= 10;
                    }
                    if (deltaX !== deltaX && deltaY !== deltaY) {
                        deltaX = 0;
                        deltaY = e.originalEvent.wheelDelta;
                    }
                    return [ deltaX, deltaY ];
                }
                function mousewheelHandler(e) {
                    var delta = getDeltaFromEvent(e);
                    var deltaX = delta[0];
                    var deltaY = delta[1];
                    shouldPrevent = false;
                    if (!settings.useBothWheelAxes) {
                        $this.scrollTop($this.scrollTop() - deltaY * settings.wheelSpeed);
                        $this.scrollLeft($this.scrollLeft() + deltaX * settings.wheelSpeed);
                    } else if (scrollbarYActive && !scrollbarXActive) {
                        if (deltaY) {
                            $this.scrollTop($this.scrollTop() - deltaY * settings.wheelSpeed);
                        } else {
                            $this.scrollTop($this.scrollTop() + deltaX * settings.wheelSpeed);
                        }
                        shouldPrevent = true;
                    } else if (scrollbarXActive && !scrollbarYActive) {
                        if (deltaX) {
                            $this.scrollLeft($this.scrollLeft() + deltaX * settings.wheelSpeed);
                        } else {
                            $this.scrollLeft($this.scrollLeft() - deltaY * settings.wheelSpeed);
                        }
                        shouldPrevent = true;
                    }
                    updateGeometry();
                    shouldPrevent = shouldPrevent || shouldPreventDefault(deltaX, deltaY);
                    if (shouldPrevent) {
                        e.stopPropagation();
                        e.preventDefault();
                    }
                }
                if (typeof window.onwheel !== "undefined") {
                    $this.bind(eventClass("wheel"), mousewheelHandler);
                } else if (typeof window.onmousewheel !== "undefined") {
                    $this.bind(eventClass("mousewheel"), mousewheelHandler);
                }
            }
            function bindKeyboardHandler() {
                var hovered = false;
                $this.bind(eventClass("mouseenter"), function(e) {
                    hovered = true;
                });
                $this.bind(eventClass("mouseleave"), function(e) {
                    hovered = false;
                });
                var shouldPrevent = false;
                $(ownerDocument).bind(eventClass("keydown"), function(e) {
                    if (e.isDefaultPrevented && e.isDefaultPrevented()) {
                        return;
                    }
                    if (!hovered) {
                        return;
                    }
                    var activeElement = document.activeElement ? document.activeElement : ownerDocument.activeElement;
                    while (activeElement.shadowRoot) {
                        activeElement = activeElement.shadowRoot.activeElement;
                    }
                    if ($(activeElement).is(":input,[contenteditable]")) {
                        return;
                    }
                    var deltaX = 0;
                    var deltaY = 0;
                    switch (e.which) {
                      case 37:
                        deltaX = -30;
                        break;

                      case 38:
                        deltaY = 30;
                        break;

                      case 39:
                        deltaX = 30;
                        break;

                      case 40:
                        deltaY = -30;
                        break;

                      case 33:
                        deltaY = 90;
                        break;

                      case 32:
                      case 34:
                        deltaY = -90;
                        break;

                      case 35:
                        if (e.ctrlKey) {
                            deltaY = -contentHeight;
                        } else {
                            deltaY = -containerHeight;
                        }
                        break;

                      case 36:
                        if (e.ctrlKey) {
                            deltaY = $this.scrollTop();
                        } else {
                            deltaY = containerHeight;
                        }
                        break;

                      default:
                        return;
                    }
                    $this.scrollTop($this.scrollTop() - deltaY);
                    $this.scrollLeft($this.scrollLeft() + deltaX);
                    shouldPrevent = shouldPreventDefault(deltaX, deltaY);
                    if (shouldPrevent) {
                        e.preventDefault();
                    }
                });
            }
            function bindRailClickHandler() {
                function stopPropagation(e) {
                    e.stopPropagation();
                }
                $scrollbarY.bind(eventClass("click"), stopPropagation);
                $scrollbarYRail.bind(eventClass("click"), function(e) {
                    var halfOfScrollbarLength = int(scrollbarYHeight / 2);
                    var positionTop = e.pageY - $scrollbarYRail.offset().top - halfOfScrollbarLength;
                    var maxPositionTop = containerHeight - scrollbarYHeight;
                    var positionRatio = positionTop / maxPositionTop;
                    if (positionRatio < 0) {
                        positionRatio = 0;
                    } else if (positionRatio > 1) {
                        positionRatio = 1;
                    }
                    $this.scrollTop((contentHeight - containerHeight) * positionRatio);
                });
                $scrollbarX.bind(eventClass("click"), stopPropagation);
                $scrollbarXRail.bind(eventClass("click"), function(e) {
                    var halfOfScrollbarLength = int(scrollbarXWidth / 2);
                    var positionLeft = e.pageX - $scrollbarXRail.offset().left - halfOfScrollbarLength;
                    var maxPositionLeft = containerWidth - scrollbarXWidth;
                    var positionRatio = positionLeft / maxPositionLeft;
                    if (positionRatio < 0) {
                        positionRatio = 0;
                    } else if (positionRatio > 1) {
                        positionRatio = 1;
                    }
                    $this.scrollLeft((contentWidth - containerWidth) * positionRatio);
                });
            }
            function bindSelectionHandler() {
                function getRangeNode() {
                    var selection = window.getSelection ? window.getSelection() : document.getSlection ? document.getSlection() : {
                        rangeCount: 0
                    };
                    if (selection.rangeCount === 0) {
                        return null;
                    } else {
                        return selection.getRangeAt(0).commonAncestorContainer;
                    }
                }
                var scrollingLoop = null;
                var scrollDiff = {
                    top: 0,
                    left: 0
                };
                function startScrolling() {
                    if (!scrollingLoop) {
                        scrollingLoop = setInterval(function() {
                            if (!isPluginAlive()) {
                                clearInterval(scrollingLoop);
                                return;
                            }
                            $this.scrollTop($this.scrollTop() + scrollDiff.top);
                            $this.scrollLeft($this.scrollLeft() + scrollDiff.left);
                            updateGeometry();
                        }, 50);
                    }
                }
                function stopScrolling() {
                    if (scrollingLoop) {
                        clearInterval(scrollingLoop);
                        scrollingLoop = null;
                    }
                    $scrollbarXRail.removeClass("in-scrolling");
                    $scrollbarYRail.removeClass("in-scrolling");
                }
                var isSelected = false;
                $(ownerDocument).bind(eventClass("selectionchange"), function(e) {
                    if ($.contains($this[0], getRangeNode())) {
                        isSelected = true;
                    } else {
                        isSelected = false;
                        stopScrolling();
                    }
                });
                $(window).bind(eventClass("mouseup"), function(e) {
                    if (isSelected) {
                        isSelected = false;
                        stopScrolling();
                    }
                });
                $(window).bind(eventClass("mousemove"), function(e) {
                    if (isSelected) {
                        var mousePosition = {
                            x: e.pageX,
                            y: e.pageY
                        };
                        var containerOffset = $this.offset();
                        var containerGeometry = {
                            left: containerOffset.left,
                            right: containerOffset.left + $this.outerWidth(),
                            top: containerOffset.top,
                            bottom: containerOffset.top + $this.outerHeight()
                        };
                        if (mousePosition.x < containerGeometry.left + 3) {
                            scrollDiff.left = -5;
                            $scrollbarXRail.addClass("in-scrolling");
                        } else if (mousePosition.x > containerGeometry.right - 3) {
                            scrollDiff.left = 5;
                            $scrollbarXRail.addClass("in-scrolling");
                        } else {
                            scrollDiff.left = 0;
                        }
                        if (mousePosition.y < containerGeometry.top + 3) {
                            if (containerGeometry.top + 3 - mousePosition.y < 5) {
                                scrollDiff.top = -5;
                            } else {
                                scrollDiff.top = -20;
                            }
                            $scrollbarYRail.addClass("in-scrolling");
                        } else if (mousePosition.y > containerGeometry.bottom - 3) {
                            if (mousePosition.y - containerGeometry.bottom + 3 < 5) {
                                scrollDiff.top = 5;
                            } else {
                                scrollDiff.top = 20;
                            }
                            $scrollbarYRail.addClass("in-scrolling");
                        } else {
                            scrollDiff.top = 0;
                        }
                        if (scrollDiff.top === 0 && scrollDiff.left === 0) {
                            stopScrolling();
                        } else {
                            startScrolling();
                        }
                    }
                });
            }
            function bindTouchHandler(supportsTouch, supportsIePointer) {
                function applyTouchMove(differenceX, differenceY) {
                    $this.scrollTop($this.scrollTop() - differenceY);
                    $this.scrollLeft($this.scrollLeft() - differenceX);
                    updateGeometry();
                }
                var startOffset = {};
                var startTime = 0;
                var speed = {};
                var easingLoop = null;
                var inGlobalTouch = false;
                var inLocalTouch = false;
                function globalTouchStart(e) {
                    inGlobalTouch = true;
                }
                function globalTouchEnd(e) {
                    inGlobalTouch = false;
                }
                function getTouch(e) {
                    if (e.originalEvent.targetTouches) {
                        return e.originalEvent.targetTouches[0];
                    } else {
                        return e.originalEvent;
                    }
                }
                function shouldHandle(e) {
                    var event = e.originalEvent;
                    if (event.targetTouches && event.targetTouches.length === 1) {
                        return true;
                    }
                    if (event.pointerType && event.pointerType !== "mouse" && event.pointerType !== event.MSPOINTER_TYPE_MOUSE) {
                        return true;
                    }
                    return false;
                }
                function touchStart(e) {
                    if (shouldHandle(e)) {
                        inLocalTouch = true;
                        var touch = getTouch(e);
                        startOffset.pageX = touch.pageX;
                        startOffset.pageY = touch.pageY;
                        startTime = new Date().getTime();
                        if (easingLoop !== null) {
                            clearInterval(easingLoop);
                        }
                        e.stopPropagation();
                    }
                }
                function touchMove(e) {
                    if (!inGlobalTouch && inLocalTouch && shouldHandle(e)) {
                        var touch = getTouch(e);
                        var currentOffset = {
                            pageX: touch.pageX,
                            pageY: touch.pageY
                        };
                        var differenceX = currentOffset.pageX - startOffset.pageX;
                        var differenceY = currentOffset.pageY - startOffset.pageY;
                        applyTouchMove(differenceX, differenceY);
                        startOffset = currentOffset;
                        var currentTime = new Date().getTime();
                        var timeGap = currentTime - startTime;
                        if (timeGap > 0) {
                            speed.x = differenceX / timeGap;
                            speed.y = differenceY / timeGap;
                            startTime = currentTime;
                        }
                        e.stopPropagation();
                        e.preventDefault();
                    }
                }
                function touchEnd(e) {
                    if (!inGlobalTouch && inLocalTouch) {
                        inLocalTouch = false;
                        clearInterval(easingLoop);
                        easingLoop = setInterval(function() {
                            if (!isPluginAlive()) {
                                clearInterval(easingLoop);
                                return;
                            }
                            if (Math.abs(speed.x) < .01 && Math.abs(speed.y) < .01) {
                                clearInterval(easingLoop);
                                return;
                            }
                            applyTouchMove(speed.x * 30, speed.y * 30);
                            speed.x *= .8;
                            speed.y *= .8;
                        }, 10);
                    }
                }
                if (supportsTouch) {
                    $(window).bind(eventClass("touchstart"), globalTouchStart);
                    $(window).bind(eventClass("touchend"), globalTouchEnd);
                    $this.bind(eventClass("touchstart"), touchStart);
                    $this.bind(eventClass("touchmove"), touchMove);
                    $this.bind(eventClass("touchend"), touchEnd);
                }
                if (supportsIePointer) {
                    if (window.PointerEvent) {
                        $(window).bind(eventClass("pointerdown"), globalTouchStart);
                        $(window).bind(eventClass("pointerup"), globalTouchEnd);
                        $this.bind(eventClass("pointerdown"), touchStart);
                        $this.bind(eventClass("pointermove"), touchMove);
                        $this.bind(eventClass("pointerup"), touchEnd);
                    } else if (window.MSPointerEvent) {
                        $(window).bind(eventClass("MSPointerDown"), globalTouchStart);
                        $(window).bind(eventClass("MSPointerUp"), globalTouchEnd);
                        $this.bind(eventClass("MSPointerDown"), touchStart);
                        $this.bind(eventClass("MSPointerMove"), touchMove);
                        $this.bind(eventClass("MSPointerUp"), touchEnd);
                    }
                }
            }
            function bindScrollHandler() {
                $this.bind(eventClass("scroll"), function(e) {
                    updateGeometry();
                });
            }
            function destroy() {
                $this.unbind(eventClass());
                $(window).unbind(eventClass());
                $(ownerDocument).unbind(eventClass());
                $this.data("perfect-scrollbar", null);
                $this.data("perfect-scrollbar-update", null);
                $this.data("perfect-scrollbar-destroy", null);
                $scrollbarX.remove();
                $scrollbarY.remove();
                $scrollbarXRail.remove();
                $scrollbarYRail.remove();
                $this = $scrollbarXRail = $scrollbarYRail = $scrollbarX = $scrollbarY = scrollbarXActive = scrollbarYActive = containerWidth = containerHeight = contentWidth = contentHeight = scrollbarXWidth = scrollbarXLeft = scrollbarXBottom = isScrollbarXUsingBottom = scrollbarXTop = scrollbarYHeight = scrollbarYTop = scrollbarYRight = isScrollbarYUsingRight = scrollbarYLeft = isRtl = eventClass = null;
            }
            var supportsTouch = "ontouchstart" in window || window.DocumentTouch && document instanceof window.DocumentTouch;
            var supportsIePointer = window.navigator.msMaxTouchPoints !== null;
            function initialize() {
                updateGeometry();
                bindScrollHandler();
                bindMouseScrollXHandler();
                bindMouseScrollYHandler();
                bindRailClickHandler();
                bindSelectionHandler();
                bindMouseWheelHandler();
                if (supportsTouch || supportsIePointer) {
                    bindTouchHandler(supportsTouch, supportsIePointer);
                }
                if (settings.useKeyboard) {
                    bindKeyboardHandler();
                }
                $this.data("perfect-scrollbar", $this);
                $this.data("perfect-scrollbar-update", updateGeometry);
                $this.data("perfect-scrollbar-destroy", destroy);
            }
            initialize();
            return $this;
        });
    };
});

(function(factory) {
    if (typeof define === "function" && define.amd) {
        define([ "jquery" ], factory);
    } else if (typeof exports === "object") {
        module.exports = factory;
    } else {
        factory(jQuery);
    }
})(function($) {
    var toFix = [ "wheel", "mousewheel", "DOMMouseScroll", "MozMousePixelScroll" ], toBind = "onwheel" in document || document.documentMode >= 9 ? [ "wheel" ] : [ "mousewheel", "DomMouseScroll", "MozMousePixelScroll" ], slice = Array.prototype.slice, nullLowestDeltaTimeout, lowestDelta;
    if ($.event.fixHooks) {
        for (var i = toFix.length; i; ) {
            $.event.fixHooks[toFix[--i]] = $.event.mouseHooks;
        }
    }
    var special = $.event.special.mousewheel = {
        version: "3.1.9",
        setup: function() {
            if (this.addEventListener) {
                for (var i = toBind.length; i; ) {
                    this.addEventListener(toBind[--i], handler, false);
                }
            } else {
                this.onmousewheel = handler;
            }
            $.data(this, "mousewheel-line-height", special.getLineHeight(this));
            $.data(this, "mousewheel-page-height", special.getPageHeight(this));
        },
        teardown: function() {
            if (this.removeEventListener) {
                for (var i = toBind.length; i; ) {
                    this.removeEventListener(toBind[--i], handler, false);
                }
            } else {
                this.onmousewheel = null;
            }
        },
        getLineHeight: function(elem) {
            return parseInt($(elem)["offsetParent" in $.fn ? "offsetParent" : "parent"]().css("fontSize"), 10);
        },
        getPageHeight: function(elem) {
            return $(elem).height();
        },
        settings: {
            adjustOldDeltas: true
        }
    };
    $.fn.extend({
        mousewheel: function(fn) {
            return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
        },
        unmousewheel: function(fn) {
            return this.unbind("mousewheel", fn);
        }
    });
    function handler(event) {
        var orgEvent = event || window.event, args = slice.call(arguments, 1), delta = 0, deltaX = 0, deltaY = 0, absDelta = 0;
        event = $.event.fix(orgEvent);
        event.type = "mousewheel";
        if ("detail" in orgEvent) {
            deltaY = orgEvent.detail * -1;
        }
        if ("wheelDelta" in orgEvent) {
            deltaY = orgEvent.wheelDelta;
        }
        if ("wheelDeltaY" in orgEvent) {
            deltaY = orgEvent.wheelDeltaY;
        }
        if ("wheelDeltaX" in orgEvent) {
            deltaX = orgEvent.wheelDeltaX * -1;
        }
        if ("axis" in orgEvent && orgEvent.axis === orgEvent.HORIZONTAL_AXIS) {
            deltaX = deltaY * -1;
            deltaY = 0;
        }
        delta = deltaY === 0 ? deltaX : deltaY;
        if ("deltaY" in orgEvent) {
            deltaY = orgEvent.deltaY * -1;
            delta = deltaY;
        }
        if ("deltaX" in orgEvent) {
            deltaX = orgEvent.deltaX;
            if (deltaY === 0) {
                delta = deltaX * -1;
            }
        }
        if (deltaY === 0 && deltaX === 0) {
            return;
        }
        if (orgEvent.deltaMode === 1) {
            var lineHeight = $.data(this, "mousewheel-line-height");
            delta *= lineHeight;
            deltaY *= lineHeight;
            deltaX *= lineHeight;
        } else if (orgEvent.deltaMode === 2) {
            var pageHeight = $.data(this, "mousewheel-page-height");
            delta *= pageHeight;
            deltaY *= pageHeight;
            deltaX *= pageHeight;
        }
        absDelta = Math.max(Math.abs(deltaY), Math.abs(deltaX));
        if (!lowestDelta || absDelta < lowestDelta) {
            lowestDelta = absDelta;
            if (shouldAdjustOldDeltas(orgEvent, absDelta)) {
                lowestDelta /= 40;
            }
        }
        if (shouldAdjustOldDeltas(orgEvent, absDelta)) {
            delta /= 40;
            deltaX /= 40;
            deltaY /= 40;
        }
        delta = Math[delta >= 1 ? "floor" : "ceil"](delta / lowestDelta);
        deltaX = Math[deltaX >= 1 ? "floor" : "ceil"](deltaX / lowestDelta);
        deltaY = Math[deltaY >= 1 ? "floor" : "ceil"](deltaY / lowestDelta);
        event.deltaX = deltaX;
        event.deltaY = deltaY;
        event.deltaFactor = lowestDelta;
        event.deltaMode = 0;
        args.unshift(event, delta, deltaX, deltaY);
        if (nullLowestDeltaTimeout) {
            clearTimeout(nullLowestDeltaTimeout);
        }
        nullLowestDeltaTimeout = setTimeout(nullLowestDelta, 200);
        return ($.event.dispatch || $.event.handle).apply(this, args);
    }
    function nullLowestDelta() {
        lowestDelta = null;
    }
    function shouldAdjustOldDeltas(orgEvent, absDelta) {
        return special.settings.adjustOldDeltas && orgEvent.type === "mousewheel" && absDelta % 120 === 0;
    }
});

jQuery.fn.doubleScroll = function(userOptions) {
    var options = {
        contentElement: undefined,
        scrollCss: {
            "overflow-x": "auto",
            "overflow-y": "hidden"
        },
        contentCss: {
            "overflow-x": "auto",
            "overflow-y": "hidden"
        },
        onlyIfScroll: true,
        resetOnWindowResize: false,
        timeToWaitForResize: 30
    };
    $.extend(true, options, userOptions);
    $.extend(options, {
        topScrollBarMarkup: '<div class="doubleScroll-scroll-wrapper" style="height: 20px;"><div class="doubleScroll-scroll" style="height: 20px;"></div></div>',
        topScrollBarWrapperSelector: ".doubleScroll-scroll-wrapper",
        topScrollBarInnerSelector: ".doubleScroll-scroll"
    });
    var _showScrollBar = function($self, options) {
        if (options.onlyIfScroll && $self.get(0).scrollWidth <= $self.width()) {
            $self.prev(options.topScrollBarWrapperSelector).remove();
            return;
        }
        var $topScrollBar = $self.prev(options.topScrollBarWrapperSelector);
        if ($topScrollBar.length == 0) {
            $topScrollBar = $(options.topScrollBarMarkup);
            $self.before($topScrollBar);
            $topScrollBar.css(options.scrollCss);
            $self.css(options.contentCss);
            $topScrollBar.bind("scroll.doubleScroll", function() {
                $self.scrollLeft($topScrollBar.scrollLeft());
            });
            var selfScrollHandler = function() {
                $topScrollBar.scrollLeft($self.scrollLeft());
            };
            $self.bind("scroll.doubleScroll", selfScrollHandler);
        }
        var $contentElement;
        if (options.contentElement !== undefined && $self.find(options.contentElement).length !== 0) {
            $contentElement = $self.find(options.contentElement);
        } else {
            $contentElement = $self.find(">:first-child");
        }
        $(options.topScrollBarInnerSelector, $topScrollBar).width($contentElement.outerWidth());
        $topScrollBar.width($self.width());
        $topScrollBar.scrollLeft($self.scrollLeft());
    };
    return this.each(function() {
        var $self = $(this);
        _showScrollBar($self, options);
        if (options.resetOnWindowResize) {
            var id;
            var handler = function(e) {
                _showScrollBar($self, options);
            };
            $(window).bind("resize.doubleScroll", function() {
                clearTimeout(id);
                id = setTimeout(handler, options.timeToWaitForResize);
            });
        }
    });
};

(function(undefined) {
    if (typeof window === "undefined") return;
    var count = 0, logEnabled = false, hiddenCheckEnabled = false, msgHeader = "message", msgHeaderLen = msgHeader.length, msgId = "[iFrameSizer]", msgIdLen = msgId.length, pagePosition = null, requestAnimationFrame = window.requestAnimationFrame, resetRequiredMethods = {
        max: 1,
        scroll: 1,
        bodyScroll: 1,
        documentElementScroll: 1
    }, settings = {}, timer = null, defaults = {
        autoResize: true,
        bodyBackground: null,
        bodyMargin: null,
        bodyMarginV1: 8,
        bodyPadding: null,
        checkOrigin: true,
        inPageLinks: false,
        enablePublicMethods: true,
        heightCalculationMethod: "bodyOffset",
        id: "iFrameResizer",
        interval: 32,
        log: false,
        maxHeight: Infinity,
        maxWidth: Infinity,
        minHeight: 0,
        minWidth: 0,
        mouseEvents: true,
        resizeFrom: "parent",
        scrolling: false,
        sizeHeight: true,
        sizeWidth: false,
        warningTimeout: 5e3,
        tolerance: 0,
        widthCalculationMethod: "scroll",
        onClose: function() {
            return true;
        },
        onClosed: function() {},
        onInit: function() {},
        onMessage: function() {
            warn("onMessage function not defined");
        },
        onMouseEnter: function() {},
        onMouseLeave: function() {},
        onResized: function() {},
        onScroll: function() {
            return true;
        }
    };
    function getMutationObserver() {
        return window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
    }
    function addEventListener(el, evt, func) {
        el.addEventListener(evt, func, false);
    }
    function removeEventListener(el, evt, func) {
        el.removeEventListener(evt, func, false);
    }
    function setupRequestAnimationFrame() {
        var vendors = [ "moz", "webkit", "o", "ms" ];
        var x;
        for (x = 0; x < vendors.length && !requestAnimationFrame; x += 1) {
            requestAnimationFrame = window[vendors[x] + "RequestAnimationFrame"];
        }
        if (!requestAnimationFrame) {
            log("setup", "RequestAnimationFrame not supported");
        } else {
            requestAnimationFrame = requestAnimationFrame.bind(window);
        }
    }
    function getMyID(iframeId) {
        var retStr = "Host page: " + iframeId;
        if (window.top !== window.self) {
            retStr = window.parentIFrame && window.parentIFrame.getId ? window.parentIFrame.getId() + ": " + iframeId : "Nested host page: " + iframeId;
        }
        return retStr;
    }
    function formatLogHeader(iframeId) {
        return msgId + "[" + getMyID(iframeId) + "]";
    }
    function isLogEnabled(iframeId) {
        return settings[iframeId] ? settings[iframeId].log : logEnabled;
    }
    function log(iframeId, msg) {
        output("log", iframeId, msg, isLogEnabled(iframeId));
    }
    function info(iframeId, msg) {
        output("info", iframeId, msg, isLogEnabled(iframeId));
    }
    function warn(iframeId, msg) {
        output("warn", iframeId, msg, true);
    }
    function output(type, iframeId, msg, enabled) {
        if (true === enabled && "object" === typeof window.console) {
            console[type](formatLogHeader(iframeId), msg);
        }
    }
    function iFrameListener(event) {
        function resizeIFrame() {
            function resize() {
                setSize(messageData);
                setPagePosition(iframeId);
                on("onResized", messageData);
            }
            ensureInRange("Height");
            ensureInRange("Width");
            syncResize(resize, messageData, "init");
        }
        function processMsg() {
            var data = msg.substr(msgIdLen).split(":");
            var height = data[1] ? parseInt(data[1], 10) : 0;
            var iframe = settings[data[0]] && settings[data[0]].iframe;
            var compStyle = getComputedStyle(iframe);
            return {
                iframe: iframe,
                id: data[0],
                height: height + getPaddingEnds(compStyle) + getBorderEnds(compStyle),
                width: data[2],
                type: data[3]
            };
        }
        function getPaddingEnds(compStyle) {
            if (compStyle.boxSizing !== "border-box") {
                return 0;
            }
            var top = compStyle.paddingTop ? parseInt(compStyle.paddingTop, 10) : 0;
            var bot = compStyle.paddingBottom ? parseInt(compStyle.paddingBottom, 10) : 0;
            return top + bot;
        }
        function getBorderEnds(compStyle) {
            if (compStyle.boxSizing !== "border-box") {
                return 0;
            }
            var top = compStyle.borderTopWidth ? parseInt(compStyle.borderTopWidth, 10) : 0;
            var bot = compStyle.borderBottomWidth ? parseInt(compStyle.borderBottomWidth, 10) : 0;
            return top + bot;
        }
        function ensureInRange(Dimension) {
            var max = Number(settings[iframeId]["max" + Dimension]), min = Number(settings[iframeId]["min" + Dimension]), dimension = Dimension.toLowerCase(), size = Number(messageData[dimension]);
            log(iframeId, "Checking " + dimension + " is in range " + min + "-" + max);
            if (size < min) {
                size = min;
                log(iframeId, "Set " + dimension + " to min value");
            }
            if (size > max) {
                size = max;
                log(iframeId, "Set " + dimension + " to max value");
            }
            messageData[dimension] = "" + size;
        }
        function isMessageFromIFrame() {
            function checkAllowedOrigin() {
                function checkList() {
                    var i = 0, retCode = false;
                    log(iframeId, "Checking connection is from allowed list of origins: " + checkOrigin);
                    for (;i < checkOrigin.length; i++) {
                        if (checkOrigin[i] === origin) {
                            retCode = true;
                            break;
                        }
                    }
                    return retCode;
                }
                function checkSingle() {
                    var remoteHost = settings[iframeId] && settings[iframeId].remoteHost;
                    log(iframeId, "Checking connection is from: " + remoteHost);
                    return origin === remoteHost;
                }
                return checkOrigin.constructor === Array ? checkList() : checkSingle();
            }
            var origin = event.origin, checkOrigin = settings[iframeId] && settings[iframeId].checkOrigin;
            if (checkOrigin && "" + origin !== "null" && !checkAllowedOrigin()) {
                throw new Error("Unexpected message received from: " + origin + " for " + messageData.iframe.id + ". Message was: " + event.data + ". This error can be disabled by setting the checkOrigin: false option or by providing of array of trusted domains.");
            }
            return true;
        }
        function isMessageForUs() {
            return msgId === ("" + msg).substr(0, msgIdLen) && msg.substr(msgIdLen).split(":")[0] in settings;
        }
        function isMessageFromMetaParent() {
            var retCode = messageData.type in {
                true: 1,
                false: 1,
                undefined: 1
            };
            if (retCode) {
                log(iframeId, "Ignoring init message from meta parent page");
            }
            return retCode;
        }
        function getMsgBody(offset) {
            return msg.substr(msg.indexOf(":") + msgHeaderLen + offset);
        }
        function forwardMsgFromIFrame(msgBody) {
            log(iframeId, "onMessage passed: {iframe: " + messageData.iframe.id + ", message: " + msgBody + "}");
            on("onMessage", {
                iframe: messageData.iframe,
                message: JSON.parse(msgBody)
            });
            log(iframeId, "--");
        }
        function getPageInfo() {
            var bodyPosition = document.body.getBoundingClientRect(), iFramePosition = messageData.iframe.getBoundingClientRect();
            return JSON.stringify({
                iframeHeight: iFramePosition.height,
                iframeWidth: iFramePosition.width,
                clientHeight: Math.max(document.documentElement.clientHeight, window.innerHeight || 0),
                clientWidth: Math.max(document.documentElement.clientWidth, window.innerWidth || 0),
                offsetTop: parseInt(iFramePosition.top - bodyPosition.top, 10),
                offsetLeft: parseInt(iFramePosition.left - bodyPosition.left, 10),
                scrollTop: window.pageYOffset,
                scrollLeft: window.pageXOffset,
                documentHeight: document.documentElement.clientHeight,
                documentWidth: document.documentElement.clientWidth,
                windowHeight: window.innerHeight,
                windowWidth: window.innerWidth
            });
        }
        function sendPageInfoToIframe(iframe, iframeId) {
            function debouncedTrigger() {
                trigger("Send Page Info", "pageInfo:" + getPageInfo(), iframe, iframeId);
            }
            debounceFrameEvents(debouncedTrigger, 32, iframeId);
        }
        function startPageInfoMonitor() {
            function setListener(type, func) {
                function sendPageInfo() {
                    if (settings[id]) {
                        sendPageInfoToIframe(settings[id].iframe, id);
                    } else {
                        stop();
                    }
                }
                [ "scroll", "resize" ].forEach(function(evt) {
                    log(id, type + evt + " listener for sendPageInfo");
                    func(window, evt, sendPageInfo);
                });
            }
            function stop() {
                setListener("Remove ", removeEventListener);
            }
            function start() {
                setListener("Add ", addEventListener);
            }
            var id = iframeId;
            start();
            if (settings[id]) {
                settings[id].stopPageInfo = stop;
            }
        }
        function stopPageInfoMonitor() {
            if (settings[iframeId] && settings[iframeId].stopPageInfo) {
                settings[iframeId].stopPageInfo();
                delete settings[iframeId].stopPageInfo;
            }
        }
        function checkIFrameExists() {
            var retBool = true;
            if (null === messageData.iframe) {
                warn(iframeId, "IFrame (" + messageData.id + ") not found");
                retBool = false;
            }
            return retBool;
        }
        function getElementPosition(target) {
            var iFramePosition = target.getBoundingClientRect();
            getPagePosition(iframeId);
            return {
                x: Math.floor(Number(iFramePosition.left) + Number(pagePosition.x)),
                y: Math.floor(Number(iFramePosition.top) + Number(pagePosition.y))
            };
        }
        function scrollRequestFromChild(addOffset) {
            function reposition() {
                pagePosition = newPosition;
                scrollTo();
                log(iframeId, "--");
            }
            function calcOffset() {
                return {
                    x: Number(messageData.width) + offset.x,
                    y: Number(messageData.height) + offset.y
                };
            }
            function scrollParent() {
                if (window.parentIFrame) {
                    window.parentIFrame["scrollTo" + (addOffset ? "Offset" : "")](newPosition.x, newPosition.y);
                } else {
                    warn(iframeId, "Unable to scroll to requested position, window.parentIFrame not found");
                }
            }
            var offset = addOffset ? getElementPosition(messageData.iframe) : {
                x: 0,
                y: 0
            }, newPosition = calcOffset();
            log(iframeId, "Reposition requested from iFrame (offset x:" + offset.x + " y:" + offset.y + ")");
            if (window.top !== window.self) {
                scrollParent();
            } else {
                reposition();
            }
        }
        function scrollTo() {
            if (false !== on("onScroll", pagePosition)) {
                setPagePosition(iframeId);
            } else {
                unsetPagePosition();
            }
        }
        function findTarget(location) {
            function jumpToTarget() {
                var jumpPosition = getElementPosition(target);
                log(iframeId, "Moving to in page link (#" + hash + ") at x: " + jumpPosition.x + " y: " + jumpPosition.y);
                pagePosition = {
                    x: jumpPosition.x,
                    y: jumpPosition.y
                };
                scrollTo();
                log(iframeId, "--");
            }
            function jumpToParent() {
                if (window.parentIFrame) {
                    window.parentIFrame.moveToAnchor(hash);
                } else {
                    log(iframeId, "In page link #" + hash + " not found and window.parentIFrame not found");
                }
            }
            var hash = location.split("#")[1] || "", hashData = decodeURIComponent(hash), target = document.getElementById(hashData) || document.getElementsByName(hashData)[0];
            if (target) {
                jumpToTarget();
            } else if (window.top !== window.self) {
                jumpToParent();
            } else {
                log(iframeId, "In page link #" + hash + " not found");
            }
        }
        function onMouse(event) {
            var mousePos = {};
            if (Number(messageData.width) === 0 && Number(messageData.height) === 0) {
                var data = getMsgBody(9).split(":");
                mousePos = {
                    x: data[1],
                    y: data[0]
                };
            } else {
                mousePos = {
                    x: messageData.width,
                    y: messageData.height
                };
            }
            on(event, {
                iframe: messageData.iframe,
                screenX: Number(mousePos.x),
                screenY: Number(mousePos.y),
                type: messageData.type
            });
        }
        function on(funcName, val) {
            return chkEvent(iframeId, funcName, val);
        }
        function actionMsg() {
            if (settings[iframeId] && settings[iframeId].firstRun) firstRun();
            switch (messageData.type) {
              case "close":
                closeIFrame(messageData.iframe);
                break;

              case "message":
                forwardMsgFromIFrame(getMsgBody(6));
                break;

              case "mouseenter":
                onMouse("onMouseEnter");
                break;

              case "mouseleave":
                onMouse("onMouseLeave");
                break;

              case "autoResize":
                settings[iframeId].autoResize = JSON.parse(getMsgBody(9));
                break;

              case "scrollTo":
                scrollRequestFromChild(false);
                break;

              case "scrollToOffset":
                scrollRequestFromChild(true);
                break;

              case "pageInfo":
                sendPageInfoToIframe(settings[iframeId] && settings[iframeId].iframe, iframeId);
                startPageInfoMonitor();
                break;

              case "pageInfoStop":
                stopPageInfoMonitor();
                break;

              case "inPageLink":
                findTarget(getMsgBody(9));
                break;

              case "reset":
                resetIFrame(messageData);
                break;

              case "init":
                resizeIFrame();
                on("onInit", messageData.iframe);
                break;

              default:
                if (Number(messageData.width) === 0 && Number(messageData.height) === 0) {
                    warn("Unsupported message received (" + messageData.type + "), this is likely due to the iframe containing a later " + "version of iframe-resizer than the parent page");
                } else {
                    resizeIFrame();
                }
            }
        }
        function hasSettings(iframeId) {
            var retBool = true;
            if (!settings[iframeId]) {
                retBool = false;
                warn(messageData.type + " No settings for " + iframeId + ". Message was: " + msg);
            }
            return retBool;
        }
        function iFrameReadyMsgReceived() {
            for (var iframeId in settings) {
                trigger("iFrame requested init", createOutgoingMsg(iframeId), settings[iframeId].iframe, iframeId);
            }
        }
        function firstRun() {
            if (settings[iframeId]) {
                settings[iframeId].firstRun = false;
            }
        }
        var msg = event.data, messageData = {}, iframeId = null;
        if ("[iFrameResizerChild]Ready" === msg) {
            iFrameReadyMsgReceived();
        } else if (isMessageForUs()) {
            messageData = processMsg();
            iframeId = messageData.id;
            if (settings[iframeId]) {
                settings[iframeId].loaded = true;
            }
            if (!isMessageFromMetaParent() && hasSettings(iframeId)) {
                log(iframeId, "Received: " + msg);
                if (checkIFrameExists() && isMessageFromIFrame()) {
                    actionMsg();
                }
            }
        } else {
            info(iframeId, "Ignored: " + msg);
        }
    }
    function chkEvent(iframeId, funcName, val) {
        var func = null, retVal = null;
        if (settings[iframeId]) {
            func = settings[iframeId][funcName];
            if ("function" === typeof func) {
                retVal = func(val);
            } else {
                throw new TypeError(funcName + " on iFrame[" + iframeId + "] is not a function");
            }
        }
        return retVal;
    }
    function removeIframeListeners(iframe) {
        var iframeId = iframe.id;
        delete settings[iframeId];
    }
    function closeIFrame(iframe) {
        var iframeId = iframe.id;
        if (chkEvent(iframeId, "onClose", iframeId) === false) {
            log(iframeId, "Close iframe cancelled by onClose event");
            return;
        }
        log(iframeId, "Removing iFrame: " + iframeId);
        try {
            if (iframe.parentNode) {
                iframe.parentNode.removeChild(iframe);
            }
        } catch (error) {
            warn(error);
        }
        chkEvent(iframeId, "onClosed", iframeId);
        log(iframeId, "--");
        removeIframeListeners(iframe);
    }
    function getPagePosition(iframeId) {
        if (null === pagePosition) {
            pagePosition = {
                x: window.pageXOffset !== undefined ? window.pageXOffset : document.documentElement.scrollLeft,
                y: window.pageYOffset !== undefined ? window.pageYOffset : document.documentElement.scrollTop
            };
            log(iframeId, "Get page position: " + pagePosition.x + "," + pagePosition.y);
        }
    }
    function setPagePosition(iframeId) {
        if (null !== pagePosition) {
            window.scrollTo(pagePosition.x, pagePosition.y);
            log(iframeId, "Set page position: " + pagePosition.x + "," + pagePosition.y);
            unsetPagePosition();
        }
    }
    function unsetPagePosition() {
        pagePosition = null;
    }
    function resetIFrame(messageData) {
        function reset() {
            setSize(messageData);
            trigger("reset", "reset", messageData.iframe, messageData.id);
        }
        log(messageData.id, "Size reset requested by " + ("init" === messageData.type ? "host page" : "iFrame"));
        getPagePosition(messageData.id);
        syncResize(reset, messageData, "reset");
    }
    function setSize(messageData) {
        function setDimension(dimension) {
            if (!messageData.id) {
                log("undefined", "messageData id not set");
                return;
            }
            messageData.iframe.style[dimension] = messageData[dimension] + "px";
            log(messageData.id, "IFrame (" + iframeId + ") " + dimension + " set to " + messageData[dimension] + "px");
        }
        function chkZero(dimension) {
            if (!hiddenCheckEnabled && "0" === messageData[dimension]) {
                hiddenCheckEnabled = true;
                log(iframeId, "Hidden iFrame detected, creating visibility listener");
                fixHiddenIFrames();
            }
        }
        function processDimension(dimension) {
            setDimension(dimension);
            chkZero(dimension);
        }
        var iframeId = messageData.iframe.id;
        if (settings[iframeId]) {
            if (settings[iframeId].sizeHeight) {
                processDimension("height");
            }
            if (settings[iframeId].sizeWidth) {
                processDimension("width");
            }
        }
    }
    function syncResize(func, messageData, doNotSync) {
        if (doNotSync !== messageData.type && requestAnimationFrame && !window.jasmine) {
            log(messageData.id, "Requesting animation frame");
            requestAnimationFrame(func);
        } else {
            func();
        }
    }
    function trigger(calleeMsg, msg, iframe, id, noResponseWarning) {
        function postMessageToIFrame() {
            var target = settings[id] && settings[id].targetOrigin;
            log(id, "[" + calleeMsg + "] Sending msg to iframe[" + id + "] (" + msg + ") targetOrigin: " + target);
            iframe.contentWindow.postMessage(msgId + msg, target);
        }
        function iFrameNotFound() {
            warn(id, "[" + calleeMsg + "] IFrame(" + id + ") not found");
        }
        function chkAndSend() {
            if (iframe && "contentWindow" in iframe && null !== iframe.contentWindow) {
                postMessageToIFrame();
            } else {
                iFrameNotFound();
            }
        }
        function warnOnNoResponse() {
            function warning() {
                if (settings[id] && !settings[id].loaded && !errorShown) {
                    errorShown = true;
                    warn(id, "IFrame has not responded within " + settings[id].warningTimeout / 1e3 + " seconds. Check iFrameResizer.contentWindow.js has been loaded in iFrame. This message can be ignored if everything is working, or you can set the warningTimeout option to a higher value or zero to suppress this warning.");
                }
            }
            if (!!noResponseWarning && settings[id] && !!settings[id].warningTimeout) {
                settings[id].msgTimeout = setTimeout(warning, settings[id].warningTimeout);
            }
        }
        var errorShown = false;
        id = id || iframe.id;
        if (settings[id]) {
            chkAndSend();
            warnOnNoResponse();
        }
    }
    function createOutgoingMsg(iframeId) {
        return iframeId + ":" + settings[iframeId].bodyMarginV1 + ":" + settings[iframeId].sizeWidth + ":" + settings[iframeId].log + ":" + settings[iframeId].interval + ":" + settings[iframeId].enablePublicMethods + ":" + settings[iframeId].autoResize + ":" + settings[iframeId].bodyMargin + ":" + settings[iframeId].heightCalculationMethod + ":" + settings[iframeId].bodyBackground + ":" + settings[iframeId].bodyPadding + ":" + settings[iframeId].tolerance + ":" + settings[iframeId].inPageLinks + ":" + settings[iframeId].resizeFrom + ":" + settings[iframeId].widthCalculationMethod + ":" + settings[iframeId].mouseEvents;
    }
    function isNumber(value) {
        return typeof value === "number";
    }
    function setupIFrame(iframe, options) {
        function setLimits() {
            function addStyle(style) {
                var styleValue = settings[iframeId][style];
                if (Infinity !== styleValue && 0 !== styleValue) {
                    iframe.style[style] = isNumber(styleValue) ? styleValue + "px" : styleValue;
                    log(iframeId, "Set " + style + " = " + iframe.style[style]);
                }
            }
            function chkMinMax(dimension) {
                if (settings[iframeId]["min" + dimension] > settings[iframeId]["max" + dimension]) {
                    throw new Error("Value for min" + dimension + " can not be greater than max" + dimension);
                }
            }
            chkMinMax("Height");
            chkMinMax("Width");
            addStyle("maxHeight");
            addStyle("minHeight");
            addStyle("maxWidth");
            addStyle("minWidth");
        }
        function newId() {
            var id = options && options.id || defaults.id + count++;
            if (null !== document.getElementById(id)) {
                id += count++;
            }
            return id;
        }
        function ensureHasId(iframeId) {
            if ("" === iframeId) {
                iframe.id = iframeId = newId();
                logEnabled = (options || {}).log;
                log(iframeId, "Added missing iframe ID: " + iframeId + " (" + iframe.src + ")");
            }
            return iframeId;
        }
        function setScrolling() {
            log(iframeId, "IFrame scrolling " + (settings[iframeId] && settings[iframeId].scrolling ? "enabled" : "disabled") + " for " + iframeId);
            iframe.style.overflow = false === (settings[iframeId] && settings[iframeId].scrolling) ? "hidden" : "auto";
            switch (settings[iframeId] && settings[iframeId].scrolling) {
              case "omit":
                break;

              case true:
                iframe.scrolling = "yes";
                break;

              case false:
                iframe.scrolling = "no";
                break;

              default:
                iframe.scrolling = settings[iframeId] ? settings[iframeId].scrolling : "no";
            }
        }
        function setupBodyMarginValues() {
            if ("number" === typeof (settings[iframeId] && settings[iframeId].bodyMargin) || "0" === (settings[iframeId] && settings[iframeId].bodyMargin)) {
                settings[iframeId].bodyMarginV1 = settings[iframeId].bodyMargin;
                settings[iframeId].bodyMargin = "" + settings[iframeId].bodyMargin + "px";
            }
        }
        function checkReset() {
            var firstRun = settings[iframeId] && settings[iframeId].firstRun, resetRequertMethod = settings[iframeId] && settings[iframeId].heightCalculationMethod in resetRequiredMethods;
            if (!firstRun && resetRequertMethod) {
                resetIFrame({
                    iframe: iframe,
                    height: 0,
                    width: 0,
                    type: "init"
                });
            }
        }
        function setupIFrameObject() {
            if (settings[iframeId]) {
                settings[iframeId].iframe.iFrameResizer = {
                    close: closeIFrame.bind(null, settings[iframeId].iframe),
                    removeListeners: removeIframeListeners.bind(null, settings[iframeId].iframe),
                    resize: trigger.bind(null, "Window resize", "resize", settings[iframeId].iframe),
                    moveToAnchor: function(anchor) {
                        trigger("Move to anchor", "moveToAnchor:" + anchor, settings[iframeId].iframe, iframeId);
                    },
                    sendMessage: function(message) {
                        message = JSON.stringify(message);
                        trigger("Send Message", "message:" + message, settings[iframeId].iframe, iframeId);
                    }
                };
            }
        }
        function init(msg) {
            function iFrameLoaded() {
                trigger("iFrame.onload", msg, iframe, undefined, true);
                checkReset();
            }
            function createDestroyObserver(MutationObserver) {
                if (!iframe.parentNode) {
                    return;
                }
                var destroyObserver = new MutationObserver(function(mutations) {
                    mutations.forEach(function(mutation) {
                        var removedNodes = Array.prototype.slice.call(mutation.removedNodes);
                        removedNodes.forEach(function(removedNode) {
                            if (removedNode === iframe) {
                                closeIFrame(iframe);
                            }
                        });
                    });
                });
                destroyObserver.observe(iframe.parentNode, {
                    childList: true
                });
            }
            var MutationObserver = getMutationObserver();
            if (MutationObserver) {
                createDestroyObserver(MutationObserver);
            }
            addEventListener(iframe, "load", iFrameLoaded);
            trigger("init", msg, iframe, undefined, true);
        }
        function checkOptions(options) {
            if ("object" !== typeof options) {
                throw new TypeError("Options is not an object");
            }
        }
        function copyOptions(options) {
            for (var option in defaults) {
                if (Object.prototype.hasOwnProperty.call(defaults, option)) {
                    settings[iframeId][option] = Object.prototype.hasOwnProperty.call(options, option) ? options[option] : defaults[option];
                }
            }
        }
        function getTargetOrigin(remoteHost) {
            return "" === remoteHost || null !== remoteHost.match(/^(about:blank|javascript:|file:\/\/)/) ? "*" : remoteHost;
        }
        function depricate(key) {
            var splitName = key.split("Callback");
            if (splitName.length === 2) {
                var name = "on" + splitName[0].charAt(0).toUpperCase() + splitName[0].slice(1);
                this[name] = this[key];
                delete this[key];
                warn(iframeId, "Deprecated: '" + key + "' has been renamed '" + name + "'. The old method will be removed in the next major version.");
            }
        }
        function processOptions(options) {
            options = options || {};
            settings[iframeId] = {
                firstRun: true,
                iframe: iframe,
                remoteHost: iframe.src && iframe.src.split("/").slice(0, 3).join("/")
            };
            checkOptions(options);
            Object.keys(options).forEach(depricate, options);
            copyOptions(options);
            if (settings[iframeId]) {
                settings[iframeId].targetOrigin = true === settings[iframeId].checkOrigin ? getTargetOrigin(settings[iframeId].remoteHost) : "*";
            }
        }
        function beenHere() {
            return iframeId in settings && "iFrameResizer" in iframe;
        }
        var iframeId = ensureHasId(iframe.id);
        if (!beenHere()) {
            processOptions(options);
            setScrolling();
            setLimits();
            setupBodyMarginValues();
            init(createOutgoingMsg(iframeId));
            setupIFrameObject();
        } else {
            warn(iframeId, "Ignored iFrame, already setup.");
        }
    }
    function debouce(fn, time) {
        if (null === timer) {
            timer = setTimeout(function() {
                timer = null;
                fn();
            }, time);
        }
    }
    var frameTimer = {};
    function debounceFrameEvents(fn, time, frameId) {
        if (!frameTimer[frameId]) {
            frameTimer[frameId] = setTimeout(function() {
                frameTimer[frameId] = null;
                fn();
            }, time);
        }
    }
    function fixHiddenIFrames() {
        function checkIFrames() {
            function checkIFrame(settingId) {
                function chkDimension(dimension) {
                    return "0px" === (settings[settingId] && settings[settingId].iframe.style[dimension]);
                }
                function isVisible(el) {
                    return null !== el.offsetParent;
                }
                if (settings[settingId] && isVisible(settings[settingId].iframe) && (chkDimension("height") || chkDimension("width"))) {
                    trigger("Visibility change", "resize", settings[settingId].iframe, settingId);
                }
            }
            Object.keys(settings).forEach(function(key) {
                checkIFrame(key);
            });
        }
        function mutationObserved(mutations) {
            log("window", "Mutation observed: " + mutations[0].target + " " + mutations[0].type);
            debouce(checkIFrames, 16);
        }
        function createMutationObserver() {
            var target = document.querySelector("body"), config = {
                attributes: true,
                attributeOldValue: false,
                characterData: true,
                characterDataOldValue: false,
                childList: true,
                subtree: true
            }, observer = new MutationObserver(mutationObserved);
            observer.observe(target, config);
        }
        var MutationObserver = getMutationObserver();
        if (MutationObserver) {
            createMutationObserver();
        }
    }
    function resizeIFrames(event) {
        function resize() {
            sendTriggerMsg("Window " + event, "resize");
        }
        log("window", "Trigger event: " + event);
        debouce(resize, 16);
    }
    function tabVisible() {
        function resize() {
            sendTriggerMsg("Tab Visable", "resize");
        }
        if ("hidden" !== document.visibilityState) {
            log("document", "Trigger event: Visiblity change");
            debouce(resize, 16);
        }
    }
    function sendTriggerMsg(eventName, event) {
        function isIFrameResizeEnabled(iframeId) {
            return settings[iframeId] && "parent" === settings[iframeId].resizeFrom && settings[iframeId].autoResize && !settings[iframeId].firstRun;
        }
        Object.keys(settings).forEach(function(iframeId) {
            if (isIFrameResizeEnabled(iframeId)) {
                trigger(eventName, event, settings[iframeId].iframe, iframeId);
            }
        });
    }
    function setupEventListeners() {
        addEventListener(window, "message", iFrameListener);
        addEventListener(window, "resize", function() {
            resizeIFrames("resize");
        });
        addEventListener(document, "visibilitychange", tabVisible);
        addEventListener(document, "-webkit-visibilitychange", tabVisible);
    }
    function factory() {
        function init(options, element) {
            function chkType() {
                if (!element.tagName) {
                    throw new TypeError("Object is not a valid DOM element");
                } else if ("IFRAME" !== element.tagName.toUpperCase()) {
                    throw new TypeError("Expected <IFRAME> tag, found <" + element.tagName + ">");
                }
            }
            if (element) {
                chkType();
                setupIFrame(element, options);
                iFrames.push(element);
            }
        }
        function warnDeprecatedOptions(options) {
            if (options && options.enablePublicMethods) {
                warn("enablePublicMethods option has been removed, public methods are now always available in the iFrame");
            }
        }
        var iFrames;
        setupRequestAnimationFrame();
        setupEventListeners();
        return function iFrameResizeF(options, target) {
            iFrames = [];
            warnDeprecatedOptions(options);
            switch (typeof target) {
              case "undefined":
              case "string":
                Array.prototype.forEach.call(document.querySelectorAll(target || "iframe"), init.bind(undefined, options));
                break;

              case "object":
                init(options, target);
                break;

              default:
                throw new TypeError("Unexpected data type (" + typeof target + ")");
            }
            return iFrames;
        };
    }
    function createJQueryPublicMethod($) {
        if (!$.fn) {
            info("", "Unable to bind to jQuery, it is not fully loaded.");
        } else if (!$.fn.iFrameResize) {
            $.fn.iFrameResize = function $iFrameResizeF(options) {
                function init(index, element) {
                    setupIFrame(element, options);
                }
                return this.filter("iframe").each(init).end();
            };
        }
    }
    if (window.jQuery) {
        createJQueryPublicMethod(window.jQuery);
    }
    if (typeof define === "function" && define.amd) {
        define([], factory);
    } else if (typeof module === "object" && typeof module.exports === "object") {
        module.exports = factory();
    }
    window.iFrameResize = window.iFrameResize || factory();
})();

!function($) {
    function isInputEventSupported(eventName) {
        var el = document.createElement("input"), evName = "on" + eventName, isSupported = evName in el;
        return isSupported || (el.setAttribute(evName, "return;"), isSupported = "function" == typeof el[evName]), 
        el = null, isSupported;
    }
    function isInputTypeSupported(inputType) {
        var isSupported = "text" == inputType || "tel" == inputType || "password" == inputType;
        if (!isSupported) {
            var el = document.createElement("input");
            el.setAttribute("type", inputType), isSupported = "text" === el.type, 
            el = null;
        }
        return isSupported;
    }
    function resolveAlias(aliasStr, options, opts) {
        var aliasDefinition = opts.aliases[aliasStr];
        return aliasDefinition ? (aliasDefinition.alias && resolveAlias(aliasDefinition.alias, void 0, opts), 
        $.extend(!0, opts, aliasDefinition), $.extend(!0, opts, options), !0) : !1;
    }
    function generateMaskSet(opts, nocache) {
        function analyseMask(mask) {
            function maskToken(isGroup, isOptional, isQuantifier, isAlternator) {
                this.matches = [], this.isGroup = isGroup || !1, this.isOptional = isOptional || !1, 
                this.isQuantifier = isQuantifier || !1, this.isAlternator = isAlternator || !1, 
                this.quantifier = {
                    min: 1,
                    max: 1
                };
            }
            function insertTestDefinition(mtoken, element, position) {
                var maskdef = opts.definitions[element], newBlockMarker = 0 == mtoken.matches.length;
                if (position = void 0 != position ? position : mtoken.matches.length, 
                maskdef && !escaped) {
                    maskdef.placeholder = $.isFunction(maskdef.placeholder) ? maskdef.placeholder.call(this, opts) : maskdef.placeholder;
                    for (var prevalidators = maskdef.prevalidator, prevalidatorsL = prevalidators ? prevalidators.length : 0, i = 1; i < maskdef.cardinality; i++) {
                        var prevalidator = prevalidatorsL >= i ? prevalidators[i - 1] : [], validator = prevalidator.validator, cardinality = prevalidator.cardinality;
                        mtoken.matches.splice(position++, 0, {
                            fn: validator ? "string" == typeof validator ? new RegExp(validator) : new function() {
                                this.test = validator;
                            }() : new RegExp("."),
                            cardinality: cardinality ? cardinality : 1,
                            optionality: mtoken.isOptional,
                            newBlockMarker: newBlockMarker,
                            casing: maskdef.casing,
                            def: maskdef.definitionSymbol || element,
                            placeholder: maskdef.placeholder,
                            mask: element
                        });
                    }
                    mtoken.matches.splice(position++, 0, {
                        fn: maskdef.validator ? "string" == typeof maskdef.validator ? new RegExp(maskdef.validator) : new function() {
                            this.test = maskdef.validator;
                        }() : new RegExp("."),
                        cardinality: maskdef.cardinality,
                        optionality: mtoken.isOptional,
                        newBlockMarker: newBlockMarker,
                        casing: maskdef.casing,
                        def: maskdef.definitionSymbol || element,
                        placeholder: maskdef.placeholder,
                        mask: element
                    });
                } else mtoken.matches.splice(position++, 0, {
                    fn: null,
                    cardinality: 0,
                    optionality: mtoken.isOptional,
                    newBlockMarker: newBlockMarker,
                    casing: null,
                    def: element,
                    placeholder: void 0,
                    mask: element
                }), escaped = !1;
            }
            for (var match, m, openingToken, currentOpeningToken, alternator, lastMatch, tokenizer = /(?:[?*+]|\{[0-9\+\*]+(?:,[0-9\+\*]*)?\})\??|[^.?*+^${[]()|\\]+|./g, escaped = !1, currentToken = new maskToken(), openenings = [], maskTokens = []; match = tokenizer.exec(mask); ) switch (m = match[0], 
            m.charAt(0)) {
              case opts.optionalmarker.end:
              case opts.groupmarker.end:
                if (openingToken = openenings.pop(), openenings.length > 0) {
                    if (currentOpeningToken = openenings[openenings.length - 1], 
                    currentOpeningToken.matches.push(openingToken), currentOpeningToken.isAlternator) {
                        alternator = openenings.pop();
                        for (var mndx = 0; mndx < alternator.matches.length; mndx++) alternator.matches[mndx].isGroup = !1;
                        openenings.length > 0 ? (currentOpeningToken = openenings[openenings.length - 1], 
                        currentOpeningToken.matches.push(alternator)) : currentToken.matches.push(alternator);
                    }
                } else currentToken.matches.push(openingToken);
                break;

              case opts.optionalmarker.start:
                openenings.push(new maskToken(!1, !0));
                break;

              case opts.groupmarker.start:
                openenings.push(new maskToken(!0));
                break;

              case opts.quantifiermarker.start:
                var quantifier = new maskToken(!1, !1, !0);
                m = m.replace(/[{}]/g, "");
                var mq = m.split(","), mq0 = isNaN(mq[0]) ? mq[0] : parseInt(mq[0]), mq1 = 1 == mq.length ? mq0 : isNaN(mq[1]) ? mq[1] : parseInt(mq[1]);
                if (("*" == mq1 || "+" == mq1) && (mq0 = "*" == mq1 ? 0 : 1), quantifier.quantifier = {
                    min: mq0,
                    max: mq1
                }, openenings.length > 0) {
                    var matches = openenings[openenings.length - 1].matches;
                    if (match = matches.pop(), !match.isGroup) {
                        var groupToken = new maskToken(!0);
                        groupToken.matches.push(match), match = groupToken;
                    }
                    matches.push(match), matches.push(quantifier);
                } else {
                    if (match = currentToken.matches.pop(), !match.isGroup) {
                        var groupToken = new maskToken(!0);
                        groupToken.matches.push(match), match = groupToken;
                    }
                    currentToken.matches.push(match), currentToken.matches.push(quantifier);
                }
                break;

              case opts.escapeChar:
                escaped = !0;
                break;

              case opts.alternatormarker:
                openenings.length > 0 ? (currentOpeningToken = openenings[openenings.length - 1], 
                lastMatch = currentOpeningToken.matches.pop()) : lastMatch = currentToken.matches.pop(), 
                lastMatch.isAlternator ? openenings.push(lastMatch) : (alternator = new maskToken(!1, !1, !1, !0), 
                alternator.matches.push(lastMatch), openenings.push(alternator));
                break;

              default:
                if (openenings.length > 0) {
                    if (currentOpeningToken = openenings[openenings.length - 1], 
                    currentOpeningToken.matches.length > 0 && !currentOpeningToken.isAlternator && (lastMatch = currentOpeningToken.matches[currentOpeningToken.matches.length - 1], 
                    lastMatch.isGroup && (lastMatch.isGroup = !1, insertTestDefinition(lastMatch, opts.groupmarker.start, 0), 
                    insertTestDefinition(lastMatch, opts.groupmarker.end))), insertTestDefinition(currentOpeningToken, m), 
                    currentOpeningToken.isAlternator) {
                        alternator = openenings.pop();
                        for (var mndx = 0; mndx < alternator.matches.length; mndx++) alternator.matches[mndx].isGroup = !1;
                        openenings.length > 0 ? (currentOpeningToken = openenings[openenings.length - 1], 
                        currentOpeningToken.matches.push(alternator)) : currentToken.matches.push(alternator);
                    }
                } else currentToken.matches.length > 0 && (lastMatch = currentToken.matches[currentToken.matches.length - 1], 
                lastMatch.isGroup && (lastMatch.isGroup = !1, insertTestDefinition(lastMatch, opts.groupmarker.start, 0), 
                insertTestDefinition(lastMatch, opts.groupmarker.end))), insertTestDefinition(currentToken, m);
            }
            return currentToken.matches.length > 0 && (lastMatch = currentToken.matches[currentToken.matches.length - 1], 
            lastMatch.isGroup && (lastMatch.isGroup = !1, insertTestDefinition(lastMatch, opts.groupmarker.start, 0), 
            insertTestDefinition(lastMatch, opts.groupmarker.end)), maskTokens.push(currentToken)), 
            maskTokens;
        }
        function generateMask(mask, metadata) {
            if (void 0 == mask || "" == mask) return void 0;
            if (1 == mask.length && 0 == opts.greedy && 0 != opts.repeat && (opts.placeholder = ""), 
            opts.repeat > 0 || "*" == opts.repeat || "+" == opts.repeat) {
                var repeatStart = "*" == opts.repeat ? 0 : "+" == opts.repeat ? 1 : opts.repeat;
                mask = opts.groupmarker.start + mask + opts.groupmarker.end + opts.quantifiermarker.start + repeatStart + "," + opts.repeat + opts.quantifiermarker.end;
            }
            var masksetDefinition;
            return void 0 == $.inputmask.masksCache[mask] || nocache === !0 ? (masksetDefinition = {
                mask: mask,
                maskToken: analyseMask(mask),
                validPositions: {},
                _buffer: void 0,
                buffer: void 0,
                tests: {},
                metadata: metadata
            }, nocache !== !0 && ($.inputmask.masksCache[mask] = masksetDefinition)) : masksetDefinition = $.extend(!0, {}, $.inputmask.masksCache[mask]), 
            masksetDefinition;
        }
        function preProcessMask(mask) {
            if (mask = mask.toString(), opts.numericInput) {
                mask = mask.split("").reverse();
                for (var ndx = 0; ndx < mask.length; ndx++) mask[ndx] == opts.optionalmarker.start ? mask[ndx] = opts.optionalmarker.end : mask[ndx] == opts.optionalmarker.end ? mask[ndx] = opts.optionalmarker.start : mask[ndx] == opts.groupmarker.start ? mask[ndx] = opts.groupmarker.end : mask[ndx] == opts.groupmarker.end && (mask[ndx] = opts.groupmarker.start);
                mask = mask.join("");
            }
            return mask;
        }
        var ms = void 0;
        if ($.isFunction(opts.mask) && (opts.mask = opts.mask.call(this, opts)), 
        $.isArray(opts.mask)) {
            if (opts.mask.length > 1) {
                opts.keepStatic = void 0 == opts.keepStatic ? !0 : opts.keepStatic;
                var altMask = "(";
                return $.each(opts.mask, function(ndx, msk) {
                    altMask.length > 1 && (altMask += ")|("), altMask += preProcessMask(void 0 == msk.mask || $.isFunction(msk.mask) ? msk : msk.mask);
                }), altMask += ")", generateMask(altMask, opts.mask);
            }
            opts.mask = opts.mask.pop();
        }
        return opts.mask && (ms = void 0 == opts.mask.mask || $.isFunction(opts.mask.mask) ? generateMask(preProcessMask(opts.mask), opts.mask) : generateMask(preProcessMask(opts.mask.mask), opts.mask)), 
        ms;
    }
    function maskScope(actionObj, maskset, opts) {
        function getMaskTemplate(baseOnInput, minimalPos, includeInput) {
            minimalPos = minimalPos || 0;
            var ndxIntlzr, test, testPos, maskTemplate = [], pos = 0;
            do {
                if (baseOnInput === !0 && getMaskSet().validPositions[pos]) {
                    var validPos = getMaskSet().validPositions[pos];
                    test = validPos.match, ndxIntlzr = validPos.locator.slice(), 
                    maskTemplate.push(includeInput === !0 ? validPos.input : getPlaceholder(pos, test));
                } else testPos = getTestTemplate(pos, ndxIntlzr, pos - 1), test = testPos.match, 
                ndxIntlzr = testPos.locator.slice(), maskTemplate.push(getPlaceholder(pos, test));
                pos++;
            } while ((void 0 == maxLength || maxLength > pos - 1) && null != test.fn || null == test.fn && "" != test.def || minimalPos >= pos);
            return maskTemplate.pop(), maskTemplate;
        }
        function getMaskSet() {
            return maskset;
        }
        function resetMaskSet(soft) {
            var maskset = getMaskSet();
            maskset.buffer = void 0, maskset.tests = {}, soft !== !0 && (maskset._buffer = void 0, 
            maskset.validPositions = {}, maskset.p = 0);
        }
        function getLastValidPosition(closestTo, strict) {
            var maskset = getMaskSet(), lastValidPosition = -1, valids = maskset.validPositions;
            void 0 == closestTo && (closestTo = -1);
            var before = lastValidPosition, after = lastValidPosition;
            for (var posNdx in valids) {
                var psNdx = parseInt(posNdx);
                valids[psNdx] && (strict || null != valids[psNdx].match.fn) && (closestTo >= psNdx && (before = psNdx), 
                psNdx >= closestTo && (after = psNdx));
            }
            return lastValidPosition = -1 != before && closestTo - before > 1 || closestTo > after ? before : after;
        }
        function setValidPosition(pos, validTest, fromSetValid) {
            if (opts.insertMode && void 0 != getMaskSet().validPositions[pos] && void 0 == fromSetValid) {
                var i, positionsClone = $.extend(!0, {}, getMaskSet().validPositions), lvp = getLastValidPosition();
                for (i = pos; lvp >= i; i++) delete getMaskSet().validPositions[i];
                getMaskSet().validPositions[pos] = validTest;
                var j, valid = !0, vps = getMaskSet().validPositions;
                for (i = j = pos; lvp >= i; i++) {
                    var t = positionsClone[i];
                    if (void 0 != t) for (var posMatch = j, prevPosMatch = -1; posMatch < getMaskLength() && (null == t.match.fn && vps[i] && (vps[i].match.optionalQuantifier === !0 || vps[i].match.optionality === !0) || null != t.match.fn); ) {
                        if (null == t.match.fn || !opts.keepStatic && vps[i] && (void 0 != vps[i + 1] && getTests(i + 1, vps[i].locator.slice(), i).length > 1 || void 0 != vps[i].alternation) ? posMatch++ : posMatch = seekNext(j), 
                        positionCanMatchDefinition(posMatch, t.match.def)) {
                            valid = isValid(posMatch, t.input, !0, !0) !== !1, j = posMatch;
                            break;
                        }
                        if (valid = null == t.match.fn, prevPosMatch == posMatch) break;
                        prevPosMatch = posMatch;
                    }
                    if (!valid) break;
                }
                if (!valid) return getMaskSet().validPositions = $.extend(!0, {}, positionsClone), 
                !1;
            } else getMaskSet().validPositions[pos] = validTest;
            return !0;
        }
        function stripValidPositions(start, end, nocheck, strict) {
            var i, startPos = start;
            getMaskSet().p = start, void 0 != getMaskSet().validPositions[start] && getMaskSet().validPositions[start].input == opts.radixPoint && (end++, 
            startPos++);
            for (i = startPos; end > i; i++) void 0 != getMaskSet().validPositions[i] && (nocheck === !0 || 0 != opts.canClearPosition(getMaskSet(), i, getLastValidPosition(), strict, opts)) && delete getMaskSet().validPositions[i];
            for (resetMaskSet(!0), i = startPos + 1; i <= getLastValidPosition(); ) {
                for (;void 0 != getMaskSet().validPositions[startPos]; ) startPos++;
                var s = getMaskSet().validPositions[startPos];
                startPos > i && (i = startPos + 1);
                var t = getMaskSet().validPositions[i];
                void 0 != t && void 0 == s ? (positionCanMatchDefinition(startPos, t.match.def) && isValid(startPos, t.input, !0) !== !1 && (delete getMaskSet().validPositions[i], 
                i++), startPos++) : i++;
            }
            var lvp = getLastValidPosition(), ml = getMaskLength();
            for (lvp >= start && void 0 != getMaskSet().validPositions[lvp] && getMaskSet().validPositions[lvp].input == opts.radixPoint && delete getMaskSet().validPositions[lvp], 
            i = lvp + 1; ml >= i; i++) getMaskSet().validPositions[i] && delete getMaskSet().validPositions[i];
            resetMaskSet(!0);
        }
        function getTestTemplate(pos, ndxIntlzr, tstPs) {
            var testPos = getMaskSet().validPositions[pos];
            if (void 0 == testPos) for (var testPositions = getTests(pos, ndxIntlzr, tstPs), lvp = getLastValidPosition(), lvTest = getMaskSet().validPositions[lvp] || getTests(0)[0], lvTestAltArr = void 0 != lvTest.alternation ? lvTest.locator[lvTest.alternation].toString().split(",") : [], ndx = 0; ndx < testPositions.length && (testPos = testPositions[ndx], 
            !(testPos.match && (opts.greedy && testPos.match.optionalQuantifier !== !0 || (testPos.match.optionality === !1 || testPos.match.newBlockMarker === !1) && testPos.match.optionalQuantifier !== !0) && (void 0 == lvTest.alternation || lvTest.alternation != testPos.alternation || void 0 != testPos.locator[lvTest.alternation] && checkAlternationMatch(testPos.locator[lvTest.alternation].toString().split(","), lvTestAltArr)))); ndx++);
            return testPos;
        }
        function getTest(pos) {
            return getMaskSet().validPositions[pos] ? getMaskSet().validPositions[pos].match : getTests(pos)[0].match;
        }
        function positionCanMatchDefinition(pos, def) {
            for (var valid = !1, tests = getTests(pos), tndx = 0; tndx < tests.length; tndx++) if (tests[tndx].match && tests[tndx].match.def == def) {
                valid = !0;
                break;
            }
            return valid;
        }
        function getTests(pos, ndxIntlzr, tstPs, cacheable) {
            function ResolveTestFromToken(maskToken, ndxInitializer, loopNdx, quantifierRecurse) {
                function handleMatch(match, loopNdx, quantifierRecurse) {
                    if (testPos > 1e4) return alert("jquery.inputmask: There is probably an error in your mask definition or in the code. Create an issue on github with an example of the mask you are using. " + getMaskSet().mask), 
                    !0;
                    if (testPos == pos && void 0 == match.matches) return matches.push({
                        match: match,
                        locator: loopNdx.reverse()
                    }), !0;
                    if (void 0 != match.matches) {
                        if (match.isGroup && quantifierRecurse !== !0) {
                            if (match = handleMatch(maskToken.matches[tndx + 1], loopNdx)) return !0;
                        } else if (match.isOptional) {
                            var optionalToken = match;
                            if (match = ResolveTestFromToken(match, ndxInitializer, loopNdx, quantifierRecurse)) {
                                var latestMatch = matches[matches.length - 1].match, isFirstMatch = 0 == $.inArray(latestMatch, optionalToken.matches);
                                if (!isFirstMatch) return !0;
                                insertStop = !0, testPos = pos;
                            }
                        } else if (match.isAlternator) {
                            var maltMatches, alternateToken = match, malternateMatches = [], currentMatches = matches.slice(), loopNdxCnt = loopNdx.length, altIndex = ndxInitializer.length > 0 ? ndxInitializer.shift() : -1;
                            if (-1 == altIndex || "string" == typeof altIndex) {
                                var currentPos = testPos, ndxInitializerClone = ndxInitializer.slice(), altIndexArr = [];
                                "string" == typeof altIndex && (altIndexArr = altIndex.split(","));
                                for (var amndx = 0; amndx < alternateToken.matches.length; amndx++) {
                                    if (matches = [], match = handleMatch(alternateToken.matches[amndx], [ amndx ].concat(loopNdx), quantifierRecurse) || match, 
                                    match !== !0 && void 0 != match && altIndexArr[altIndexArr.length - 1] < alternateToken.matches.length) {
                                        var ntndx = maskToken.matches.indexOf(match) + 1;
                                        maskToken.matches.length > ntndx && (match = handleMatch(maskToken.matches[ntndx], [ ntndx ].concat(loopNdx.slice(1, loopNdx.length)), quantifierRecurse), 
                                        match && (altIndexArr.push(ntndx.toString()), 
                                        $.each(matches, function(ndx, lmnt) {
                                            lmnt.alternation = loopNdx.length - 1;
                                        })));
                                    }
                                    maltMatches = matches.slice(), testPos = currentPos, 
                                    matches = [];
                                    for (var i = 0; i < ndxInitializerClone.length; i++) ndxInitializer[i] = ndxInitializerClone[i];
                                    for (var ndx1 = 0; ndx1 < maltMatches.length; ndx1++) {
                                        var altMatch = maltMatches[ndx1];
                                        altMatch.alternation = altMatch.alternation || loopNdxCnt;
                                        for (var ndx2 = 0; ndx2 < malternateMatches.length; ndx2++) {
                                            var altMatch2 = malternateMatches[ndx2];
                                            if (altMatch.match.mask == altMatch2.match.mask && ("string" != typeof altIndex || -1 != $.inArray(altMatch.locator[altMatch.alternation].toString(), altIndexArr))) {
                                                maltMatches.splice(ndx1, 1), ndx1--, 
                                                altMatch2.locator[altMatch.alternation] = altMatch2.locator[altMatch.alternation] + "," + altMatch.locator[altMatch.alternation], 
                                                altMatch2.alternation = altMatch.alternation;
                                                break;
                                            }
                                        }
                                    }
                                    malternateMatches = malternateMatches.concat(maltMatches);
                                }
                                "string" == typeof altIndex && (malternateMatches = $.map(malternateMatches, function(lmnt, ndx) {
                                    if (isFinite(ndx)) {
                                        var mamatch, alternation = lmnt.alternation, altLocArr = lmnt.locator[alternation].toString().split(",");
                                        lmnt.locator[alternation] = void 0, lmnt.alternation = void 0;
                                        for (var alndx = 0; alndx < altLocArr.length; alndx++) mamatch = -1 != $.inArray(altLocArr[alndx], altIndexArr), 
                                        mamatch && (void 0 != lmnt.locator[alternation] ? (lmnt.locator[alternation] += ",", 
                                        lmnt.locator[alternation] += altLocArr[alndx]) : lmnt.locator[alternation] = parseInt(altLocArr[alndx]), 
                                        lmnt.alternation = alternation);
                                        if (void 0 != lmnt.locator[alternation]) return lmnt;
                                    }
                                })), matches = currentMatches.concat(malternateMatches), 
                                testPos = pos, insertStop = matches.length > 0;
                            } else match = alternateToken.matches[altIndex] ? handleMatch(alternateToken.matches[altIndex], [ altIndex ].concat(loopNdx), quantifierRecurse) : !1;
                            if (match) return !0;
                        } else if (match.isQuantifier && quantifierRecurse !== !0) for (var qt = match, qndx = ndxInitializer.length > 0 && quantifierRecurse !== !0 ? ndxInitializer.shift() : 0; qndx < (isNaN(qt.quantifier.max) ? qndx + 1 : qt.quantifier.max) && pos >= testPos; qndx++) {
                            var tokenGroup = maskToken.matches[$.inArray(qt, maskToken.matches) - 1];
                            if (match = handleMatch(tokenGroup, [ qndx ].concat(loopNdx), !0)) {
                                var latestMatch = matches[matches.length - 1].match;
                                latestMatch.optionalQuantifier = qndx > qt.quantifier.min - 1;
                                var isFirstMatch = 0 == $.inArray(latestMatch, tokenGroup.matches);
                                if (isFirstMatch) {
                                    if (qndx > qt.quantifier.min - 1) {
                                        insertStop = !0, testPos = pos;
                                        break;
                                    }
                                    return !0;
                                }
                                return !0;
                            }
                        } else if (match = ResolveTestFromToken(match, ndxInitializer, loopNdx, quantifierRecurse)) return !0;
                    } else testPos++;
                }
                for (var tndx = ndxInitializer.length > 0 ? ndxInitializer.shift() : 0; tndx < maskToken.matches.length; tndx++) if (maskToken.matches[tndx].isQuantifier !== !0) {
                    var match = handleMatch(maskToken.matches[tndx], [ tndx ].concat(loopNdx), quantifierRecurse);
                    if (match && testPos == pos) return match;
                    if (testPos > pos) break;
                }
            }
            var maskTokens = getMaskSet().maskToken, testPos = ndxIntlzr ? tstPs : 0, ndxInitializer = ndxIntlzr || [ 0 ], matches = [], insertStop = !1;
            if (cacheable === !0 && getMaskSet().tests[pos]) return getMaskSet().tests[pos];
            if (void 0 == ndxIntlzr) {
                for (var test, previousPos = pos - 1; void 0 == (test = getMaskSet().validPositions[previousPos]) && previousPos > -1 && (!getMaskSet().tests[previousPos] || void 0 == (test = getMaskSet().tests[previousPos][0])); ) previousPos--;
                void 0 != test && previousPos > -1 && (testPos = previousPos, ndxInitializer = test.locator.slice());
            }
            for (var mtndx = ndxInitializer.shift(); mtndx < maskTokens.length; mtndx++) {
                var match = ResolveTestFromToken(maskTokens[mtndx], ndxInitializer, [ mtndx ]);
                if (match && testPos == pos || testPos > pos) break;
            }
            return (0 == matches.length || insertStop) && matches.push({
                match: {
                    fn: null,
                    cardinality: 0,
                    optionality: !0,
                    casing: null,
                    def: ""
                },
                locator: []
            }), getMaskSet().tests[pos] = $.extend(!0, [], matches), getMaskSet().tests[pos];
        }
        function getBufferTemplate() {
            return void 0 == getMaskSet()._buffer && (getMaskSet()._buffer = getMaskTemplate(!1, 1)), 
            getMaskSet()._buffer;
        }
        function getBuffer() {
            return void 0 == getMaskSet().buffer && (getMaskSet().buffer = getMaskTemplate(!0, getLastValidPosition(), !0)), 
            getMaskSet().buffer;
        }
        function refreshFromBuffer(start, end, buffer) {
            if (buffer = buffer || getBuffer().slice(), start === !0) resetMaskSet(), 
            start = 0, end = buffer.length; else for (var i = start; end > i; i++) delete getMaskSet().validPositions[i], 
            delete getMaskSet().tests[i];
            for (var i = start; end > i; i++) buffer[i] != opts.skipOptionalPartCharacter && isValid(i, buffer[i], !0, !0);
        }
        function casing(elem, test) {
            switch (test.casing) {
              case "upper":
                elem = elem.toUpperCase();
                break;

              case "lower":
                elem = elem.toLowerCase();
            }
            return elem;
        }
        function checkAlternationMatch(altArr1, altArr2) {
            for (var altArrC = opts.greedy ? altArr2 : altArr2.slice(0, 1), isMatch = !1, alndx = 0; alndx < altArr1.length; alndx++) if (-1 != $.inArray(altArr1[alndx], altArrC)) {
                isMatch = !0;
                break;
            }
            return isMatch;
        }
        function isValid(pos, c, strict, fromSetValid) {
            function _isValid(position, c, strict, fromSetValid) {
                var rslt = !1;
                return $.each(getTests(position), function(ndx, tst) {
                    for (var test = tst.match, loopend = c ? 1 : 0, chrs = "", i = (getBuffer(), 
                    test.cardinality); i > loopend; i--) chrs += getBufferElement(position - (i - 1));
                    if (c && (chrs += c), rslt = null != test.fn ? test.fn.test(chrs, getMaskSet(), position, strict, opts) : c != test.def && c != opts.skipOptionalPartCharacter || "" == test.def ? !1 : {
                        c: test.def,
                        pos: position
                    }, rslt !== !1) {
                        var elem = void 0 != rslt.c ? rslt.c : c;
                        elem = elem == opts.skipOptionalPartCharacter && null === test.fn ? test.def : elem;
                        var validatedPos = position, possibleModifiedBuffer = getBuffer();
                        if (void 0 != rslt.remove && ($.isArray(rslt.remove) || (rslt.remove = [ rslt.remove ]), 
                        $.each(rslt.remove.sort(function(a, b) {
                            return b - a;
                        }), function(ndx, lmnt) {
                            stripValidPositions(lmnt, lmnt + 1, !0);
                        })), void 0 != rslt.insert && ($.isArray(rslt.insert) || (rslt.insert = [ rslt.insert ]), 
                        $.each(rslt.insert.sort(function(a, b) {
                            return a - b;
                        }), function(ndx, lmnt) {
                            isValid(lmnt.pos, lmnt.c, !0);
                        })), rslt.refreshFromBuffer) {
                            var refresh = rslt.refreshFromBuffer;
                            if (strict = !0, refreshFromBuffer(refresh === !0 ? refresh : refresh.start, refresh.end, possibleModifiedBuffer), 
                            void 0 == rslt.pos && void 0 == rslt.c) return rslt.pos = getLastValidPosition(), 
                            !1;
                            if (validatedPos = void 0 != rslt.pos ? rslt.pos : position, 
                            validatedPos != position) return rslt = $.extend(rslt, isValid(validatedPos, elem, !0)), 
                            !1;
                        } else if (rslt !== !0 && void 0 != rslt.pos && rslt.pos != position && (validatedPos = rslt.pos, 
                        refreshFromBuffer(position, validatedPos), validatedPos != position)) return rslt = $.extend(rslt, isValid(validatedPos, elem, !0)), 
                        !1;
                        return 1 != rslt && void 0 == rslt.pos && void 0 == rslt.c ? !1 : (ndx > 0 && resetMaskSet(!0), 
                        setValidPosition(validatedPos, $.extend({}, tst, {
                            input: casing(elem, test)
                        }), fromSetValid) || (rslt = !1), !1);
                    }
                }), rslt;
            }
            function alternate(pos, c, strict, fromSetValid) {
                for (var lastAlt, alternation, isValidRslt, altPos, validPsClone = $.extend(!0, {}, getMaskSet().validPositions), lAlt = getLastValidPosition(); lAlt >= 0 && (altPos = getMaskSet().validPositions[lAlt], 
                !altPos || void 0 == altPos.alternation || (lastAlt = lAlt, alternation = getMaskSet().validPositions[lastAlt].alternation, 
                getTestTemplate(lastAlt).locator[altPos.alternation] == altPos.locator[altPos.alternation])); lAlt--);
                if (void 0 != alternation) for (var decisionPos in getMaskSet().validPositions) if (altPos = getMaskSet().validPositions[decisionPos], 
                parseInt(decisionPos) > parseInt(lastAlt) && void 0 != altPos.alternation) {
                    var altNdxs = getMaskSet().validPositions[lastAlt].locator[alternation].toString().split(","), decisionTaker = altPos.locator[alternation] || altNdxs[0];
                    decisionTaker.length > 0 && (decisionTaker = decisionTaker.split(",")[0]);
                    for (var mndx = 0; mndx < altNdxs.length; mndx++) if (decisionTaker < altNdxs[mndx]) {
                        for (var possibilityPos, possibilities, dp = decisionPos - 1; dp >= 0; dp--) if (possibilityPos = getMaskSet().validPositions[dp], 
                        void 0 != possibilityPos) {
                            possibilities = possibilityPos.locator[alternation], 
                            possibilityPos.locator[alternation] = parseInt(altNdxs[mndx]);
                            break;
                        }
                        if (decisionTaker != possibilityPos.locator[alternation]) {
                            for (var validInputs = [], i = decisionPos; i < getLastValidPosition() + 1; i++) {
                                var validPos = getMaskSet().validPositions[i];
                                validPos && null != validPos.match.fn && validInputs.push(validPos.input), 
                                delete getMaskSet().validPositions[i], delete getMaskSet().tests[i];
                            }
                            for (resetMaskSet(!0), opts.keepStatic = !opts.keepStatic, 
                            isValidRslt = !0; validInputs.length > 0; ) {
                                var input = validInputs.shift();
                                if (input != opts.skipOptionalPartCharacter && !(isValidRslt = isValid(getLastValidPosition() + 1, input, !1, !0))) break;
                            }
                            if (possibilityPos.alternation = alternation, possibilityPos.locator[alternation] = possibilities, 
                            isValidRslt) {
                                var targetLvp = getLastValidPosition(pos) + 1;
                                isValidRslt = isValid(pos > targetLvp ? targetLvp : pos, c, strict, fromSetValid);
                            }
                            if (opts.keepStatic = !opts.keepStatic, isValidRslt) return isValidRslt;
                            resetMaskSet(), getMaskSet().validPositions = $.extend(!0, {}, validPsClone);
                        }
                    }
                    break;
                }
                return !1;
            }
            function trackbackAlternations(originalPos, newPos) {
                for (var vp = getMaskSet().validPositions[newPos], targetLocator = vp.locator, tll = targetLocator.length, ps = originalPos; newPos > ps; ps++) if (!isMask(ps)) {
                    var tests = getTests(ps), bestMatch = tests[0], equality = -1;
                    $.each(tests, function(ndx, tst) {
                        for (var i = 0; tll > i; i++) tst.locator[i] && checkAlternationMatch(tst.locator[i].toString().split(","), targetLocator[i].toString().split(",")) && i > equality && (equality = i, 
                        bestMatch = tst);
                    }), setValidPosition(ps, $.extend({}, bestMatch, {
                        input: bestMatch.match.def
                    }), !0);
                }
            }
            strict = strict === !0;
            for (var buffer = getBuffer(), pndx = pos - 1; pndx > -1 && !getMaskSet().validPositions[pndx]; pndx--);
            for (pndx++; pos > pndx; pndx++) void 0 == getMaskSet().validPositions[pndx] && ((!isMask(pndx) || buffer[pndx] != getPlaceholder(pndx)) && getTests(pndx).length > 1 || buffer[pndx] == opts.radixPoint || "0" == buffer[pndx] && $.inArray(opts.radixPoint, buffer) < pndx) && _isValid(pndx, buffer[pndx], !0);
            var maskPos = pos, result = !1, positionsClone = $.extend(!0, {}, getMaskSet().validPositions);
            if (maskPos < getMaskLength() && (result = _isValid(maskPos, c, strict, fromSetValid), 
            (!strict || fromSetValid) && result === !1)) {
                var currentPosValid = getMaskSet().validPositions[maskPos];
                if (!currentPosValid || null != currentPosValid.match.fn || currentPosValid.match.def != c && c != opts.skipOptionalPartCharacter) {
                    if ((opts.insertMode || void 0 == getMaskSet().validPositions[seekNext(maskPos)]) && !isMask(maskPos)) for (var nPos = maskPos + 1, snPos = seekNext(maskPos); snPos >= nPos; nPos++) if (result = _isValid(nPos, c, strict, fromSetValid), 
                    result !== !1) {
                        trackbackAlternations(maskPos, nPos), maskPos = nPos;
                        break;
                    }
                } else result = {
                    caret: seekNext(maskPos)
                };
            }
            if (result === !1 && opts.keepStatic && isComplete(buffer) && (result = alternate(pos, c, strict, fromSetValid)), 
            result === !0 && (result = {
                pos: maskPos
            }), $.isFunction(opts.postValidation) && 0 != result && !strict) {
                resetMaskSet(!0);
                var postValidResult = opts.postValidation(getBuffer(), opts);
                if (!postValidResult) return resetMaskSet(!0), getMaskSet().validPositions = $.extend(!0, {}, positionsClone), 
                !1;
            }
            return result;
        }
        function isMask(pos) {
            var test = getTest(pos);
            if (null != test.fn) return test.fn;
            if (!opts.keepStatic && void 0 == getMaskSet().validPositions[pos]) {
                for (var tests = getTests(pos), staticAlternations = !0, i = 0; i < tests.length; i++) if ("" != tests[i].match.def && (void 0 == tests[i].alternation || tests[i].locator[tests[i].alternation].length > 1)) {
                    staticAlternations = !1;
                    break;
                }
                return staticAlternations;
            }
            return !1;
        }
        function getMaskLength() {
            var maskLength;
            maxLength = $el.prop("maxLength"), -1 == maxLength && (maxLength = void 0);
            var pos, lvp = getLastValidPosition(), testPos = getMaskSet().validPositions[lvp], ndxIntlzr = void 0 != testPos ? testPos.locator.slice() : void 0;
            for (pos = lvp + 1; void 0 == testPos || null != testPos.match.fn || null == testPos.match.fn && "" != testPos.match.def; pos++) testPos = getTestTemplate(pos, ndxIntlzr, pos - 1), 
            ndxIntlzr = testPos.locator.slice();
            var lastTest = getTest(pos - 1);
            return maskLength = "" != lastTest.def ? pos : pos - 1, void 0 == maxLength || maxLength > maskLength ? maskLength : maxLength;
        }
        function seekNext(pos) {
            var maskL = getMaskLength();
            if (pos >= maskL) return maskL;
            for (var position = pos; ++position < maskL && !isMask(position) && (opts.nojumps !== !0 || opts.nojumpsThreshold > position); );
            return position;
        }
        function seekPrevious(pos) {
            var position = pos;
            if (0 >= position) return 0;
            for (;--position > 0 && !isMask(position); );
            return position;
        }
        function getBufferElement(position) {
            return void 0 == getMaskSet().validPositions[position] ? getPlaceholder(position) : getMaskSet().validPositions[position].input;
        }
        function writeBuffer(input, buffer, caretPos, event, triggerInputEvent) {
            if (event && $.isFunction(opts.onBeforeWrite)) {
                var result = opts.onBeforeWrite.call(input, event, buffer, caretPos, opts);
                if (result) {
                    if (result.refreshFromBuffer) {
                        var refresh = result.refreshFromBuffer;
                        refreshFromBuffer(refresh === !0 ? refresh : refresh.start, refresh.end, result.buffer), 
                        resetMaskSet(!0), buffer = getBuffer();
                    }
                    caretPos = result.caret || caretPos;
                }
            }
            input._valueSet(buffer.join("")), void 0 != caretPos && caret(input, caretPos), 
            triggerInputEvent === !0 && (skipInputEvent = !0, $(input).trigger("input"));
        }
        function getPlaceholder(pos, test) {
            if (test = test || getTest(pos), void 0 != test.placeholder) return test.placeholder;
            if (null == test.fn) {
                if (!opts.keepStatic && void 0 == getMaskSet().validPositions[pos]) {
                    for (var tests = getTests(pos), staticAlternations = !0, i = 0; i < tests.length; i++) if ("" != tests[i].match.def && (null !== tests[i].match.fn || void 0 == tests[i].alternation || tests[i].locator[tests[i].alternation].length > 1)) {
                        staticAlternations = !1;
                        break;
                    }
                    if (staticAlternations) return opts.placeholder.charAt(pos % opts.placeholder.length);
                }
                return test.def;
            }
            return opts.placeholder.charAt(pos % opts.placeholder.length);
        }
        function checkVal(input, writeOut, strict, nptvl) {
            function isTemplateMatch() {
                var isMatch = !1, charCodeNdx = getBufferTemplate().slice(initialNdx, seekNext(initialNdx)).join("").indexOf(charCodes);
                if (-1 != charCodeNdx && !isMask(initialNdx)) {
                    isMatch = !0;
                    for (var bufferTemplateArr = getBufferTemplate().slice(initialNdx, initialNdx + charCodeNdx), i = 0; i < bufferTemplateArr.length; i++) if (" " != bufferTemplateArr[i]) {
                        isMatch = !1;
                        break;
                    }
                }
                return isMatch;
            }
            var inputValue = void 0 != nptvl ? nptvl.slice() : input._valueGet().split(""), charCodes = "", initialNdx = 0;
            if (resetMaskSet(), getMaskSet().p = seekNext(-1), writeOut && input._valueSet(""), 
            !strict) {
                var staticInput = getBufferTemplate().slice(0, seekNext(-1)).join(""), matches = inputValue.join("").match(new RegExp("^" + escapeRegex(staticInput), "g"));
                matches && matches.length > 0 && (inputValue.splice(0, matches.length * staticInput.length), 
                initialNdx = seekNext(initialNdx));
            }
            $.each(inputValue, function(ndx, charCode) {
                var keypress = $.Event("keypress");
                keypress.which = charCode.charCodeAt(0), charCodes += charCode;
                var lvp = getLastValidPosition(void 0, !0), lvTest = getMaskSet().validPositions[lvp], nextTest = getTestTemplate(lvp + 1, lvTest ? lvTest.locator.slice() : void 0, lvp);
                if (!isTemplateMatch() || strict) {
                    var pos = strict ? ndx : null == nextTest.match.fn && nextTest.match.optionality && lvp + 1 < getMaskSet().p ? lvp + 1 : getMaskSet().p;
                    keypressEvent.call(input, keypress, !0, !1, strict, pos), initialNdx = pos + 1, 
                    charCodes = "";
                } else keypressEvent.call(input, keypress, !0, !1, !0, lvp + 1);
            }), writeOut && writeBuffer(input, getBuffer(), $(input).is(":focus") ? seekNext(getLastValidPosition(0)) : void 0, $.Event("checkval"));
        }
        function escapeRegex(str) {
            return $.inputmask.escapeRegex(str);
        }
        function unmaskedvalue($input) {
            if ($input.data("_inputmask") && !$input.hasClass("hasDatepicker")) {
                var umValue = [], vps = getMaskSet().validPositions;
                for (var pndx in vps) vps[pndx].match && null != vps[pndx].match.fn && umValue.push(vps[pndx].input);
                var unmaskedValue = (isRTL ? umValue.reverse() : umValue).join(""), bufferValue = (isRTL ? getBuffer().slice().reverse() : getBuffer()).join("");
                return $.isFunction(opts.onUnMask) && (unmaskedValue = opts.onUnMask.call($input, bufferValue, unmaskedValue, opts) || unmaskedValue), 
                unmaskedValue;
            }
            return $input[0]._valueGet();
        }
        function TranslatePosition(pos) {
            if (isRTL && "number" == typeof pos && (!opts.greedy || "" != opts.placeholder)) {
                var bffrLght = getBuffer().length;
                pos = bffrLght - pos;
            }
            return pos;
        }
        function caret(input, begin, end) {
            var range, npt = input.jquery && input.length > 0 ? input[0] : input;
            if ("number" != typeof begin) return npt.setSelectionRange ? (begin = npt.selectionStart, 
            end = npt.selectionEnd) : window.getSelection ? (range = window.getSelection().getRangeAt(0), 
            (range.commonAncestorContainer.parentNode == npt || range.commonAncestorContainer == npt) && (begin = range.startOffset, 
            end = range.endOffset)) : document.selection && document.selection.createRange && (range = document.selection.createRange(), 
            begin = 0 - range.duplicate().moveStart("character", -1e5), end = begin + range.text.length), 
            {
                begin: TranslatePosition(begin),
                end: TranslatePosition(end)
            };
            if (begin = TranslatePosition(begin), end = TranslatePosition(end), 
            end = "number" == typeof end ? end : begin, $(npt).is(":visible")) {
                var scrollCalc = $(npt).css("font-size").replace("px", "") * end;
                if (npt.scrollLeft = scrollCalc > npt.scrollWidth ? scrollCalc : 0, 
                androidchrome || 0 != opts.insertMode || begin != end || end++, 
                npt.setSelectionRange) npt.selectionStart = begin, npt.selectionEnd = end; else if (window.getSelection) {
                    if (range = document.createRange(), void 0 == npt.firstChild) {
                        var textNode = document.createTextNode("");
                        npt.appendChild(textNode);
                    }
                    range.setStart(npt.firstChild, begin < npt._valueGet().length ? begin : npt._valueGet().length), 
                    range.setEnd(npt.firstChild, end < npt._valueGet().length ? end : npt._valueGet().length), 
                    range.collapse(!0);
                    var sel = window.getSelection();
                    sel.removeAllRanges(), sel.addRange(range);
                } else npt.createTextRange && (range = npt.createTextRange(), range.collapse(!0), 
                range.moveEnd("character", end), range.moveStart("character", begin), 
                range.select());
            }
        }
        function determineLastRequiredPosition(returnDefinition) {
            var pos, testPos, buffer = getBuffer(), bl = buffer.length, lvp = getLastValidPosition(), positions = {}, lvTest = getMaskSet().validPositions[lvp], ndxIntlzr = void 0 != lvTest ? lvTest.locator.slice() : void 0;
            for (pos = lvp + 1; pos < buffer.length; pos++) testPos = getTestTemplate(pos, ndxIntlzr, pos - 1), 
            ndxIntlzr = testPos.locator.slice(), positions[pos] = $.extend(!0, {}, testPos);
            var lvTestAlt = lvTest && void 0 != lvTest.alternation ? lvTest.locator[lvTest.alternation] : void 0;
            for (pos = bl - 1; pos > lvp && (testPos = positions[pos], (testPos.match.optionality || testPos.match.optionalQuantifier || lvTestAlt && (lvTestAlt != positions[pos].locator[lvTest.alternation] && null != testPos.match.fn || null == testPos.match.fn && testPos.locator[lvTest.alternation] && checkAlternationMatch(testPos.locator[lvTest.alternation].toString().split(","), lvTestAlt.split(",")) && "" != getTests(pos)[0].def)) && buffer[pos] == getPlaceholder(pos, testPos.match)); pos--) bl--;
            return returnDefinition ? {
                l: bl,
                def: positions[bl] ? positions[bl].match : void 0
            } : bl;
        }
        function clearOptionalTail(buffer) {
            for (var rl = determineLastRequiredPosition(), lmib = buffer.length - 1; lmib > rl && !isMask(lmib); lmib--);
            return buffer.splice(rl, lmib + 1 - rl), buffer;
        }
        function isComplete(buffer) {
            if ($.isFunction(opts.isComplete)) return opts.isComplete.call($el, buffer, opts);
            if ("*" == opts.repeat) return void 0;
            {
                var complete = !1, lrp = determineLastRequiredPosition(!0), aml = seekPrevious(lrp.l);
                getLastValidPosition();
            }
            if (void 0 == lrp.def || lrp.def.newBlockMarker || lrp.def.optionality || lrp.def.optionalQuantifier) {
                complete = !0;
                for (var i = 0; aml >= i; i++) {
                    var test = getTestTemplate(i).match;
                    if (null != test.fn && void 0 == getMaskSet().validPositions[i] && test.optionality !== !0 && test.optionalQuantifier !== !0 || null == test.fn && buffer[i] != getPlaceholder(i, test)) {
                        complete = !1;
                        break;
                    }
                }
            }
            return complete;
        }
        function isSelection(begin, end) {
            return isRTL ? begin - end > 1 || begin - end == 1 && opts.insertMode : end - begin > 1 || end - begin == 1 && opts.insertMode;
        }
        function installEventRuler(npt) {
            var events = $._data(npt).events, inComposition = !1;
            $.each(events, function(eventType, eventHandlers) {
                $.each(eventHandlers, function(ndx, eventHandler) {
                    if ("inputmask" == eventHandler.namespace && "setvalue" != eventHandler.type) {
                        var handler = eventHandler.handler;
                        eventHandler.handler = function(e) {
                            if (!(this.disabled || this.readOnly && !("keydown" == e.type && e.ctrlKey && 67 == e.keyCode || e.keyCode == $.inputmask.keyCode.TAB))) {
                                switch (e.type) {
                                  case "input":
                                    if (skipInputEvent === !0 || inComposition === !0) return skipInputEvent = !1, 
                                    e.preventDefault();
                                    break;

                                  case "keydown":
                                    skipKeyPressEvent = !1, inComposition = !1;
                                    break;

                                  case "keypress":
                                    if (skipKeyPressEvent === !0) return e.preventDefault();
                                    skipKeyPressEvent = !0;
                                    break;

                                  case "compositionstart":
                                    inComposition = !0;
                                    break;

                                  case "compositionupdate":
                                    skipInputEvent = !0;
                                    break;

                                  case "compositionend":
                                    inComposition = !1;
                                }
                                return handler.apply(this, arguments);
                            }
                            e.preventDefault();
                        };
                    }
                });
            });
        }
        function patchValueProperty(npt) {
            function PatchValhook(type) {
                if (void 0 == $.valHooks[type] || 1 != $.valHooks[type].inputmaskpatch) {
                    var valhookGet = $.valHooks[type] && $.valHooks[type].get ? $.valHooks[type].get : function(elem) {
                        return elem.value;
                    }, valhookSet = $.valHooks[type] && $.valHooks[type].set ? $.valHooks[type].set : function(elem, value) {
                        return elem.value = value, elem;
                    };
                    $.valHooks[type] = {
                        get: function(elem) {
                            var $elem = $(elem);
                            if ($elem.data("_inputmask")) {
                                if ($elem.data("_inputmask").opts.autoUnmask) return $elem.inputmask("unmaskedvalue");
                                var result = valhookGet(elem), inputData = $elem.data("_inputmask"), maskset = inputData.maskset, bufferTemplate = maskset._buffer;
                                return bufferTemplate = bufferTemplate ? bufferTemplate.join("") : "", 
                                result != bufferTemplate ? result : "";
                            }
                            return valhookGet(elem);
                        },
                        set: function(elem, value) {
                            var result, $elem = $(elem), inputData = $elem.data("_inputmask");
                            return result = valhookSet(elem, value), inputData && $elem.triggerHandler("setvalue.inputmask"), 
                            result;
                        },
                        inputmaskpatch: !0
                    };
                }
            }
            function getter() {
                var $self = $(this), inputData = $(this).data("_inputmask");
                return inputData ? inputData.opts.autoUnmask ? $self.inputmask("unmaskedvalue") : valueGet.call(this) != getBufferTemplate().join("") ? valueGet.call(this) : "" : valueGet.call(this);
            }
            function setter(value) {
                var inputData = $(this).data("_inputmask");
                valueSet.call(this, value), inputData && $(this).triggerHandler("setvalue.inputmask");
            }
            function InstallNativeValueSetFallback(npt) {
                $(npt).bind("mouseenter.inputmask", function(event) {
                    var $input = $(this), input = this, value = input._valueGet();
                    "" != value && value != getBuffer().join("") && $input.triggerHandler("setvalue.inputmask");
                });
                var events = $._data(npt).events, handlers = events.mouseover;
                if (handlers) {
                    for (var ourHandler = handlers[handlers.length - 1], i = handlers.length - 1; i > 0; i--) handlers[i] = handlers[i - 1];
                    handlers[0] = ourHandler;
                }
            }
            var valueGet, valueSet;
            if (!npt._valueGet) {
                var valueProperty;
                Object.getOwnPropertyDescriptor && void 0 == npt.value ? (valueGet = function() {
                    return this.textContent;
                }, valueSet = function(value) {
                    this.textContent = value;
                }, Object.defineProperty(npt, "value", {
                    get: getter,
                    set: setter
                })) : ((valueProperty = Object.getOwnPropertyDescriptor && Object.getOwnPropertyDescriptor(npt, "value")) && valueProperty.configurable, 
                document.__lookupGetter__ && npt.__lookupGetter__("value") ? (valueGet = npt.__lookupGetter__("value"), 
                valueSet = npt.__lookupSetter__("value"), npt.__defineGetter__("value", getter), 
                npt.__defineSetter__("value", setter)) : (valueGet = function() {
                    return npt.value;
                }, valueSet = function(value) {
                    npt.value = value;
                }, PatchValhook(npt.type), InstallNativeValueSetFallback(npt))), 
                npt._valueGet = function(overruleRTL) {
                    return isRTL && overruleRTL !== !0 ? valueGet.call(this).split("").reverse().join("") : valueGet.call(this);
                }, npt._valueSet = function(value) {
                    valueSet.call(this, isRTL ? value.split("").reverse().join("") : value);
                };
            }
        }
        function handleRemove(input, k, pos, strict) {
            function generalize() {
                if (opts.keepStatic) {
                    resetMaskSet(!0);
                    var lastAlt, validInputs = [], positionsClone = $.extend(!0, {}, getMaskSet().validPositions);
                    for (lastAlt = getLastValidPosition(); lastAlt >= 0; lastAlt--) {
                        var validPos = getMaskSet().validPositions[lastAlt];
                        if (validPos) {
                            if (void 0 != validPos.alternation && validPos.locator[validPos.alternation] == getTestTemplate(lastAlt).locator[validPos.alternation]) break;
                            null != validPos.match.fn && validInputs.push(validPos.input), 
                            delete getMaskSet().validPositions[lastAlt];
                        }
                    }
                    if (lastAlt > 0) for (;validInputs.length > 0; ) {
                        getMaskSet().p = seekNext(getLastValidPosition());
                        var keypress = $.Event("keypress");
                        keypress.which = validInputs.pop().charCodeAt(0), keypressEvent.call(input, keypress, !0, !1, !1, getMaskSet().p);
                    } else getMaskSet().validPositions = $.extend(!0, {}, positionsClone);
                }
            }
            if ((opts.numericInput || isRTL) && (k == $.inputmask.keyCode.BACKSPACE ? k = $.inputmask.keyCode.DELETE : k == $.inputmask.keyCode.DELETE && (k = $.inputmask.keyCode.BACKSPACE), 
            isRTL)) {
                var pend = pos.end;
                pos.end = pos.begin, pos.begin = pend;
            }
            if (k == $.inputmask.keyCode.BACKSPACE && (pos.end - pos.begin < 1 || 0 == opts.insertMode) ? pos.begin = seekPrevious(pos.begin) : k == $.inputmask.keyCode.DELETE && pos.begin == pos.end && (pos.end = isMask(pos.end) ? pos.end + 1 : seekNext(pos.end) + 1), 
            stripValidPositions(pos.begin, pos.end, !1, strict), strict !== !0) {
                generalize();
                var lvp = getLastValidPosition(pos.begin);
                lvp < pos.begin ? (-1 == lvp && resetMaskSet(), getMaskSet().p = seekNext(lvp)) : getMaskSet().p = pos.begin;
            }
        }
        function keydownEvent(e) {
            var input = this, $input = $(input), k = e.keyCode, pos = caret(input);
            k == $.inputmask.keyCode.BACKSPACE || k == $.inputmask.keyCode.DELETE || iphone && 127 == k || e.ctrlKey && 88 == k && !isInputEventSupported("cut") ? (e.preventDefault(), 
            88 == k && (undoValue = getBuffer().join("")), handleRemove(input, k, pos), 
            writeBuffer(input, getBuffer(), getMaskSet().p, e, undoValue != getBuffer().join("")), 
            input._valueGet() == getBufferTemplate().join("") ? $input.trigger("cleared") : isComplete(getBuffer()) === !0 && $input.trigger("complete"), 
            opts.showTooltip && $input.prop("title", getMaskSet().mask)) : k == $.inputmask.keyCode.END || k == $.inputmask.keyCode.PAGE_DOWN ? setTimeout(function() {
                var caretPos = seekNext(getLastValidPosition());
                opts.insertMode || caretPos != getMaskLength() || e.shiftKey || caretPos--, 
                caret(input, e.shiftKey ? pos.begin : caretPos, caretPos);
            }, 0) : k == $.inputmask.keyCode.HOME && !e.shiftKey || k == $.inputmask.keyCode.PAGE_UP ? caret(input, 0, e.shiftKey ? pos.begin : 0) : (opts.undoOnEscape && k == $.inputmask.keyCode.ESCAPE || 90 == k && e.ctrlKey) && e.altKey !== !0 ? (checkVal(input, !0, !1, undoValue.split("")), 
            $input.click()) : k != $.inputmask.keyCode.INSERT || e.shiftKey || e.ctrlKey ? 0 != opts.insertMode || e.shiftKey || (k == $.inputmask.keyCode.RIGHT ? setTimeout(function() {
                var caretPos = caret(input);
                caret(input, caretPos.begin);
            }, 0) : k == $.inputmask.keyCode.LEFT && setTimeout(function() {
                var caretPos = caret(input);
                caret(input, isRTL ? caretPos.begin + 1 : caretPos.begin - 1);
            }, 0)) : (opts.insertMode = !opts.insertMode, caret(input, opts.insertMode || pos.begin != getMaskLength() ? pos.begin : pos.begin - 1)), 
            opts.onKeyDown.call(this, e, getBuffer(), caret(input).begin, opts), 
            ignorable = -1 != $.inArray(k, opts.ignorables);
        }
        function keypressEvent(e, checkval, writeOut, strict, ndx) {
            var input = this, $input = $(input), k = e.which || e.charCode || e.keyCode;
            if (!(checkval === !0 || e.ctrlKey && e.altKey) && (e.ctrlKey || e.metaKey || ignorable)) return !0;
            if (k) {
                46 == k && 0 == e.shiftKey && "," == opts.radixPoint && (k = 44);
                var forwardPosition, pos = checkval ? {
                    begin: ndx,
                    end: ndx
                } : caret(input), c = String.fromCharCode(k), isSlctn = isSelection(pos.begin, pos.end);
                isSlctn && (getMaskSet().undoPositions = $.extend(!0, {}, getMaskSet().validPositions), 
                handleRemove(input, $.inputmask.keyCode.DELETE, pos, !0), pos.begin = getMaskSet().p, 
                opts.insertMode || (opts.insertMode = !opts.insertMode, setValidPosition(pos.begin, strict), 
                opts.insertMode = !opts.insertMode), isSlctn = !opts.multi), getMaskSet().writeOutBuffer = !0;
                var p = isRTL && !isSlctn ? pos.end : pos.begin, valResult = isValid(p, c, strict);
                if (valResult !== !1) {
                    if (valResult !== !0 && (p = void 0 != valResult.pos ? valResult.pos : p, 
                    c = void 0 != valResult.c ? valResult.c : c), resetMaskSet(!0), 
                    void 0 != valResult.caret) forwardPosition = valResult.caret; else {
                        var vps = getMaskSet().validPositions;
                        forwardPosition = !opts.keepStatic && (void 0 != vps[p + 1] && getTests(p + 1, vps[p].locator.slice(), p).length > 1 || void 0 != vps[p].alternation) ? p + 1 : seekNext(p);
                    }
                    getMaskSet().p = forwardPosition;
                }
                if (writeOut !== !1) {
                    var self = this;
                    if (setTimeout(function() {
                        opts.onKeyValidation.call(self, valResult, opts);
                    }, 0), getMaskSet().writeOutBuffer && valResult !== !1) {
                        var buffer = getBuffer();
                        writeBuffer(input, buffer, checkval ? void 0 : opts.numericInput ? seekPrevious(forwardPosition) : forwardPosition, e, checkval !== !0), 
                        checkval !== !0 && setTimeout(function() {
                            isComplete(buffer) === !0 && $input.trigger("complete");
                        }, 0);
                    } else isSlctn && (getMaskSet().buffer = void 0, getMaskSet().validPositions = getMaskSet().undoPositions);
                } else isSlctn && (getMaskSet().buffer = void 0, getMaskSet().validPositions = getMaskSet().undoPositions);
                if (opts.showTooltip && $input.prop("title", getMaskSet().mask), 
                checkval && $.isFunction(opts.onBeforeWrite)) {
                    var result = opts.onBeforeWrite.call(this, e, getBuffer(), forwardPosition, opts);
                    if (result && result.refreshFromBuffer) {
                        var refresh = result.refreshFromBuffer;
                        refreshFromBuffer(refresh === !0 ? refresh : refresh.start, refresh.end, result.buffer), 
                        resetMaskSet(!0), result.caret && (getMaskSet().p = result.caret);
                    }
                }
                e.preventDefault();
            }
        }
        function pasteEvent(e) {
            var input = this, $input = $(input), inputValue = input._valueGet(!0), caretPos = caret(input);
            if ("propertychange" == e.type && input._valueGet().length <= getMaskLength()) return !0;
            if ("paste" == e.type) {
                var valueBeforeCaret = inputValue.substr(0, caretPos.begin), valueAfterCaret = inputValue.substr(caretPos.end, inputValue.length);
                valueBeforeCaret == getBufferTemplate().slice(0, caretPos.begin).join("") && (valueBeforeCaret = ""), 
                valueAfterCaret == getBufferTemplate().slice(caretPos.end).join("") && (valueAfterCaret = ""), 
                window.clipboardData && window.clipboardData.getData ? inputValue = valueBeforeCaret + window.clipboardData.getData("Text") + valueAfterCaret : e.originalEvent && e.originalEvent.clipboardData && e.originalEvent.clipboardData.getData && (inputValue = valueBeforeCaret + e.originalEvent.clipboardData.getData("text/plain") + valueAfterCaret);
            }
            var pasteValue = inputValue;
            if ($.isFunction(opts.onBeforePaste)) {
                if (pasteValue = opts.onBeforePaste.call(input, inputValue, opts), 
                pasteValue === !1) return e.preventDefault(), !1;
                pasteValue || (pasteValue = inputValue);
            }
            return checkVal(input, !0, !1, isRTL ? pasteValue.split("").reverse() : pasteValue.split("")), 
            $input.click(), isComplete(getBuffer()) === !0 && $input.trigger("complete"), 
            !1;
        }
        function inputFallBackEvent(e) {
            var input = this;
            checkVal(input, !0, !1), isComplete(getBuffer()) === !0 && $(input).trigger("complete"), 
            e.preventDefault();
        }
        function compositionStartEvent(e) {
            var input = this;
            undoValue = getBuffer().join(""), ("" == compositionData || 0 != e.originalEvent.data.indexOf(compositionData)) && (compositionCaretPos = caret(input));
        }
        function compositionUpdateEvent(e) {
            var input = this, caretPos = compositionCaretPos || caret(input);
            0 == e.originalEvent.data.indexOf(compositionData) && (resetMaskSet(), 
            caretPos = {
                begin: 0,
                end: 0
            });
            var newData = e.originalEvent.data;
            caret(input, caretPos.begin, caretPos.end);
            for (var i = 0; i < newData.length; i++) {
                var keypress = $.Event("keypress");
                keypress.which = newData.charCodeAt(i), skipKeyPressEvent = !1, 
                ignorable = !1, keypressEvent.call(input, keypress);
            }
            setTimeout(function() {
                var forwardPosition = getMaskSet().p;
                writeBuffer(input, getBuffer(), opts.numericInput ? seekPrevious(forwardPosition) : forwardPosition);
            }, 0), compositionData = e.originalEvent.data;
        }
        function compositionEndEvent(e) {}
        function mask(el) {
            if ($el = $(el), $el.data("_inputmask", {
                maskset: maskset,
                opts: opts,
                isRTL: !1
            }), opts.showTooltip && $el.prop("title", getMaskSet().mask), ("rtl" == el.dir || opts.rightAlign) && $el.css("text-align", "right"), 
            "rtl" == el.dir || opts.numericInput) {
                el.dir = "ltr", $el.removeAttr("dir");
                var inputData = $el.data("_inputmask");
                inputData.isRTL = !0, $el.data("_inputmask", inputData), isRTL = !0;
            }
            $el.unbind(".inputmask"), ($el.is(":input") && isInputTypeSupported($el.attr("type")) || el.isContentEditable) && ($el.closest("form").bind("submit", function(e) {
                undoValue != getBuffer().join("") && $el.change(), $el[0]._valueGet && $el[0]._valueGet() == getBufferTemplate().join("") && $el[0]._valueSet(""), 
                opts.removeMaskOnSubmit && $el.inputmask("remove");
            }).bind("reset", function() {
                setTimeout(function() {
                    $el.triggerHandler("setvalue.inputmask");
                }, 0);
            }), $el.bind("mouseenter.inputmask", function() {
                var $input = $(this), input = this;
                !$input.is(":focus") && opts.showMaskOnHover && input._valueGet() != getBuffer().join("") && writeBuffer(input, getBuffer());
            }).bind("blur.inputmask", function(e) {
                var $input = $(this), input = this;
                if ($input.data("_inputmask")) {
                    var nptValue = input._valueGet(), buffer = getBuffer().slice();
                    firstClick = !0, undoValue != buffer.join("") && setTimeout(function() {
                        $input.change(), undoValue = buffer.join("");
                    }, 0), "" != nptValue && (opts.clearMaskOnLostFocus && (nptValue == getBufferTemplate().join("") ? buffer = [] : clearOptionalTail(buffer)), 
                    isComplete(buffer) === !1 && ($input.trigger("incomplete"), 
                    opts.clearIncomplete && (resetMaskSet(), buffer = opts.clearMaskOnLostFocus ? [] : getBufferTemplate().slice())), 
                    writeBuffer(input, buffer, void 0, e));
                }
            }).bind("focus.inputmask", function(e) {
                var input = ($(this), this), nptValue = input._valueGet();
                opts.showMaskOnFocus && (!opts.showMaskOnHover || opts.showMaskOnHover && "" == nptValue) && input._valueGet() != getBuffer().join("") && writeBuffer(input, getBuffer(), seekNext(getLastValidPosition())), 
                undoValue = getBuffer().join("");
            }).bind("mouseleave.inputmask", function() {
                var $input = $(this), input = this;
                if (opts.clearMaskOnLostFocus) {
                    var buffer = getBuffer().slice(), nptValue = input._valueGet();
                    $input.is(":focus") || nptValue == $input.attr("placeholder") || "" == nptValue || (nptValue == getBufferTemplate().join("") ? buffer = [] : clearOptionalTail(buffer), 
                    writeBuffer(input, buffer));
                }
            }).bind("click.inputmask", function() {
                var $input = $(this), input = this;
                if ($input.is(":focus")) {
                    var selectedCaret = caret(input);
                    if (selectedCaret.begin == selectedCaret.end) if (opts.radixFocus && "" != opts.radixPoint && -1 != $.inArray(opts.radixPoint, getBuffer()) && (firstClick || getBuffer().join("") == getBufferTemplate().join(""))) caret(input, $.inArray(opts.radixPoint, getBuffer())), 
                    firstClick = !1; else {
                        var clickPosition = TranslatePosition(selectedCaret.begin), lastPosition = seekNext(getLastValidPosition(clickPosition));
                        lastPosition > clickPosition ? caret(input, isMask(clickPosition) ? clickPosition : seekNext(clickPosition)) : caret(input, lastPosition);
                    }
                }
            }).bind("dblclick.inputmask", function() {
                var input = this;
                setTimeout(function() {
                    caret(input, 0, seekNext(getLastValidPosition()));
                }, 0);
            }).bind(PasteEventType + ".inputmask dragdrop.inputmask drop.inputmask", pasteEvent).bind("cut.inputmask", function(e) {
                skipInputEvent = !0;
                var input = this, $input = $(input), pos = caret(input);
                handleRemove(input, $.inputmask.keyCode.DELETE, pos), writeBuffer(input, getBuffer(), getMaskSet().p, e, undoValue != getBuffer().join("")), 
                input._valueGet() == getBufferTemplate().join("") && $input.trigger("cleared"), 
                opts.showTooltip && $input.prop("title", getMaskSet().mask);
            }).bind("complete.inputmask", opts.oncomplete).bind("incomplete.inputmask", opts.onincomplete).bind("cleared.inputmask", opts.oncleared), 
            $el.bind("keydown.inputmask", keydownEvent).bind("keypress.inputmask", keypressEvent), 
            androidfirefox || $el.bind("compositionstart.inputmask", compositionStartEvent).bind("compositionupdate.inputmask", compositionUpdateEvent).bind("compositionend.inputmask", compositionEndEvent), 
            "paste" === PasteEventType && $el.bind("input.inputmask", inputFallBackEvent)), 
            $el.bind("setvalue.inputmask", function() {
                var input = this, value = input._valueGet();
                input._valueSet($.isFunction(opts.onBeforeMask) ? opts.onBeforeMask.call(input, value, opts) || value : value), 
                checkVal(input, !0, !1), undoValue = getBuffer().join(""), (opts.clearMaskOnLostFocus || opts.clearIncomplete) && input._valueGet() == getBufferTemplate().join("") && input._valueSet("");
            }), patchValueProperty(el);
            var initialValue = $.isFunction(opts.onBeforeMask) ? opts.onBeforeMask.call(el, el._valueGet(), opts) || el._valueGet() : el._valueGet();
            checkVal(el, !0, !1, initialValue.split(""));
            var buffer = getBuffer().slice();
            undoValue = buffer.join("");
            var activeElement;
            try {
                activeElement = document.activeElement;
            } catch (e) {}
            isComplete(buffer) === !1 && opts.clearIncomplete && resetMaskSet(), 
            opts.clearMaskOnLostFocus && (buffer.join("") == getBufferTemplate().join("") ? buffer = [] : clearOptionalTail(buffer)), 
            writeBuffer(el, buffer), activeElement === el && caret(el, seekNext(getLastValidPosition())), 
            installEventRuler(el);
        }
        var undoValue, compositionCaretPos, compositionData, $el, maxLength, isRTL = !1, skipKeyPressEvent = !1, skipInputEvent = !1, ignorable = !1, firstClick = !0;
        if (void 0 != actionObj) switch (actionObj.action) {
          case "isComplete":
            return $el = $(actionObj.el), maskset = $el.data("_inputmask").maskset, 
            opts = $el.data("_inputmask").opts, isComplete(actionObj.buffer);

          case "unmaskedvalue":
            return $el = actionObj.$input, maskset = $el.data("_inputmask").maskset, 
            opts = $el.data("_inputmask").opts, isRTL = actionObj.$input.data("_inputmask").isRTL, 
            unmaskedvalue(actionObj.$input);

          case "mask":
            undoValue = getBuffer().join(""), mask(actionObj.el);
            break;

          case "format":
            $el = $({}), $el.data("_inputmask", {
                maskset: maskset,
                opts: opts,
                isRTL: opts.numericInput
            }), opts.numericInput && (isRTL = !0);
            var valueBuffer = ($.isFunction(opts.onBeforeMask) ? opts.onBeforeMask.call($el, actionObj.value, opts) || actionObj.value : actionObj.value).split("");
            return checkVal($el, !1, !1, isRTL ? valueBuffer.reverse() : valueBuffer), 
            $.isFunction(opts.onBeforeWrite) && opts.onBeforeWrite.call(this, void 0, getBuffer(), 0, opts), 
            actionObj.metadata ? {
                value: isRTL ? getBuffer().slice().reverse().join("") : getBuffer().join(""),
                metadata: $el.inputmask("getmetadata")
            } : isRTL ? getBuffer().slice().reverse().join("") : getBuffer().join("");

          case "isValid":
            $el = $({}), $el.data("_inputmask", {
                maskset: maskset,
                opts: opts,
                isRTL: opts.numericInput
            }), opts.numericInput && (isRTL = !0);
            var valueBuffer = actionObj.value.split("");
            checkVal($el, !1, !0, isRTL ? valueBuffer.reverse() : valueBuffer);
            for (var buffer = getBuffer(), rl = determineLastRequiredPosition(), lmib = buffer.length - 1; lmib > rl && !isMask(lmib); lmib--);
            return buffer.splice(rl, lmib + 1 - rl), isComplete(buffer) && actionObj.value == buffer.join("");

          case "getemptymask":
            return $el = $(actionObj.el), maskset = $el.data("_inputmask").maskset, 
            opts = $el.data("_inputmask").opts, getBufferTemplate();

          case "remove":
            var el = actionObj.el;
            $el = $(el), maskset = $el.data("_inputmask").maskset, opts = $el.data("_inputmask").opts, 
            el._valueSet(unmaskedvalue($el)), $el.unbind(".inputmask"), $el.removeData("_inputmask");
            var valueProperty;
            Object.getOwnPropertyDescriptor && (valueProperty = Object.getOwnPropertyDescriptor(el, "value")), 
            valueProperty && valueProperty.get ? el._valueGet && Object.defineProperty(el, "value", {
                get: el._valueGet,
                set: el._valueSet
            }) : document.__lookupGetter__ && el.__lookupGetter__("value") && el._valueGet && (el.__defineGetter__("value", el._valueGet), 
            el.__defineSetter__("value", el._valueSet));
            try {
                delete el._valueGet, delete el._valueSet;
            } catch (e) {
                el._valueGet = void 0, el._valueSet = void 0;
            }
            break;

          case "getmetadata":
            if ($el = $(actionObj.el), maskset = $el.data("_inputmask").maskset, 
            opts = $el.data("_inputmask").opts, $.isArray(maskset.metadata)) {
                for (var alternation, lvp = getLastValidPosition(), firstAlt = lvp; firstAlt >= 0; firstAlt--) if (getMaskSet().validPositions[firstAlt] && void 0 != getMaskSet().validPositions[firstAlt].alternation) {
                    alternation = getMaskSet().validPositions[firstAlt].alternation;
                    break;
                }
                return void 0 != alternation ? maskset.metadata[getMaskSet().validPositions[lvp].locator[alternation]] : maskset.metadata[0];
            }
            return maskset.metadata;
        }
    }
    if (void 0 === $.fn.inputmask) {
        var ua = navigator.userAgent, iphone = null !== ua.match(new RegExp("iphone", "i")), androidchrome = (null !== ua.match(new RegExp("android.*safari.*", "i")), 
        null !== ua.match(new RegExp("android.*chrome.*", "i"))), androidfirefox = null !== ua.match(new RegExp("android.*firefox.*", "i")), PasteEventType = (/Kindle/i.test(ua) || /Silk/i.test(ua) || /KFTT/i.test(ua) || /KFOT/i.test(ua) || /KFJWA/i.test(ua) || /KFJWI/i.test(ua) || /KFSOWI/i.test(ua) || /KFTHWA/i.test(ua) || /KFTHWI/i.test(ua) || /KFAPWA/i.test(ua) || /KFAPWI/i.test(ua), 
        isInputEventSupported("paste") ? "paste" : isInputEventSupported("input") ? "input" : "propertychange");
        $.inputmask = {
            defaults: {
                placeholder: "_",
                optionalmarker: {
                    start: "[",
                    end: "]"
                },
                quantifiermarker: {
                    start: "{",
                    end: "}"
                },
                groupmarker: {
                    start: "(",
                    end: ")"
                },
                alternatormarker: "|",
                escapeChar: "\\",
                mask: null,
                oncomplete: $.noop,
                onincomplete: $.noop,
                oncleared: $.noop,
                repeat: 0,
                greedy: !0,
                autoUnmask: !1,
                removeMaskOnSubmit: !1,
                clearMaskOnLostFocus: !0,
                insertMode: !0,
                clearIncomplete: !1,
                aliases: {},
                alias: null,
                onKeyDown: $.noop,
                onBeforeMask: void 0,
                onBeforePaste: void 0,
                onBeforeWrite: void 0,
                onUnMask: void 0,
                showMaskOnFocus: !0,
                showMaskOnHover: !0,
                onKeyValidation: $.noop,
                skipOptionalPartCharacter: " ",
                showTooltip: !1,
                numericInput: !1,
                rightAlign: !1,
                undoOnEscape: !0,
                radixPoint: "",
                radixFocus: !1,
                nojumps: !1,
                nojumpsThreshold: 0,
                keepStatic: void 0,
                definitions: {
                    9: {
                        validator: "[0-9]",
                        cardinality: 1,
                        definitionSymbol: "*"
                    },
                    a: {
                        validator: "[A-Za-zА-яЁёÀ-ÿµ]",
                        cardinality: 1,
                        definitionSymbol: "*"
                    },
                    "*": {
                        validator: "[0-9A-Za-zА-яЁёÀ-ÿµ]",
                        cardinality: 1
                    }
                },
                ignorables: [ 8, 9, 13, 19, 27, 33, 34, 35, 36, 37, 38, 39, 40, 45, 46, 93, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123 ],
                isComplete: void 0,
                canClearPosition: $.noop,
                postValidation: void 0
            },
            keyCode: {
                ALT: 18,
                BACKSPACE: 8,
                CAPS_LOCK: 20,
                COMMA: 188,
                COMMAND: 91,
                COMMAND_LEFT: 91,
                COMMAND_RIGHT: 93,
                CONTROL: 17,
                DELETE: 46,
                DOWN: 40,
                END: 35,
                ENTER: 13,
                ESCAPE: 27,
                HOME: 36,
                INSERT: 45,
                LEFT: 37,
                MENU: 93,
                NUMPAD_ADD: 107,
                NUMPAD_DECIMAL: 110,
                NUMPAD_DIVIDE: 111,
                NUMPAD_ENTER: 108,
                NUMPAD_MULTIPLY: 106,
                NUMPAD_SUBTRACT: 109,
                PAGE_DOWN: 34,
                PAGE_UP: 33,
                PERIOD: 190,
                RIGHT: 39,
                SHIFT: 16,
                SPACE: 32,
                TAB: 9,
                UP: 38,
                WINDOWS: 91
            },
            masksCache: {},
            escapeRegex: function(str) {
                var specials = [ "/", ".", "*", "+", "?", "|", "(", ")", "[", "]", "{", "}", "\\", "$", "^" ];
                return str.replace(new RegExp("(\\" + specials.join("|\\") + ")", "gim"), "\\$1");
            },
            format: function(value, options, metadata) {
                var opts = $.extend(!0, {}, $.inputmask.defaults, options);
                return resolveAlias(opts.alias, options, opts), maskScope({
                    action: "format",
                    value: value,
                    metadata: metadata
                }, generateMaskSet(opts, options && void 0 !== options.definitions), opts);
            },
            isValid: function(value, options) {
                var opts = $.extend(!0, {}, $.inputmask.defaults, options);
                return resolveAlias(opts.alias, options, opts), maskScope({
                    action: "isValid",
                    value: value
                }, generateMaskSet(opts, options && void 0 !== options.definitions), opts);
            }
        }, $.fn.inputmask = function(fn, options) {
            function importAttributeOptions(npt, opts, importedOptionsContainer) {
                var $npt = $(npt);
                $npt.data("inputmask-alias") && resolveAlias($npt.data("inputmask-alias"), $.extend(!0, {}, opts), opts);
                for (var option in opts) {
                    var optionData = $npt.data("inputmask-" + option.toLowerCase());
                    void 0 != optionData && (optionData = "boolean" == typeof optionData ? optionData : optionData.toString(), 
                    "mask" == option && 0 == optionData.indexOf("[") ? (opts[option] = optionData.replace(/[\s[\]]/g, "").split("','"), 
                    opts[option][0] = opts[option][0].replace("'", ""), opts[option][opts[option].length - 1] = opts[option][opts[option].length - 1].replace("'", "")) : opts[option] = optionData, 
                    importedOptionsContainer && (importedOptionsContainer[option] = opts[option]));
                }
                return opts;
            }
            var maskset, opts = $.extend(!0, {}, $.inputmask.defaults, options);
            if ("string" == typeof fn) switch (fn) {
              case "mask":
                return resolveAlias(opts.alias, options, opts), this.each(function() {
                    return importAttributeOptions(this, opts), maskset = generateMaskSet(opts, options && void 0 !== options.definitions), 
                    void 0 == maskset ? this : void maskScope({
                        action: "mask",
                        el: this
                    }, maskset, opts);
                });

              case "unmaskedvalue":
                var $input = $(this);
                return $input.data("_inputmask") ? maskScope({
                    action: "unmaskedvalue",
                    $input: $input
                }) : $input.val();

              case "remove":
                return this.each(function() {
                    var $input = $(this);
                    $input.data("_inputmask") && maskScope({
                        action: "remove",
                        el: this
                    });
                });

              case "getemptymask":
                return this.data("_inputmask") ? maskScope({
                    action: "getemptymask",
                    el: this
                }) : "";

              case "hasMaskedValue":
                return this.data("_inputmask") ? !this.data("_inputmask").opts.autoUnmask : !1;

              case "isComplete":
                return this.data("_inputmask") ? maskScope({
                    action: "isComplete",
                    buffer: this[0]._valueGet().split(""),
                    el: this
                }) : !0;

              case "getmetadata":
                return this.data("_inputmask") ? maskScope({
                    action: "getmetadata",
                    el: this
                }) : void 0;

              default:
                return resolveAlias(opts.alias, options, opts), resolveAlias(fn, options, opts) || (opts.mask = fn), 
                this.each(function() {
                    return importAttributeOptions(this, opts), maskset = generateMaskSet(opts, options && void 0 !== options.definitions), 
                    void 0 == maskset ? this : void maskScope({
                        action: "mask",
                        el: this
                    }, maskset, opts);
                });
            } else {
                if ("object" == typeof fn) return opts = $.extend(!0, {}, $.inputmask.defaults, fn), 
                resolveAlias(opts.alias, fn, opts), this.each(function() {
                    return importAttributeOptions(this, opts), maskset = generateMaskSet(opts, fn && void 0 !== fn.definitions), 
                    void 0 == maskset ? this : void maskScope({
                        action: "mask",
                        el: this
                    }, maskset, opts);
                });
                if (void 0 == fn) return this.each(function() {
                    var attrOptions = $(this).attr("data-inputmask");
                    if (attrOptions && "" != attrOptions) try {
                        attrOptions = attrOptions.replace(new RegExp("'", "g"), '"');
                        var dataoptions = $.parseJSON("{" + attrOptions + "}");
                        $.extend(!0, dataoptions, options), opts = $.extend(!0, {}, $.inputmask.defaults, dataoptions), 
                        opts = importAttributeOptions(this, opts), resolveAlias(opts.alias, dataoptions, opts), 
                        opts.alias = void 0, $(this).inputmask("mask", opts);
                    } catch (ex) {}
                    if ($(this).attr("data-inputmask-mask") || $(this).attr("data-inputmask-alias")) {
                        opts = $.extend(!0, {}, $.inputmask.defaults, {});
                        var dataOptions = {};
                        opts = importAttributeOptions(this, opts, dataOptions), 
                        resolveAlias(opts.alias, dataOptions, opts), opts.alias = void 0, 
                        $(this).inputmask("mask", opts);
                    }
                });
            }
        };
    }
    return $.fn.inputmask;
}(jQuery), function($) {
    return $.extend($.inputmask.defaults.definitions, {
        h: {
            validator: "[01][0-9]|2[0-3]",
            cardinality: 2,
            prevalidator: [ {
                validator: "[0-2]",
                cardinality: 1
            } ]
        },
        s: {
            validator: "[0-5][0-9]",
            cardinality: 2,
            prevalidator: [ {
                validator: "[0-5]",
                cardinality: 1
            } ]
        },
        d: {
            validator: "0[1-9]|[12][0-9]|3[01]",
            cardinality: 2,
            prevalidator: [ {
                validator: "[0-3]",
                cardinality: 1
            } ]
        },
        m: {
            validator: "0[1-9]|1[012]",
            cardinality: 2,
            prevalidator: [ {
                validator: "[01]",
                cardinality: 1
            } ]
        },
        y: {
            validator: "(19|20)\\d{2}",
            cardinality: 4,
            prevalidator: [ {
                validator: "[12]",
                cardinality: 1
            }, {
                validator: "(19|20)",
                cardinality: 2
            }, {
                validator: "(19|20)\\d",
                cardinality: 3
            } ]
        }
    }), $.extend($.inputmask.defaults.aliases, {
        "dd/mm/yyyy": {
            mask: "1/2/y",
            placeholder: "dd/mm/yyyy",
            regex: {
                val1pre: new RegExp("[0-3]"),
                val1: new RegExp("0[1-9]|[12][0-9]|3[01]"),
                val2pre: function(separator) {
                    var escapedSeparator = $.inputmask.escapeRegex.call(this, separator);
                    return new RegExp("((0[1-9]|[12][0-9]|3[01])" + escapedSeparator + "[01])");
                },
                val2: function(separator) {
                    var escapedSeparator = $.inputmask.escapeRegex.call(this, separator);
                    return new RegExp("((0[1-9]|[12][0-9])" + escapedSeparator + "(0[1-9]|1[012]))|(30" + escapedSeparator + "(0[13-9]|1[012]))|(31" + escapedSeparator + "(0[13578]|1[02]))");
                }
            },
            leapday: "29/02/",
            separator: "/",
            yearrange: {
                minyear: 1900,
                maxyear: 2099
            },
            isInYearRange: function(chrs, minyear, maxyear) {
                if (isNaN(chrs)) return !1;
                var enteredyear = parseInt(chrs.concat(minyear.toString().slice(chrs.length))), enteredyear2 = parseInt(chrs.concat(maxyear.toString().slice(chrs.length)));
                return (isNaN(enteredyear) ? !1 : enteredyear >= minyear && maxyear >= enteredyear) || (isNaN(enteredyear2) ? !1 : enteredyear2 >= minyear && maxyear >= enteredyear2);
            },
            determinebaseyear: function(minyear, maxyear, hint) {
                var currentyear = new Date().getFullYear();
                if (minyear > currentyear) return minyear;
                if (currentyear > maxyear) {
                    for (var maxYearPrefix = maxyear.toString().slice(0, 2), maxYearPostfix = maxyear.toString().slice(2, 4); maxYearPrefix + hint > maxyear; ) maxYearPrefix--;
                    var maxxYear = maxYearPrefix + maxYearPostfix;
                    return minyear > maxxYear ? minyear : maxxYear;
                }
                return currentyear;
            },
            onKeyDown: function(e, buffer, caretPos, opts) {
                var $input = $(this);
                if (e.ctrlKey && e.keyCode == $.inputmask.keyCode.RIGHT) {
                    var today = new Date();
                    $input.val(today.getDate().toString() + (today.getMonth() + 1).toString() + today.getFullYear().toString()), 
                    $input.triggerHandler("setvalue.inputmask");
                }
            },
            getFrontValue: function(mask, buffer, opts) {
                for (var start = 0, length = 0, i = 0; i < mask.length && "2" != mask.charAt(i); i++) {
                    var definition = opts.definitions[mask.charAt(i)];
                    definition ? (start += length, length = definition.cardinality) : length++;
                }
                return buffer.join("").substr(start, length);
            },
            definitions: {
                1: {
                    validator: function(chrs, maskset, pos, strict, opts) {
                        var isValid = opts.regex.val1.test(chrs);
                        return strict || isValid || chrs.charAt(1) != opts.separator && -1 == "-./".indexOf(chrs.charAt(1)) || !(isValid = opts.regex.val1.test("0" + chrs.charAt(0))) ? isValid : (maskset.buffer[pos - 1] = "0", 
                        {
                            refreshFromBuffer: {
                                start: pos - 1,
                                end: pos
                            },
                            pos: pos,
                            c: chrs.charAt(0)
                        });
                    },
                    cardinality: 2,
                    prevalidator: [ {
                        validator: function(chrs, maskset, pos, strict, opts) {
                            var pchrs = chrs;
                            isNaN(maskset.buffer[pos + 1]) || (pchrs += maskset.buffer[pos + 1]);
                            var isValid = 1 == pchrs.length ? opts.regex.val1pre.test(pchrs) : opts.regex.val1.test(pchrs);
                            if (!strict && !isValid) {
                                if (isValid = opts.regex.val1.test(chrs + "0")) return maskset.buffer[pos] = chrs, 
                                maskset.buffer[++pos] = "0", {
                                    pos: pos,
                                    c: "0"
                                };
                                if (isValid = opts.regex.val1.test("0" + chrs)) return maskset.buffer[pos] = "0", 
                                pos++, {
                                    pos: pos
                                };
                            }
                            return isValid;
                        },
                        cardinality: 1
                    } ]
                },
                2: {
                    validator: function(chrs, maskset, pos, strict, opts) {
                        var frontValue = opts.getFrontValue(maskset.mask, maskset.buffer, opts);
                        -1 != frontValue.indexOf(opts.placeholder[0]) && (frontValue = "01" + opts.separator);
                        var isValid = opts.regex.val2(opts.separator).test(frontValue + chrs);
                        if (!strict && !isValid && (chrs.charAt(1) == opts.separator || -1 != "-./".indexOf(chrs.charAt(1))) && (isValid = opts.regex.val2(opts.separator).test(frontValue + "0" + chrs.charAt(0)))) return maskset.buffer[pos - 1] = "0", 
                        {
                            refreshFromBuffer: {
                                start: pos - 1,
                                end: pos
                            },
                            pos: pos,
                            c: chrs.charAt(0)
                        };
                        if (opts.mask.indexOf("2") == opts.mask.length - 1 && isValid) {
                            var dayMonthValue = maskset.buffer.join("").substr(4, 4) + chrs;
                            if (dayMonthValue != opts.leapday) return !0;
                            var year = parseInt(maskset.buffer.join("").substr(0, 4), 10);
                            return year % 4 === 0 ? year % 100 === 0 ? year % 400 === 0 ? !0 : !1 : !0 : !1;
                        }
                        return isValid;
                    },
                    cardinality: 2,
                    prevalidator: [ {
                        validator: function(chrs, maskset, pos, strict, opts) {
                            isNaN(maskset.buffer[pos + 1]) || (chrs += maskset.buffer[pos + 1]);
                            var frontValue = opts.getFrontValue(maskset.mask, maskset.buffer, opts);
                            -1 != frontValue.indexOf(opts.placeholder[0]) && (frontValue = "01" + opts.separator);
                            var isValid = 1 == chrs.length ? opts.regex.val2pre(opts.separator).test(frontValue + chrs) : opts.regex.val2(opts.separator).test(frontValue + chrs);
                            return strict || isValid || !(isValid = opts.regex.val2(opts.separator).test(frontValue + "0" + chrs)) ? isValid : (maskset.buffer[pos] = "0", 
                            pos++, {
                                pos: pos
                            });
                        },
                        cardinality: 1
                    } ]
                },
                y: {
                    validator: function(chrs, maskset, pos, strict, opts) {
                        if (opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear)) {
                            var dayMonthValue = maskset.buffer.join("").substr(0, 6);
                            if (dayMonthValue != opts.leapday) return !0;
                            var year = parseInt(chrs, 10);
                            return year % 4 === 0 ? year % 100 === 0 ? year % 400 === 0 ? !0 : !1 : !0 : !1;
                        }
                        return !1;
                    },
                    cardinality: 4,
                    prevalidator: [ {
                        validator: function(chrs, maskset, pos, strict, opts) {
                            var isValid = opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
                            if (!strict && !isValid) {
                                var yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs + "0").toString().slice(0, 1);
                                if (isValid = opts.isInYearRange(yearPrefix + chrs, opts.yearrange.minyear, opts.yearrange.maxyear)) return maskset.buffer[pos++] = yearPrefix.charAt(0), 
                                {
                                    pos: pos
                                };
                                if (yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs + "0").toString().slice(0, 2), 
                                isValid = opts.isInYearRange(yearPrefix + chrs, opts.yearrange.minyear, opts.yearrange.maxyear)) return maskset.buffer[pos++] = yearPrefix.charAt(0), 
                                maskset.buffer[pos++] = yearPrefix.charAt(1), {
                                    pos: pos
                                };
                            }
                            return isValid;
                        },
                        cardinality: 1
                    }, {
                        validator: function(chrs, maskset, pos, strict, opts) {
                            var isValid = opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
                            if (!strict && !isValid) {
                                var yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs).toString().slice(0, 2);
                                if (isValid = opts.isInYearRange(chrs[0] + yearPrefix[1] + chrs[1], opts.yearrange.minyear, opts.yearrange.maxyear)) return maskset.buffer[pos++] = yearPrefix.charAt(1), 
                                {
                                    pos: pos
                                };
                                if (yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs).toString().slice(0, 2), 
                                opts.isInYearRange(yearPrefix + chrs, opts.yearrange.minyear, opts.yearrange.maxyear)) {
                                    var dayMonthValue = maskset.buffer.join("").substr(0, 6);
                                    if (dayMonthValue != opts.leapday) isValid = !0; else {
                                        var year = parseInt(chrs, 10);
                                        isValid = year % 4 === 0 ? year % 100 === 0 ? year % 400 === 0 ? !0 : !1 : !0 : !1;
                                    }
                                } else isValid = !1;
                                if (isValid) return maskset.buffer[pos - 1] = yearPrefix.charAt(0), 
                                maskset.buffer[pos++] = yearPrefix.charAt(1), maskset.buffer[pos++] = chrs.charAt(0), 
                                {
                                    refreshFromBuffer: {
                                        start: pos - 3,
                                        end: pos
                                    },
                                    pos: pos
                                };
                            }
                            return isValid;
                        },
                        cardinality: 2
                    }, {
                        validator: function(chrs, maskset, pos, strict, opts) {
                            return opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
                        },
                        cardinality: 3
                    } ]
                }
            },
            insertMode: !1,
            autoUnmask: !1
        },
        "mm/dd/yyyy": {
            placeholder: "mm/dd/yyyy",
            alias: "dd/mm/yyyy",
            regex: {
                val2pre: function(separator) {
                    var escapedSeparator = $.inputmask.escapeRegex.call(this, separator);
                    return new RegExp("((0[13-9]|1[012])" + escapedSeparator + "[0-3])|(02" + escapedSeparator + "[0-2])");
                },
                val2: function(separator) {
                    var escapedSeparator = $.inputmask.escapeRegex.call(this, separator);
                    return new RegExp("((0[1-9]|1[012])" + escapedSeparator + "(0[1-9]|[12][0-9]))|((0[13-9]|1[012])" + escapedSeparator + "30)|((0[13578]|1[02])" + escapedSeparator + "31)");
                },
                val1pre: new RegExp("[01]"),
                val1: new RegExp("0[1-9]|1[012]")
            },
            leapday: "02/29/",
            onKeyDown: function(e, buffer, caretPos, opts) {
                var $input = $(this);
                if (e.ctrlKey && e.keyCode == $.inputmask.keyCode.RIGHT) {
                    var today = new Date();
                    $input.val((today.getMonth() + 1).toString() + today.getDate().toString() + today.getFullYear().toString()), 
                    $input.triggerHandler("setvalue.inputmask");
                }
            }
        },
        "yyyy/mm/dd": {
            mask: "y/1/2",
            placeholder: "yyyy/mm/dd",
            alias: "mm/dd/yyyy",
            leapday: "/02/29",
            onKeyDown: function(e, buffer, caretPos, opts) {
                var $input = $(this);
                if (e.ctrlKey && e.keyCode == $.inputmask.keyCode.RIGHT) {
                    var today = new Date();
                    $input.val(today.getFullYear().toString() + (today.getMonth() + 1).toString() + today.getDate().toString()), 
                    $input.triggerHandler("setvalue.inputmask");
                }
            }
        },
        "dd.mm.yyyy": {
            mask: "1.2.y",
            placeholder: "dd.mm.yyyy",
            leapday: "29.02.",
            separator: ".",
            alias: "dd/mm/yyyy"
        },
        "dd-mm-yyyy": {
            mask: "1-2-y",
            placeholder: "dd-mm-yyyy",
            leapday: "29-02-",
            separator: "-",
            alias: "dd/mm/yyyy"
        },
        "mm.dd.yyyy": {
            mask: "1.2.y",
            placeholder: "mm.dd.yyyy",
            leapday: "02.29.",
            separator: ".",
            alias: "mm/dd/yyyy"
        },
        "mm-dd-yyyy": {
            mask: "1-2-y",
            placeholder: "mm-dd-yyyy",
            leapday: "02-29-",
            separator: "-",
            alias: "mm/dd/yyyy"
        },
        "yyyy.mm.dd": {
            mask: "y.1.2",
            placeholder: "yyyy.mm.dd",
            leapday: ".02.29",
            separator: ".",
            alias: "yyyy/mm/dd"
        },
        "yyyy-mm-dd": {
            mask: "y-1-2",
            placeholder: "yyyy-mm-dd",
            leapday: "-02-29",
            separator: "-",
            alias: "yyyy/mm/dd"
        },
        datetime: {
            mask: "1/2/y h:s",
            placeholder: "dd/mm/yyyy hh:mm",
            alias: "dd/mm/yyyy",
            regex: {
                hrspre: new RegExp("[012]"),
                hrs24: new RegExp("2[0-4]|1[3-9]"),
                hrs: new RegExp("[01][0-9]|2[0-4]"),
                ampm: new RegExp("^[a|p|A|P][m|M]"),
                mspre: new RegExp("[0-5]"),
                ms: new RegExp("[0-5][0-9]")
            },
            timeseparator: ":",
            hourFormat: "24",
            definitions: {
                h: {
                    validator: function(chrs, maskset, pos, strict, opts) {
                        if ("24" == opts.hourFormat && 24 == parseInt(chrs, 10)) return maskset.buffer[pos - 1] = "0", 
                        maskset.buffer[pos] = "0", {
                            refreshFromBuffer: {
                                start: pos - 1,
                                end: pos
                            },
                            c: "0"
                        };
                        var isValid = opts.regex.hrs.test(chrs);
                        if (!strict && !isValid && (chrs.charAt(1) == opts.timeseparator || -1 != "-.:".indexOf(chrs.charAt(1))) && (isValid = opts.regex.hrs.test("0" + chrs.charAt(0)))) return maskset.buffer[pos - 1] = "0", 
                        maskset.buffer[pos] = chrs.charAt(0), pos++, {
                            refreshFromBuffer: {
                                start: pos - 2,
                                end: pos
                            },
                            pos: pos,
                            c: opts.timeseparator
                        };
                        if (isValid && "24" !== opts.hourFormat && opts.regex.hrs24.test(chrs)) {
                            var tmp = parseInt(chrs, 10);
                            return 24 == tmp ? (maskset.buffer[pos + 5] = "a", maskset.buffer[pos + 6] = "m") : (maskset.buffer[pos + 5] = "p", 
                            maskset.buffer[pos + 6] = "m"), tmp -= 12, 10 > tmp ? (maskset.buffer[pos] = tmp.toString(), 
                            maskset.buffer[pos - 1] = "0") : (maskset.buffer[pos] = tmp.toString().charAt(1), 
                            maskset.buffer[pos - 1] = tmp.toString().charAt(0)), 
                            {
                                refreshFromBuffer: {
                                    start: pos - 1,
                                    end: pos + 6
                                },
                                c: maskset.buffer[pos]
                            };
                        }
                        return isValid;
                    },
                    cardinality: 2,
                    prevalidator: [ {
                        validator: function(chrs, maskset, pos, strict, opts) {
                            var isValid = opts.regex.hrspre.test(chrs);
                            return strict || isValid || !(isValid = opts.regex.hrs.test("0" + chrs)) ? isValid : (maskset.buffer[pos] = "0", 
                            pos++, {
                                pos: pos
                            });
                        },
                        cardinality: 1
                    } ]
                },
                s: {
                    validator: "[0-5][0-9]",
                    cardinality: 2,
                    prevalidator: [ {
                        validator: function(chrs, maskset, pos, strict, opts) {
                            var isValid = opts.regex.mspre.test(chrs);
                            return strict || isValid || !(isValid = opts.regex.ms.test("0" + chrs)) ? isValid : (maskset.buffer[pos] = "0", 
                            pos++, {
                                pos: pos
                            });
                        },
                        cardinality: 1
                    } ]
                },
                t: {
                    validator: function(chrs, maskset, pos, strict, opts) {
                        return opts.regex.ampm.test(chrs + "m");
                    },
                    casing: "lower",
                    cardinality: 1
                }
            },
            insertMode: !1,
            autoUnmask: !1
        },
        datetime12: {
            mask: "1/2/y h:s t\\m",
            placeholder: "dd/mm/yyyy hh:mm xm",
            alias: "datetime",
            hourFormat: "12"
        },
        "hh:mm t": {
            mask: "h:s t\\m",
            placeholder: "hh:mm xm",
            alias: "datetime",
            hourFormat: "12"
        },
        "h:s t": {
            mask: "h:s t\\m",
            placeholder: "hh:mm xm",
            alias: "datetime",
            hourFormat: "12"
        },
        "hh:mm:ss": {
            mask: "h:s:s",
            placeholder: "hh:mm:ss",
            alias: "datetime",
            autoUnmask: !1
        },
        "hh:mm": {
            mask: "h:s",
            placeholder: "hh:mm",
            alias: "datetime",
            autoUnmask: !1
        },
        date: {
            alias: "dd/mm/yyyy"
        },
        "mm/yyyy": {
            mask: "1/y",
            placeholder: "mm/yyyy",
            leapday: "donotuse",
            separator: "/",
            alias: "mm/dd/yyyy"
        }
    }), $.fn.inputmask;
}(jQuery), function($) {
    return $.extend($.inputmask.defaults.definitions, {
        A: {
            validator: "[A-Za-zА-яЁёÀ-ÿµ]",
            cardinality: 1,
            casing: "upper"
        },
        "#": {
            validator: "[0-9A-Za-zА-яЁёÀ-ÿµ]",
            cardinality: 1,
            casing: "upper"
        }
    }), $.extend($.inputmask.defaults.aliases, {
        url: {
            mask: "ir",
            placeholder: "",
            separator: "",
            defaultPrefix: "http://",
            regex: {
                urlpre1: new RegExp("[fh]"),
                urlpre2: new RegExp("(ft|ht)"),
                urlpre3: new RegExp("(ftp|htt)"),
                urlpre4: new RegExp("(ftp:|http|ftps)"),
                urlpre5: new RegExp("(ftp:/|ftps:|http:|https)"),
                urlpre6: new RegExp("(ftp://|ftps:/|http:/|https:)"),
                urlpre7: new RegExp("(ftp://|ftps://|http://|https:/)"),
                urlpre8: new RegExp("(ftp://|ftps://|http://|https://)")
            },
            definitions: {
                i: {
                    validator: function(chrs, maskset, pos, strict, opts) {
                        return !0;
                    },
                    cardinality: 8,
                    prevalidator: function() {
                        for (var result = [], prefixLimit = 8, i = 0; prefixLimit > i; i++) result[i] = function() {
                            var j = i;
                            return {
                                validator: function(chrs, maskset, pos, strict, opts) {
                                    if (opts.regex["urlpre" + (j + 1)]) {
                                        var k, tmp = chrs;
                                        j + 1 - chrs.length > 0 && (tmp = maskset.buffer.join("").substring(0, j + 1 - chrs.length) + "" + tmp);
                                        var isValid = opts.regex["urlpre" + (j + 1)].test(tmp);
                                        if (!strict && !isValid) {
                                            for (pos -= j, k = 0; k < opts.defaultPrefix.length; k++) maskset.buffer[pos] = opts.defaultPrefix[k], 
                                            pos++;
                                            for (k = 0; k < tmp.length - 1; k++) maskset.buffer[pos] = tmp[k], 
                                            pos++;
                                            return {
                                                pos: pos
                                            };
                                        }
                                        return isValid;
                                    }
                                    return !1;
                                },
                                cardinality: j
                            };
                        }();
                        return result;
                    }()
                },
                r: {
                    validator: ".",
                    cardinality: 50
                }
            },
            insertMode: !1,
            autoUnmask: !1
        },
        ip: {
            mask: "i[i[i]].i[i[i]].i[i[i]].i[i[i]]",
            definitions: {
                i: {
                    validator: function(chrs, maskset, pos, strict, opts) {
                        return pos - 1 > -1 && "." != maskset.buffer[pos - 1] ? (chrs = maskset.buffer[pos - 1] + chrs, 
                        chrs = pos - 2 > -1 && "." != maskset.buffer[pos - 2] ? maskset.buffer[pos - 2] + chrs : "0" + chrs) : chrs = "00" + chrs, 
                        new RegExp("25[0-5]|2[0-4][0-9]|[01][0-9][0-9]").test(chrs);
                    },
                    cardinality: 1
                }
            }
        },
        email: {
            mask: "*{1,64}[.*{1,64}][.*{1,64}][.*{1,64}]@*{1,64}[.*{2,64}][.*{2,6}][.*{1,2}]",
            greedy: !1,
            onBeforePaste: function(pastedValue, opts) {
                return pastedValue = pastedValue.toLowerCase(), pastedValue.replace("mailto:", "");
            },
            definitions: {
                "*": {
                    validator: "[0-9A-Za-z!#$%&'*+/=?^_`{|}~-]",
                    cardinality: 1,
                    casing: "lower"
                }
            }
        }
    }), $.fn.inputmask;
}(jQuery), function($) {
    return $.extend($.inputmask.defaults.aliases, {
        numeric: {
            mask: function(opts) {
                function autoEscape(txt) {
                    for (var escapedTxt = "", i = 0; i < txt.length; i++) escapedTxt += opts.definitions[txt[i]] ? "\\" + txt[i] : txt[i];
                    return escapedTxt;
                }
                if (0 !== opts.repeat && isNaN(opts.integerDigits) && (opts.integerDigits = opts.repeat), 
                opts.repeat = 0, opts.groupSeparator == opts.radixPoint && ("." == opts.radixPoint ? opts.groupSeparator = "," : "," == opts.radixPoint ? opts.groupSeparator = "." : opts.groupSeparator = ""), 
                " " === opts.groupSeparator && (opts.skipOptionalPartCharacter = void 0), 
                opts.autoGroup = opts.autoGroup && "" != opts.groupSeparator, opts.autoGroup && ("string" == typeof opts.groupSize && isFinite(opts.groupSize) && (opts.groupSize = parseInt(opts.groupSize)), 
                isFinite(opts.integerDigits))) {
                    var seps = Math.floor(opts.integerDigits / opts.groupSize), mod = opts.integerDigits % opts.groupSize;
                    opts.integerDigits = parseInt(opts.integerDigits) + (0 == mod ? seps - 1 : seps);
                }
                opts.placeholder.length > 1 && (opts.placeholder = opts.placeholder.charAt(0)), 
                opts.radixFocus = opts.radixFocus && "0" == opts.placeholder, opts.definitions[";"] = opts.definitions["~"];
                var mask = autoEscape(opts.prefix);
                return mask += "[+]", mask += "~{1," + opts.integerDigits + "}", 
                void 0 != opts.digits && (isNaN(opts.digits) || parseInt(opts.digits) > 0) && (mask += opts.digitsOptional ? "[" + (opts.decimalProtect ? ":" : opts.radixPoint) + ";{" + opts.digits + "}]" : (opts.decimalProtect ? ":" : opts.radixPoint) + ";{" + opts.digits + "}"), 
                "" != opts.negationSymbol.back && (mask += "[-]"), mask += autoEscape(opts.suffix), 
                opts.greedy = !1, mask;
            },
            placeholder: "",
            greedy: !1,
            digits: "*",
            digitsOptional: !0,
            groupSeparator: "",
            radixPoint: ".",
            radixFocus: !0,
            groupSize: 3,
            autoGroup: !1,
            allowPlus: !0,
            allowMinus: !0,
            negationSymbol: {
                front: "-",
                back: ""
            },
            integerDigits: "+",
            prefix: "",
            suffix: "",
            rightAlign: !0,
            decimalProtect: !0,
            min: void 0,
            max: void 0,
            postFormat: function(buffer, pos, reformatOnly, opts) {
                var suffixStripped = !1;
                buffer.length >= opts.suffix.length && buffer.join("").indexOf(opts.suffix) == buffer.length - opts.suffix.length && (buffer.length = buffer.length - opts.suffix.length, 
                suffixStripped = !0), pos = pos >= buffer.length ? buffer.length - 1 : pos < opts.prefix.length ? opts.prefix.length : pos;
                var needsRefresh = !1, charAtPos = buffer[pos];
                if ("" == opts.groupSeparator || -1 != $.inArray(opts.radixPoint, buffer) && pos >= $.inArray(opts.radixPoint, buffer) || new RegExp("[" + $.inputmask.escapeRegex(opts.negationSymbol.front) + "+]").test(charAtPos)) {
                    if (suffixStripped) for (var i = 0, l = opts.suffix.length; l > i; i++) buffer.push(opts.suffix.charAt(i));
                    return {
                        pos: pos
                    };
                }
                var cbuf = buffer.slice();
                charAtPos == opts.groupSeparator && (cbuf.splice(pos--, 1), charAtPos = cbuf[pos]), 
                reformatOnly ? cbuf[pos] = "?" : cbuf.splice(pos, 0, "?");
                var bufVal = cbuf.join(""), bufValOrigin = bufVal;
                if (bufVal.length > 0 && opts.autoGroup || reformatOnly && -1 != bufVal.indexOf(opts.groupSeparator)) {
                    var escapedGroupSeparator = $.inputmask.escapeRegex(opts.groupSeparator);
                    needsRefresh = 0 == bufVal.indexOf(opts.groupSeparator), bufVal = bufVal.replace(new RegExp(escapedGroupSeparator, "g"), "");
                    var radixSplit = bufVal.split(opts.radixPoint);
                    if (bufVal = "" == opts.radixPoint ? bufVal : radixSplit[0], 
                    bufVal != opts.prefix + "?0" && bufVal.length >= opts.groupSize + opts.prefix.length) for (var reg = new RegExp("([-+]?[\\d?]+)([\\d?]{" + opts.groupSize + "})"); reg.test(bufVal); ) bufVal = bufVal.replace(reg, "$1" + opts.groupSeparator + "$2"), 
                    bufVal = bufVal.replace(opts.groupSeparator + opts.groupSeparator, opts.groupSeparator);
                    "" != opts.radixPoint && radixSplit.length > 1 && (bufVal += opts.radixPoint + radixSplit[1]);
                }
                needsRefresh = bufValOrigin != bufVal, buffer.length = bufVal.length;
                for (var i = 0, l = bufVal.length; l > i; i++) buffer[i] = bufVal.charAt(i);
                var newPos = $.inArray("?", buffer);
                if (reformatOnly ? buffer[newPos] = charAtPos : buffer.splice(newPos, 1), 
                !needsRefresh && suffixStripped) for (var i = 0, l = opts.suffix.length; l > i; i++) buffer.push(opts.suffix.charAt(i));
                return {
                    pos: newPos,
                    refreshFromBuffer: needsRefresh,
                    buffer: buffer
                };
            },
            onBeforeWrite: function(e, buffer, caretPos, opts) {
                if (e && "blur" == e.type) {
                    var maskedValue = buffer.join(""), processValue = maskedValue.replace(opts.prefix, "");
                    if (processValue = processValue.replace(opts.suffix, ""), processValue = processValue.replace(new RegExp($.inputmask.escapeRegex(opts.groupSeparator), "g"), ""), 
                    "," === opts.radixPoint && (processValue = processValue.replace($.inputmask.escapeRegex(opts.radixPoint), ".")), 
                    isFinite(processValue) && isFinite(opts.min) && parseFloat(processValue) < parseFloat(opts.min)) return $.extend(!0, {
                        refreshFromBuffer: !0,
                        buffer: (opts.prefix + opts.min).split("")
                    }, opts.postFormat((opts.prefix + opts.min).split(""), 0, !0, opts));
                    var tmpBufSplit = "" != opts.radixPoint ? buffer.join("").split(opts.radixPoint) : [ buffer.join("") ], matchRslt = tmpBufSplit[0].match(opts.regex.integerPart(opts)), matchRsltDigits = 2 == tmpBufSplit.length ? tmpBufSplit[1].match(opts.regex.integerNPart(opts)) : void 0;
                    !matchRslt || matchRslt[0] != opts.negationSymbol.front + "0" && matchRslt[0] != opts.negationSymbol.front && "+" != matchRslt[0] || void 0 != matchRsltDigits && !matchRsltDigits[0].match(/^0+$/) || buffer.splice(matchRslt.index, 1);
                    var radixPosition = $.inArray(opts.radixPoint, buffer);
                    if (-1 != radixPosition && isFinite(opts.digits) && !opts.digitsOptional) {
                        for (var i = 1; i <= opts.digits; i++) (void 0 == buffer[radixPosition + i] || buffer[radixPosition + i] == opts.placeholder.charAt(0)) && (buffer[radixPosition + i] = "0");
                        return {
                            refreshFromBuffer: !0,
                            buffer: buffer
                        };
                    }
                }
                if (opts.autoGroup) {
                    var rslt = opts.postFormat(buffer, caretPos - 1, !0, opts);
                    return rslt.caret = caretPos <= opts.prefix.length ? rslt.pos : rslt.pos + 1, 
                    rslt;
                }
            },
            regex: {
                integerPart: function(opts) {
                    return new RegExp("[" + $.inputmask.escapeRegex(opts.negationSymbol.front) + "+]?\\d+");
                },
                integerNPart: function(opts) {
                    return new RegExp("[\\d" + $.inputmask.escapeRegex(opts.groupSeparator) + "]+");
                }
            },
            signHandler: function(chrs, maskset, pos, strict, opts) {
                if (!strict && opts.allowMinus && "-" === chrs || opts.allowPlus && "+" === chrs) {
                    var matchRslt = maskset.buffer.join("").match(opts.regex.integerPart(opts));
                    if (matchRslt && matchRslt[0].length > 0) return maskset.buffer[matchRslt.index] == ("-" === chrs ? "+" : opts.negationSymbol.front) ? "-" == chrs ? "" != opts.negationSymbol.back ? {
                        pos: matchRslt.index,
                        c: opts.negationSymbol.front,
                        remove: matchRslt.index,
                        caret: pos,
                        insert: {
                            pos: maskset.buffer.length - opts.suffix.length - 1,
                            c: opts.negationSymbol.back
                        }
                    } : {
                        pos: matchRslt.index,
                        c: opts.negationSymbol.front,
                        remove: matchRslt.index,
                        caret: pos
                    } : "" != opts.negationSymbol.back ? {
                        pos: matchRslt.index,
                        c: "+",
                        remove: [ matchRslt.index, maskset.buffer.length - opts.suffix.length - 1 ],
                        caret: pos
                    } : {
                        pos: matchRslt.index,
                        c: "+",
                        remove: matchRslt.index,
                        caret: pos
                    } : maskset.buffer[matchRslt.index] == ("-" === chrs ? opts.negationSymbol.front : "+") ? "-" == chrs && "" != opts.negationSymbol.back ? {
                        remove: [ matchRslt.index, maskset.buffer.length - opts.suffix.length - 1 ],
                        caret: pos - 1
                    } : {
                        remove: matchRslt.index,
                        caret: pos - 1
                    } : "-" == chrs ? "" != opts.negationSymbol.back ? {
                        pos: matchRslt.index,
                        c: opts.negationSymbol.front,
                        caret: pos + 1,
                        insert: {
                            pos: maskset.buffer.length - opts.suffix.length,
                            c: opts.negationSymbol.back
                        }
                    } : {
                        pos: matchRslt.index,
                        c: opts.negationSymbol.front,
                        caret: pos + 1
                    } : {
                        pos: matchRslt.index,
                        c: chrs,
                        caret: pos + 1
                    };
                }
                return !1;
            },
            radixHandler: function(chrs, maskset, pos, strict, opts) {
                if (!strict && chrs === opts.radixPoint && opts.digits > 0) {
                    var radixPos = $.inArray(opts.radixPoint, maskset.buffer), integerValue = maskset.buffer.join("").match(opts.regex.integerPart(opts));
                    if (-1 != radixPos && maskset.validPositions[radixPos]) return maskset.validPositions[radixPos - 1] ? {
                        caret: radixPos + 1
                    } : {
                        pos: integerValue.index,
                        c: integerValue[0],
                        caret: radixPos + 1
                    };
                    if (!integerValue || "0" == integerValue[0] && integerValue.index + 1 != pos) return maskset.buffer[integerValue ? integerValue.index : pos] = "0", 
                    {
                        pos: (integerValue ? integerValue.index : pos) + 1
                    };
                }
                return !1;
            },
            leadingZeroHandler: function(chrs, maskset, pos, strict, opts) {
                var matchRslt = maskset.buffer.join("").match(opts.regex.integerNPart(opts)), radixPosition = $.inArray(opts.radixPoint, maskset.buffer);
                if (matchRslt && !strict && (-1 == radixPosition || radixPosition >= pos)) if (0 == matchRslt[0].indexOf("0")) {
                    pos < opts.prefix.length && (pos = matchRslt.index);
                    var _radixPosition = $.inArray(opts.radixPoint, maskset._buffer), digitsMatch = maskset._buffer && maskset.buffer.slice(radixPosition).join("") == maskset._buffer.slice(_radixPosition).join("") || 0 == parseInt(maskset.buffer.slice(radixPosition + 1).join("")), integerMatch = maskset._buffer && maskset.buffer.slice(matchRslt.index, radixPosition).join("") == maskset._buffer.slice(opts.prefix.length, _radixPosition).join("") || "0" == maskset.buffer.slice(matchRslt.index, radixPosition).join("");
                    if (-1 == radixPosition || digitsMatch && integerMatch) return maskset.buffer.splice(matchRslt.index, 1), 
                    pos = pos > matchRslt.index ? pos - 1 : matchRslt.index, {
                        pos: pos,
                        remove: matchRslt.index
                    };
                    if (matchRslt.index + 1 == pos || "0" == chrs) return maskset.buffer.splice(matchRslt.index, 1), 
                    pos = matchRslt.index, {
                        pos: pos,
                        remove: matchRslt.index
                    };
                } else if ("0" === chrs && pos <= matchRslt.index && matchRslt[0] != opts.groupSeparator) return !1;
                return !0;
            },
            postValidation: function(buffer, opts) {
                var isValid = !0, maskedValue = buffer.join(""), processValue = maskedValue.replace(opts.prefix, "");
                return processValue = processValue.replace(opts.suffix, ""), processValue = processValue.replace(new RegExp($.inputmask.escapeRegex(opts.groupSeparator), "g"), ""), 
                "," === opts.radixPoint && (processValue = processValue.replace($.inputmask.escapeRegex(opts.radixPoint), ".")), 
                processValue = processValue.replace(new RegExp("^" + $.inputmask.escapeRegex(opts.negationSymbol.front)), "-"), 
                processValue = processValue.replace(new RegExp($.inputmask.escapeRegex(opts.negationSymbol.back) + "$"), ""), 
                isFinite(processValue) && isFinite(opts.max) && (isValid = parseFloat(processValue) <= parseFloat(opts.max)), 
                isValid;
            },
            definitions: {
                "~": {
                    validator: function(chrs, maskset, pos, strict, opts) {
                        var isValid = opts.signHandler(chrs, maskset, pos, strict, opts);
                        if (!isValid && (isValid = opts.radixHandler(chrs, maskset, pos, strict, opts), 
                        !isValid && (isValid = strict ? new RegExp("[0-9" + $.inputmask.escapeRegex(opts.groupSeparator) + "]").test(chrs) : new RegExp("[0-9]").test(chrs), 
                        isValid === !0 && (isValid = opts.leadingZeroHandler(chrs, maskset, pos, strict, opts), 
                        isValid === !0)))) {
                            var radixPosition = $.inArray(opts.radixPoint, maskset.buffer);
                            isValid = opts.digitsOptional === !1 && pos > radixPosition && !strict ? {
                                pos: pos,
                                remove: pos
                            } : {
                                pos: pos
                            };
                        }
                        return isValid;
                    },
                    cardinality: 1,
                    prevalidator: null
                },
                "+": {
                    validator: function(chrs, maskset, pos, strict, opts) {
                        var isValid = opts.signHandler(chrs, maskset, pos, strict, opts);
                        return !isValid && (strict && opts.allowMinus && chrs === opts.negationSymbol.front || opts.allowMinus && "-" == chrs || opts.allowPlus && "+" == chrs) && (isValid = "-" == chrs ? "" != opts.negationSymbol.back ? {
                            pos: pos,
                            c: "-" === chrs ? opts.negationSymbol.front : "+",
                            caret: pos + 1,
                            insert: {
                                pos: maskset.buffer.length,
                                c: opts.negationSymbol.back
                            }
                        } : {
                            pos: pos,
                            c: "-" === chrs ? opts.negationSymbol.front : "+",
                            caret: pos + 1
                        } : !0), isValid;
                    },
                    cardinality: 1,
                    prevalidator: null,
                    placeholder: ""
                },
                "-": {
                    validator: function(chrs, maskset, pos, strict, opts) {
                        var isValid = opts.signHandler(chrs, maskset, pos, strict, opts);
                        return !isValid && strict && opts.allowMinus && chrs === opts.negationSymbol.back && (isValid = !0), 
                        isValid;
                    },
                    cardinality: 1,
                    prevalidator: null,
                    placeholder: ""
                },
                ":": {
                    validator: function(chrs, maskset, pos, strict, opts) {
                        var isValid = opts.signHandler(chrs, maskset, pos, strict, opts);
                        if (!isValid) {
                            var radix = "[" + $.inputmask.escapeRegex(opts.radixPoint) + "]";
                            isValid = new RegExp(radix).test(chrs), isValid && maskset.validPositions[pos] && maskset.validPositions[pos].match.placeholder == opts.radixPoint && (isValid = {
                                caret: pos + 1
                            });
                        }
                        return isValid;
                    },
                    cardinality: 1,
                    prevalidator: null,
                    placeholder: function(opts) {
                        return opts.radixPoint;
                    }
                }
            },
            insertMode: !0,
            autoUnmask: !1,
            unmaskAsNumber: !1,
            onUnMask: function(maskedValue, unmaskedValue, opts) {
                var processValue = maskedValue.replace(opts.prefix, "");
                return processValue = processValue.replace(opts.suffix, ""), processValue = processValue.replace(new RegExp($.inputmask.escapeRegex(opts.groupSeparator), "g"), ""), 
                opts.unmaskAsNumber ? (processValue = processValue.replace($.inputmask.escapeRegex.call(this, opts.radixPoint), "."), 
                Number(processValue)) : processValue;
            },
            isComplete: function(buffer, opts) {
                var maskedValue = buffer.join(""), bufClone = buffer.slice();
                if (opts.postFormat(bufClone, 0, !0, opts), bufClone.join("") != maskedValue) return !1;
                var processValue = maskedValue.replace(opts.prefix, "");
                return processValue = processValue.replace(opts.suffix, ""), processValue = processValue.replace(new RegExp($.inputmask.escapeRegex(opts.groupSeparator), "g"), ""), 
                "," === opts.radixPoint && (processValue = processValue.replace($.inputmask.escapeRegex(opts.radixPoint), ".")), 
                isFinite(processValue);
            },
            onBeforeMask: function(initialValue, opts) {
                if ("" != opts.radixPoint && isFinite(initialValue)) initialValue = initialValue.toString().replace(".", opts.radixPoint); else {
                    var kommaMatches = initialValue.match(/,/g), dotMatches = initialValue.match(/\./g);
                    dotMatches && kommaMatches ? dotMatches.length > kommaMatches.length ? (initialValue = initialValue.replace(/\./g, ""), 
                    initialValue = initialValue.replace(",", opts.radixPoint)) : kommaMatches.length > dotMatches.length ? (initialValue = initialValue.replace(/,/g, ""), 
                    initialValue = initialValue.replace(".", opts.radixPoint)) : initialValue = initialValue.indexOf(".") < initialValue.indexOf(",") ? initialValue.replace(/\./g, "") : initialValue = initialValue.replace(/,/g, "") : initialValue = initialValue.replace(new RegExp($.inputmask.escapeRegex(opts.groupSeparator), "g"), "");
                }
                return 0 == opts.digits && (-1 != initialValue.indexOf(".") ? initialValue = initialValue.substring(0, initialValue.indexOf(".")) : -1 != initialValue.indexOf(",") && (initialValue = initialValue.substring(0, initialValue.indexOf(",")))), 
                initialValue;
            },
            canClearPosition: function(maskset, position, lvp, strict, opts) {
                var positionInput = maskset.validPositions[position].input, canClear = positionInput != opts.radixPoint && isFinite(positionInput) || position == lvp || positionInput == opts.groupSeparator || positionInput == opts.negationSymbol.front || positionInput == opts.negationSymbol.back;
                if (canClear && isFinite(positionInput)) {
                    var matchRslt;
                    if (!strict && maskset.buffer) {
                        matchRslt = maskset.buffer.join("").substr(0, position).match(opts.regex.integerNPart(opts));
                        var pos = position + 1, isNull = null == matchRslt || 0 == parseInt(matchRslt[0].replace(new RegExp($.inputmask.escapeRegex(opts.groupSeparator), "g"), ""));
                        if (isNull) for (;maskset.validPositions[pos] && (maskset.validPositions[pos].input == opts.groupSeparator || "0" == maskset.validPositions[pos].input); ) delete maskset.validPositions[pos], 
                        pos++;
                    }
                    var buffer = [];
                    for (var vp in maskset.validPositions) buffer.push(maskset.validPositions[vp].input);
                    matchRslt = buffer.join("").match(opts.regex.integerNPart(opts));
                    var radixPosition = $.inArray(opts.radixPoint, maskset.buffer);
                    if (matchRslt && (-1 == radixPosition || radixPosition >= position)) if (0 == matchRslt[0].indexOf("0")) canClear = matchRslt.index != position || -1 == radixPosition; else {
                        var intPart = parseInt(matchRslt[0].replace(new RegExp($.inputmask.escapeRegex(opts.groupSeparator), "g"), ""));
                        -1 != radixPosition && 10 > intPart && "0" == opts.placeholder.charAt(0) && (maskset.validPositions[position].input = "0", 
                        maskset.p = opts.prefix.length + 1, canClear = !1);
                    }
                }
                return canClear;
            }
        },
        currency: {
            prefix: "$ ",
            groupSeparator: ",",
            alias: "numeric",
            placeholder: "0",
            autoGroup: !0,
            digits: 2,
            digitsOptional: !1,
            clearMaskOnLostFocus: !1
        },
        decimal: {
            alias: "numeric"
        },
        integer: {
            alias: "numeric",
            digits: "0",
            radixPoint: ""
        }
    }), $.fn.inputmask;
}(jQuery), function($) {
    return $.extend($.inputmask.defaults.aliases, {
        phone: {
            url: "phone-codes/phone-codes.js",
            countrycode: "",
            mask: function(opts) {
                opts.definitions["#"] = opts.definitions[9];
                var maskList = [];
                return $.ajax({
                    url: opts.url,
                    async: !1,
                    dataType: "json",
                    success: function(response) {
                        maskList = response;
                    },
                    error: function(xhr, ajaxOptions, thrownError) {
                        alert(thrownError + " - " + opts.url);
                    }
                }), maskList = maskList.sort(function(a, b) {
                    return (a.mask || a) < (b.mask || b) ? -1 : 1;
                });
            },
            keepStatic: !1,
            nojumps: !0,
            nojumpsThreshold: 1,
            onBeforeMask: function(value, opts) {
                var processedValue = value.replace(/^0/g, "");
                return (processedValue.indexOf(opts.countrycode) > 1 || -1 == processedValue.indexOf(opts.countrycode)) && (processedValue = "+" + opts.countrycode + processedValue), 
                processedValue;
            }
        },
        phonebe: {
            alias: "phone",
            url: "phone-codes/phone-be.js",
            countrycode: "32",
            nojumpsThreshold: 4
        }
    }), $.fn.inputmask;
}(jQuery), function($) {
    return $.extend($.inputmask.defaults.aliases, {
        Regex: {
            mask: "r",
            greedy: !1,
            repeat: "*",
            regex: null,
            regexTokens: null,
            tokenizer: /\[\^?]?(?:[^\\\]]+|\\[\S\s]?)*]?|\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9][0-9]*|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|c[A-Za-z]|[\S\s]?)|\((?:\?[:=!]?)?|(?:[?*+]|\{[0-9]+(?:,[0-9]*)?\})\??|[^.?*+^${[()|\\]+|./g,
            quantifierFilter: /[0-9]+[^,]/,
            isComplete: function(buffer, opts) {
                return new RegExp(opts.regex).test(buffer.join(""));
            },
            definitions: {
                r: {
                    validator: function(chrs, maskset, pos, strict, opts) {
                        function regexToken(isGroup, isQuantifier) {
                            this.matches = [], this.isGroup = isGroup || !1, this.isQuantifier = isQuantifier || !1, 
                            this.quantifier = {
                                min: 1,
                                max: 1
                            }, this.repeaterPart = void 0;
                        }
                        function analyseRegex() {
                            var match, m, currentToken = new regexToken(), opengroups = [];
                            for (opts.regexTokens = []; match = opts.tokenizer.exec(opts.regex); ) switch (m = match[0], 
                            m.charAt(0)) {
                              case "(":
                                opengroups.push(new regexToken(!0));
                                break;

                              case ")":
                                var groupToken = opengroups.pop();
                                opengroups.length > 0 ? opengroups[opengroups.length - 1].matches.push(groupToken) : currentToken.matches.push(groupToken);
                                break;

                              case "{":
                              case "+":
                              case "*":
                                var quantifierToken = new regexToken(!1, !0);
                                m = m.replace(/[{}]/g, "");
                                var mq = m.split(","), mq0 = isNaN(mq[0]) ? mq[0] : parseInt(mq[0]), mq1 = 1 == mq.length ? mq0 : isNaN(mq[1]) ? mq[1] : parseInt(mq[1]);
                                if (quantifierToken.quantifier = {
                                    min: mq0,
                                    max: mq1
                                }, opengroups.length > 0) {
                                    var matches = opengroups[opengroups.length - 1].matches;
                                    if (match = matches.pop(), !match.isGroup) {
                                        var groupToken = new regexToken(!0);
                                        groupToken.matches.push(match), match = groupToken;
                                    }
                                    matches.push(match), matches.push(quantifierToken);
                                } else {
                                    if (match = currentToken.matches.pop(), !match.isGroup) {
                                        var groupToken = new regexToken(!0);
                                        groupToken.matches.push(match), match = groupToken;
                                    }
                                    currentToken.matches.push(match), currentToken.matches.push(quantifierToken);
                                }
                                break;

                              default:
                                opengroups.length > 0 ? opengroups[opengroups.length - 1].matches.push(m) : currentToken.matches.push(m);
                            }
                            currentToken.matches.length > 0 && opts.regexTokens.push(currentToken);
                        }
                        function validateRegexToken(token, fromGroup) {
                            var isvalid = !1;
                            fromGroup && (regexPart += "(", openGroupCount++);
                            for (var mndx = 0; mndx < token.matches.length; mndx++) {
                                var matchToken = token.matches[mndx];
                                if (1 == matchToken.isGroup) isvalid = validateRegexToken(matchToken, !0); else if (1 == matchToken.isQuantifier) {
                                    var crrntndx = $.inArray(matchToken, token.matches), matchGroup = token.matches[crrntndx - 1], regexPartBak = regexPart;
                                    if (isNaN(matchToken.quantifier.max)) {
                                        for (;matchToken.repeaterPart && matchToken.repeaterPart != regexPart && matchToken.repeaterPart.length > regexPart.length && !(isvalid = validateRegexToken(matchGroup, !0)); );
                                        isvalid = isvalid || validateRegexToken(matchGroup, !0), 
                                        isvalid && (matchToken.repeaterPart = regexPart), 
                                        regexPart = regexPartBak + matchToken.quantifier.max;
                                    } else {
                                        for (var i = 0, qm = matchToken.quantifier.max - 1; qm > i && !(isvalid = validateRegexToken(matchGroup, !0)); i++);
                                        regexPart = regexPartBak + "{" + matchToken.quantifier.min + "," + matchToken.quantifier.max + "}";
                                    }
                                } else if (void 0 != matchToken.matches) for (var k = 0; k < matchToken.length && !(isvalid = validateRegexToken(matchToken[k], fromGroup)); k++); else {
                                    var testExp;
                                    if ("[" == matchToken.charAt(0)) {
                                        testExp = regexPart, testExp += matchToken;
                                        for (var j = 0; openGroupCount > j; j++) testExp += ")";
                                        var exp = new RegExp("^(" + testExp + ")$");
                                        isvalid = exp.test(bufferStr);
                                    } else for (var l = 0, tl = matchToken.length; tl > l; l++) if ("\\" != matchToken.charAt(l)) {
                                        testExp = regexPart, testExp += matchToken.substr(0, l + 1), 
                                        testExp = testExp.replace(/\|$/, "");
                                        for (var j = 0; openGroupCount > j; j++) testExp += ")";
                                        var exp = new RegExp("^(" + testExp + ")$");
                                        if (isvalid = exp.test(bufferStr)) break;
                                    }
                                    regexPart += matchToken;
                                }
                                if (isvalid) break;
                            }
                            return fromGroup && (regexPart += ")", openGroupCount--), 
                            isvalid;
                        }
                        null == opts.regexTokens && analyseRegex();
                        var cbuffer = maskset.buffer.slice(), regexPart = "", isValid = !1, openGroupCount = 0;
                        cbuffer.splice(pos, 0, chrs);
                        for (var bufferStr = cbuffer.join(""), i = 0; i < opts.regexTokens.length; i++) {
                            var regexToken = opts.regexTokens[i];
                            if (isValid = validateRegexToken(regexToken, regexToken.isGroup)) break;
                        }
                        return isValid;
                    },
                    cardinality: 1
                }
            }
        }
    }), $.fn.inputmask;
}(jQuery);

(function(factory) {
    "use strict";
    if (typeof define === "function" && define.amd) {
        define([ "jquery" ], factory);
    } else if (typeof exports === "object") {
        factory(require("jquery"));
    } else {
        factory(window.jQuery);
    }
})(function($) {
    "use strict";
    var counter = 0;
    $.ajaxTransport("iframe", function(options) {
        if (options.async) {
            var initialIframeSrc = options.initialIframeSrc || "javascript:false;", form, iframe, addParamChar;
            return {
                send: function(_, completeCallback) {
                    form = $('<form style="display:none;"></form>');
                    form.attr("accept-charset", options.formAcceptCharset);
                    addParamChar = /\?/.test(options.url) ? "&" : "?";
                    if (options.type === "DELETE") {
                        options.url = options.url + addParamChar + "_method=DELETE";
                        options.type = "POST";
                    } else if (options.type === "PUT") {
                        options.url = options.url + addParamChar + "_method=PUT";
                        options.type = "POST";
                    } else if (options.type === "PATCH") {
                        options.url = options.url + addParamChar + "_method=PATCH";
                        options.type = "POST";
                    }
                    counter += 1;
                    iframe = $('<iframe src="' + initialIframeSrc + '" name="iframe-transport-' + counter + '"></iframe>').bind("load", function() {
                        var fileInputClones, paramNames = $.isArray(options.paramName) ? options.paramName : [ options.paramName ];
                        iframe.unbind("load").bind("load", function() {
                            var response;
                            try {
                                response = iframe.contents();
                                if (!response.length || !response[0].firstChild) {
                                    throw new Error();
                                }
                            } catch (e) {
                                response = undefined;
                            }
                            completeCallback(200, "success", {
                                iframe: response
                            });
                            $('<iframe src="' + initialIframeSrc + '"></iframe>').appendTo(form);
                            window.setTimeout(function() {
                                form.remove();
                            }, 0);
                        });
                        form.prop("target", iframe.prop("name")).prop("action", options.url).prop("method", options.type);
                        if (options.formData) {
                            $.each(options.formData, function(index, field) {
                                $('<input type="hidden"/>').prop("name", field.name).val(field.value).appendTo(form);
                            });
                        }
                        if (options.fileInput && options.fileInput.length && options.type === "POST") {
                            fileInputClones = options.fileInput.clone();
                            options.fileInput.after(function(index) {
                                return fileInputClones[index];
                            });
                            if (options.paramName) {
                                options.fileInput.each(function(index) {
                                    $(this).prop("name", paramNames[index] || options.paramName);
                                });
                            }
                            form.append(options.fileInput).prop("enctype", "multipart/form-data").prop("encoding", "multipart/form-data");
                            options.fileInput.removeAttr("form");
                        }
                        form.submit();
                        if (fileInputClones && fileInputClones.length) {
                            options.fileInput.each(function(index, input) {
                                var clone = $(fileInputClones[index]);
                                $(input).prop("name", clone.prop("name")).attr("form", clone.attr("form"));
                                clone.replaceWith(input);
                            });
                        }
                    });
                    form.append(iframe).appendTo(document.body);
                },
                abort: function() {
                    if (iframe) {
                        iframe.unbind("load").prop("src", initialIframeSrc);
                    }
                    if (form) {
                        form.remove();
                    }
                }
            };
        }
    });
    $.ajaxSetup({
        converters: {
            "iframe text": function(iframe) {
                return iframe && $(iframe[0].body).text();
            },
            "iframe json": function(iframe) {
                return iframe && $.parseJSON($(iframe[0].body).text());
            },
            "iframe html": function(iframe) {
                return iframe && $(iframe[0].body).html();
            },
            "iframe xml": function(iframe) {
                var xmlDoc = iframe && iframe[0];
                return xmlDoc && $.isXMLDoc(xmlDoc) ? xmlDoc : $.parseXML(xmlDoc.XMLDocument && xmlDoc.XMLDocument.xml || $(xmlDoc.body).html());
            },
            "iframe script": function(iframe) {
                return iframe && $.globalEval($(iframe[0].body).text());
            }
        }
    });
});

(function() {
    var Dragster, __bind = function(fn, me) {
        return function() {
            return fn.apply(me, arguments);
        };
    };
    Dragster = function() {
        function Dragster(el) {
            this.el = el;
            this.dragleave = __bind(this.dragleave, this);
            this.dragenter = __bind(this.dragenter, this);
            if (this.supportsEventConstructors()) {
                this.first = false;
                this.second = false;
                this.el.addEventListener("dragenter", this.dragenter, false);
                this.el.addEventListener("dragleave", this.dragleave, false);
            }
        }
        Dragster.prototype.dragenter = function(event) {
            if (this.first) {
                return this.second = true;
            } else {
                this.first = true;
                return this.el.dispatchEvent(new CustomEvent("dragster:enter", {
                    bubbles: true,
                    cancelable: true,
                    detail: {
                        dataTransfer: event.dataTransfer
                    }
                }));
            }
        };
        Dragster.prototype.dragleave = function(event) {
            if (this.second) {
                this.second = false;
            } else if (this.first) {
                this.first = false;
            }
            if (!this.first && !this.second) {
                return this.el.dispatchEvent(new CustomEvent("dragster:leave", {
                    bubbles: true,
                    cancelable: true,
                    detail: {
                        dataTransfer: event.dataTransfer
                    }
                }));
            }
        };
        Dragster.prototype.removeListeners = function() {
            this.el.removeEventListener("dragenter", this.dragenter, false);
            return this.el.removeEventListener("dragleave", this.dragleave, false);
        };
        Dragster.prototype.supportsEventConstructors = function() {
            try {
                new CustomEvent("z");
            } catch (_error) {
                return false;
            }
            return true;
        };
        Dragster.prototype.reset = function() {
            this.first = false;
            return this.second = false;
        };
        return Dragster;
    }();
    if (typeof module === "undefined") {
        window.Dragster = Dragster;
    } else {
        module.exports = Dragster;
    }
}).call(this);

(function() {
    var Dropzone;
    Dropzone = function() {
        function Dropzone($elements, $options) {
            var defaults;
            if ($options == null) {
                $options = [];
            }
            defaults = {
                script: null,
                ajaxQueue: false,
                autoUpload: false,
                classDragOver: "is-dragover",
                onUploadingFiles: function(count, total) {},
                onSelectFiles: function(files, element) {},
                onSuccessFile: function(file, response, element) {},
                onComplete: function(files, element) {},
                onFileError: function(jqXHR, element) {},
                onFileFail: function(jqXHR, element) {}
            };
            this.options = $.extend(defaults, $options);
            this.files = [];
            $.each($($elements), function(_this) {
                return function(i, el) {
                    var element, file;
                    element = $(el);
                    file = element.find("input[type=file]");
                    element.data("pos", i);
                    file.on("change", function(e) {
                        var droppedFiles;
                        droppedFiles = $(e.currentTarget).prop("files");
                        _this.options.onSelectFiles(droppedFiles, element);
                        _this.files[element.data("pos")] = e.target.files;
                        if (_this.options.autoUpload) {
                            return _this.submit(element, e.target.files);
                        }
                    });
                    return _this.initDrag(element);
                };
            }(this));
        }
        Dropzone.prototype.initDrag = function(box) {
            var droppedFiles;
            if (this.isAdvancedUpload()) {
                droppedFiles = false;
                return box.on("drag dragstart dragend dragover dragenter dragleave drop", function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                }).on("dragover dragenter", function(_this) {
                    return function() {
                        box.addClass(_this.options.classDragOver);
                    };
                }(this)).on("dragleave dragend drop", function(_this) {
                    return function() {
                        box.removeClass(_this.options.classDragOver);
                    };
                }(this)).on("drop", function(_this) {
                    return function(e) {
                        droppedFiles = e.originalEvent.dataTransfer.files;
                        _this.options.onSelectFiles(droppedFiles, box);
                        if (_this.options.autoUpload) {
                            return _this.submit(box, droppedFiles);
                        } else {
                            return _this.files[box.data("pos")] = droppedFiles;
                        }
                    };
                }(this));
            }
        };
        Dropzone.prototype.startUpload = function(box) {
            var files;
            files = this.files[box.data("pos")];
            if (files) {
                return this.submit(box, files);
            }
        };
        Dropzone.prototype.submit = function(box, droppedFiles) {
            var ajax, file, inputname, j, key, len, myFormData, results, total_files, upload_files;
            if (box.hasClass("is-uploading")) {
                return false;
            }
            box.addClass("is-uploading");
            total_files = droppedFiles.length;
            upload_files = 1;
            inputname = box.find("input[type=file]").attr("name");
            this.options.onUploadingFiles(upload_files, total_files);
            results = [];
            for (key = j = 0, len = droppedFiles.length; j < len; key = ++j) {
                file = droppedFiles[key];
                myFormData = new FormData();
                myFormData.append(inputname + "[]", file);
                myFormData.append("position", key);
                ajax = this.options.ajaxQueue ? $.ajaxQueue : $.ajax;
                results.push(ajax({
                    url: this.options.script,
                    type: "POST",
                    data: myFormData,
                    processData: false,
                    contentType: false,
                    cache: false,
                    complete: function(_this) {
                        return function() {
                            upload_files++;
                            if (upload_files >= total_files + 1) {
                                _this.options.onComplete(droppedFiles, box);
                                _this.removeFiles(box);
                                return box.removeClass("is-uploading");
                            } else {
                                return _this.options.onUploadingFiles(upload_files, total_files);
                            }
                        };
                    }(this),
                    success: function(_this) {
                        return function(data) {
                            _this.options.onSuccessFile(file, data, box);
                        };
                    }(this),
                    fail: function(_this) {
                        return function(jqXHR) {
                            _this.options.onFileFail(jqXHR, box);
                        };
                    }(this),
                    error: function(_this) {
                        return function(jqXHR) {
                            _this.options.onFileError(jqXHR, box);
                        };
                    }(this)
                }));
            }
            return results;
        };
        Dropzone.prototype.removeFiles = function(box) {
            return this.files[box.data("pos")] = null;
        };
        Dropzone.prototype.isAdvancedUpload = function() {
            var div;
            div = document.createElement("div");
            return ("draggable" in div || "ondragstart" in div && "ondrop" in div) && "FormData" in window && "FileReader" in window;
        };
        Dropzone.prototype.isFormData = function() {
            return "FormData" in window;
        };
        Dropzone.prototype.isFileReader = function() {
            return "FileReader" in window;
        };
        Dropzone.prototype.isDraggable = function() {
            var div;
            div = document.createElement("div");
            return "draggable" in div || "ondragstart" in div && "ondrop" in div;
        };
        return Dropzone;
    }();
    if (typeof module === "undefined") {
        window.Dropzone = Dropzone;
    } else {
        module.exports = Dropzone;
    }
    return Dropzone;
}).call(this);

window = typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {};

document = window.document || {};

(function(factory, global) {
    if (typeof require === "function" && typeof exports === "object" && typeof module === "object") {
        factory(require("jquery"));
    } else if (typeof define === "function" && define.amd) {
        define([ "jquery" ], factory);
    } else {
        factory(global.jQuery);
    }
})(function($) {
    "use strict";
    var unique = 0;
    var eventStorage = {};
    var possibleEvents = {};
    var emojione = window.emojione;
    var readyCallbacks = [];
    function emojioneReady(fn) {
        if (emojione) {
            fn();
        } else {
            readyCallbacks.push(fn);
        }
    }
    var blankImg = "data:image/gif;base64,R0lGODlhAQABAJH/AP///wAAAMDAwAAAACH5BAEAAAIALAAAAAABAAEAAAICVAEAOw==";
    var slice = [].slice;
    var css_class = "emojionearea";
    var emojioneSupportMode = 0;
    var invisibleChar = "&#8203;";
    function trigger(self, event, args) {
        var result = true, j = 1;
        if (event) {
            event = event.toLowerCase();
            do {
                var _event = j == 1 ? "@" + event : event;
                if (eventStorage[self.id][_event] && eventStorage[self.id][_event].length) {
                    $.each(eventStorage[self.id][_event], function(i, fn) {
                        return result = fn.apply(self, args || []) !== false;
                    });
                }
            } while (result && !!j--);
        }
        return result;
    }
    function attach(self, element, events, target) {
        target = target || function(event, callerEvent) {
            return $(callerEvent.currentTarget);
        };
        $.each(events, function(event, link) {
            event = $.isArray(events) ? link : event;
            (possibleEvents[self.id][link] || (possibleEvents[self.id][link] = [])).push([ element, event, target ]);
        });
    }
    function getTemplate(template, unicode, shortname) {
        var imageType = emojione.imageType, imagePath;
        if (imageType == "svg") {
            imagePath = emojione.imagePathSVG;
        } else {
            imagePath = emojione.imagePathPNG;
        }
        var friendlyName = "";
        if (shortname) {
            friendlyName = shortname.substr(1, shortname.length - 2).replace(/_/g, " ").replace(/\w\S*/g, function(txt) {
                return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
            });
        }
        var fname = "";
        if (unicode.uc_base && emojioneSupportMode > 4) {
            fname = unicode.uc_base;
            unicode = unicode.uc_output.toUpperCase();
        } else {
            fname = unicode;
        }
        template = template.replace("{name}", shortname || "").replace("{friendlyName}", friendlyName).replace("{img}", imagePath + (emojioneSupportMode < 2 ? fname.toUpperCase() : fname) + "." + imageType).replace("{uni}", unicode);
        if (shortname) {
            template = template.replace("{alt}", emojione.shortnameToUnicode(shortname));
        } else {
            template = template.replace("{alt}", emojione.convert(unicode));
        }
        return template;
    }
    function shortnameTo(str, template, clear) {
        return str.replace(/:?\+?[\w_\-]+:?/g, function(shortname) {
            shortname = ":" + shortname.replace(/:$/, "").replace(/^:/, "") + ":";
            var unicode = emojione.emojioneList[shortname];
            if (unicode) {
                if (emojioneSupportMode > 4) {
                    return getTemplate(template, unicode, shortname);
                } else {
                    if (emojioneSupportMode > 3) unicode = unicode.unicode;
                    return getTemplate(template, unicode[unicode.length - 1], shortname);
                }
            }
            return clear ? "" : shortname;
        });
    }
    function pasteHtmlAtCaret(html) {
        var sel, range;
        if (window.getSelection) {
            sel = window.getSelection();
            if (sel.getRangeAt && sel.rangeCount) {
                range = sel.getRangeAt(0);
                range.deleteContents();
                var el = document.createElement("div");
                el.innerHTML = html;
                var frag = document.createDocumentFragment(), node, lastNode;
                while (node = el.firstChild) {
                    lastNode = frag.appendChild(node);
                }
                range.insertNode(frag);
                if (lastNode) {
                    range = range.cloneRange();
                    range.setStartAfter(lastNode);
                    range.collapse(true);
                    sel.removeAllRanges();
                    sel.addRange(range);
                }
            }
        } else if (document.selection && document.selection.type != "Control") {
            document.selection.createRange().pasteHTML(html);
        }
    }
    function getEmojioneVersion() {
        return window.emojioneVersion || "3.1.2";
    }
    function isObject(variable) {
        return typeof variable === "object";
    }
    function detectVersion(emojione) {
        var version;
        if (emojione.cacheBustParam) {
            version = emojione.cacheBustParam;
            if (!isObject(emojione["jsEscapeMap"])) return "1.5.2";
            if (version === "?v=1.2.4") return "2.0.0";
            if (version === "?v=2.0.1") return "2.1.0";
            if (version === "?v=2.1.1") return "2.1.1";
            if (version === "?v=2.1.2") return "2.1.2";
            if (version === "?v=2.1.3") return "2.1.3";
            if (version === "?v=2.1.4") return "2.1.4";
            if (version === "?v=2.2.7") return "2.2.7";
            return "2.2.7";
        } else {
            return emojione.emojiVersion;
        }
    }
    function getSupportMode(version) {
        switch (version) {
          case "1.5.2":
            return 0;

          case "2.0.0":
            return 1;

          case "2.1.0":
          case "2.1.1":
            return 2;

          case "2.1.2":
            return 3;

          case "2.1.3":
          case "2.1.4":
          case "2.2.7":
            return 4;

          case "3.0.1":
          case "3.0.2":
          case "3.0.3":
          case "3.0":
            return 5;

          case "3.1.0":
          case "3.1.1":
          case "3.1.2":
          case "3.1":
          default:
            return 6;
        }
    }
    function getDefaultOptions() {
        if ($.fn.emojioneArea && $.fn.emojioneArea.defaults) {
            return $.fn.emojioneArea.defaults;
        }
        var defaultOptions = {
            attributes: {
                dir: "ltr",
                spellcheck: false,
                autocomplete: "off",
                autocorrect: "off",
                autocapitalize: "off"
            },
            search: true,
            placeholder: null,
            emojiPlaceholder: ":smiley:",
            searchPlaceholder: "SEARCH",
            container: null,
            hideSource: true,
            shortnames: true,
            sprite: true,
            pickerPosition: "top",
            filtersPosition: "top",
            searchPosition: "top",
            hidePickerOnBlur: true,
            buttonTitle: "Use the TAB key to insert emoji faster",
            tones: true,
            tonesStyle: "bullet",
            inline: null,
            saveEmojisAs: "unicode",
            shortcuts: true,
            autocomplete: true,
            autocompleteTones: false,
            standalone: false,
            useInternalCDN: true,
            imageType: "png",
            recentEmojis: true,
            textcomplete: {
                maxCount: 15,
                placement: null
            }
        };
        var supportMode = !emojione ? getSupportMode(getEmojioneVersion()) : getSupportMode(detectVersion(emojione));
        if (supportMode > 4) {
            defaultOptions.filters = {
                tones: {
                    title: "Diversity",
                    emoji: "open_hands raised_hands palms_up_together clap pray thumbsup thumbsdown punch fist left_facing_fist right_facing_fist " + "fingers_crossed v metal love_you_gesture ok_hand point_left point_right point_up_2 point_down point_up raised_hand " + "raised_back_of_hand hand_splayed vulcan wave call_me muscle middle_finger writing_hand selfie nail_care ear " + "nose baby boy girl man woman blond-haired_woman blond-haired_man older_man older_woman " + "man_with_chinese_cap woman_wearing_turban man_wearing_turban woman_police_officer " + "man_police_officer woman_construction_worker man_construction_worker " + "woman_guard man_guard woman_detective man_detective woman_health_worker man_health_worker " + "woman_farmer man_farmer woman_cook man_cook woman_student man_student woman_singer man_singer woman_teacher " + "man_teacher woman_factory_worker man_factory_worker woman_technologist man_technologist woman_office_worker " + "man_office_worker woman_mechanic man_mechanic woman_scientist man_scientist woman_artist man_artist " + "woman_firefighter man_firefighter woman_pilot man_pilot woman_astronaut man_astronaut woman_judge " + "man_judge mrs_claus santa princess prince bride_with_veil man_in_tuxedo angel pregnant_woman " + "breast_feeding woman_bowing man_bowing man_tipping_hand woman_tipping_hand " + "man_gesturing_no woman_gesturing_no man_gesturing_ok woman_gesturing_ok " + "man_raising_hand woman_raising_hand woman_facepalming man_facepalming " + "woman_shrugging man_shrugging man_pouting woman_pouting " + "man_frowning woman_frowning man_getting_haircut woman_getting_haircut " + "man_getting_face_massage woman_getting_face_massage man_in_business_suit_levitating dancer man_dancing " + "woman_walking man_walking woman_running man_running adult child older_adult " + "bearded_person woman_with_headscarf woman_mage man_mage " + "woman_fairy man_fairy woman_vampire man_vampire mermaid merman woman_elf man_elf " + "snowboarder woman_lifting_weights man_lifting_weights woman_cartwheeling " + "man_cartwheeling woman_bouncing_ball man_bouncing_ball " + "woman_playing_handball man_playing_handball woman_golfing man_golfing " + "woman_surfing man_surfing woman_swimming man_swimming woman_playing_water_polo " + "man_playing_water_polo woman_rowing_boat man_rowing_boat " + "horse_racing woman_biking man_biking woman_mountain_biking " + "man_mountain_biking woman_juggling man_juggling " + "woman_in_steamy_room man_in_steamy_room woman_climbing " + "man_climbing woman_in_lotus_position man_in_lotus_position bath person_in_bed"
                },
                recent: {
                    icon: "clock3",
                    title: "Recent",
                    emoji: ""
                },
                smileys_people: {
                    icon: "yum",
                    title: "Smileys & People",
                    emoji: "grinning smiley smile grin laughing sweat_smile joy rofl relaxed blush innocent slight_smile upside_down " + "wink relieved crazy_face star_struck heart_eyes kissing_heart kissing kissing_smiling_eyes kissing_closed_eyes yum " + "stuck_out_tongue_winking_eye stuck_out_tongue_closed_eyes stuck_out_tongue money_mouth hugging nerd sunglasses " + "cowboy smirk unamused disappointed pensive worried face_with_raised_eyebrow face_with_monocle confused slight_frown " + "frowning2 persevere confounded tired_face weary triumph angry rage face_with_symbols_over_mouth " + "no_mouth neutral_face expressionless hushed frowning anguished open_mouth astonished dizzy_face exploding_head flushed scream " + "fearful cold_sweat cry disappointed_relieved drooling_face sob sweat sleepy sleeping rolling_eyes thinking " + "shushing_face face_with_hand_over_mouth lying_face grimacing zipper_mouth face_vomiting nauseated_face sneezing_face mask thermometer_face " + "head_bandage smiling_imp imp japanese_ogre japanese_goblin poop ghost skull skull_crossbones alien space_invader " + "robot jack_o_lantern clown smiley_cat smile_cat joy_cat heart_eyes_cat smirk_cat kissing_cat scream_cat crying_cat_face " + "pouting_cat open_hands raised_hands palms_up_together clap pray handshake thumbsup thumbsdown punch fist left_facing_fist " + "right_facing_fist fingers_crossed v metal love_you_gesture ok_hand point_left point_right point_up_2 point_down point_up " + "raised_hand raised_back_of_hand hand_splayed vulcan wave call_me muscle middle_finger writing_hand selfie " + "nail_care ring lipstick kiss lips tongue ear nose footprints eye eyes speaking_head bust_in_silhouette " + "busts_in_silhouette baby boy girl man woman blond-haired_woman blond_haired_man older_man older_woman " + "man_with_chinese_cap woman_wearing_turban man_wearing_turban woman_police_officer police_officer " + "woman_construction_worker construction_worker woman_guard guard woman_detective detective woman_health_worker " + "man_health_worker woman_farmer man_farmer woman_cook man_cook woman_student man_student woman_singer man_singer " + "woman_teacher man_teacher woman_factory_worker man_factory_worker woman_technologist man_technologist " + "woman_office_worker man_office_worker woman_mechanic man_mechanic woman_scientist man_scientist woman_artist " + "man_artist woman_firefighter man_firefighter woman_pilot man_pilot woman_astronaut man_astronaut woman_judge " + "man_judge mrs_claus santa princess prince bride_with_veil man_in_tuxedo angel pregnant_woman breast_feeding woman_bowing " + "man_bowing woman_tipping_hand man_tipping_hand woman_gesturing_no man_gesturing_no woman_gesturing_ok " + "man_gesturing_ok woman_raising_hand man_raising_hand woman_facepalming man_facepalming woman_shrugging " + "man_shrugging woman_pouting man_pouting woman_frowning man_frowning woman_getting_haircut man_getting_haircut " + "woman_getting_face_massage man_getting_face_massage man_in_business_suit_levitating dancer man_dancing women_with_bunny_ears_partying " + "men_with_bunny_ears_partying woman_walking man_walking woman_running man_running couple two_women_holding_hands " + "two_men_holding_hands couple_with_heart couple_ww couple_mm couplekiss kiss_ww kiss_mm family family_mwg family_mwgb " + "family_mwbb family_mwgg family_wwb family_wwg family_wwgb family_wwbb family_wwgg family_mmb family_mmg family_mmgb " + "family_mmbb family_mmgg family_woman_boy family_woman_girl family_woman_girl_boy family_woman_boy_boy " + "family_woman_girl_girl family_man_boy family_man_girl family_man_girl_boy family_man_boy_boy family_man_girl_girl " + "bearded_person woman_with_headscarf woman_mage man_mage woman_fairy man_fairy woman_vampire man_vampire " + "mermaid merman woman_elf man_elf woman_genie man_genie woman_zombie man_zombie " + "womans_clothes shirt jeans necktie dress bikini kimono high_heel sandal boot mans_shoe athletic_shoe womans_hat " + "tophat mortar_board crown helmet_with_cross school_satchel pouch purse handbag briefcase eyeglasses dark_sunglasses " + "closed_umbrella umbrella2 brain billed_cap scarf gloves coat socks "
                },
                animals_nature: {
                    icon: "hamster",
                    title: "Animals & Nature",
                    emoji: "dog cat mouse hamster rabbit fox bear panda_face koala tiger lion_face cow pig pig_nose frog monkey_face see_no_evil " + "hear_no_evil speak_no_evil monkey chicken penguin bird baby_chick hatching_chick hatched_chick duck eagle owl bat wolf boar " + "horse unicorn bee bug butterfly snail shell beetle ant spider spider_web turtle snake lizard scorpion crab squid octopus shrimp " + "tropical_fish fish blowfish dolphin shark whale whale2 crocodile leopard tiger2 water_buffalo ox cow2 deer dromedary_camel camel " + "elephant rhino gorilla racehorse pig2 goat ram sheep dog2 poodle cat2 rooster turkey dove rabbit2 mouse2 rat chipmunk dragon " + "giraffe zebra hedgehog sauropod t_rex cricket dragon_face feet cactus christmas_tree evergreen_tree deciduous_tree palm_tree seedling herb shamrock four_leaf_clover " + "bamboo tanabata_tree leaves fallen_leaf maple_leaf mushroom ear_of_rice bouquet tulip rose wilted_rose sunflower blossom " + "cherry_blossom hibiscus earth_americas earth_africa earth_asia full_moon waning_gibbous_moon last_quarter_moon " + "waning_crescent_moon new_moon waxing_crescent_moon first_quarter_moon waxing_gibbous_moon new_moon_with_face " + "full_moon_with_face sun_with_face first_quarter_moon_with_face last_quarter_moon_with_face crescent_moon dizzy star star2 " + "sparkles zap fire boom comet sunny white_sun_small_cloud partly_sunny white_sun_cloud white_sun_rain_cloud rainbow cloud " + "cloud_rain thunder_cloud_rain cloud_lightning cloud_snow snowman2 snowman snowflake wind_blowing_face dash cloud_tornado " + "fog ocean droplet sweat_drops umbrella "
                },
                food_drink: {
                    icon: "pizza",
                    title: "Food & Drink",
                    emoji: "green_apple apple pear tangerine lemon banana watermelon grapes strawberry melon cherries peach pineapple kiwi " + "avocado tomato eggplant cucumber carrot corn hot_pepper potato sweet_potato chestnut peanuts honey_pot croissant " + "bread french_bread cheese egg cooking bacon pancakes fried_shrimp poultry_leg meat_on_bone pizza hotdog hamburger " + "fries stuffed_flatbread taco burrito salad shallow_pan_of_food spaghetti ramen stew fish_cake sushi bento curry " + "rice_ball rice rice_cracker oden dango shaved_ice ice_cream icecream cake birthday custard lollipop candy " + "chocolate_bar popcorn doughnut cookie milk baby_bottle coffee tea sake beer beers champagne_glass wine_glass " + "tumbler_glass cocktail tropical_drink champagne spoon fork_and_knife fork_knife_plate dumpling fortune_cookie " + "takeout_box chopsticks bowl_with_spoon cup_with_straw coconut broccoli pie pretzel cut_of_meat sandwich canned_food"
                },
                activity: {
                    icon: "basketball",
                    title: "Activity",
                    emoji: "soccer basketball football baseball tennis volleyball rugby_football 8ball ping_pong badminton goal hockey field_hockey " + "cricket_game golf bow_and_arrow fishing_pole_and_fish boxing_glove martial_arts_uniform ice_skate ski skier snowboarder " + "woman_lifting_weights man_lifting_weights person_fencing women_wrestling men_wrestling woman_cartwheeling " + "man_cartwheeling woman_bouncing_ball man_bouncing_ball woman_playing_handball man_playing_handball woman_golfing " + "man_golfing woman_surfing man_surfing woman_swimming man_swimming woman_playing_water_polo " + "man_playing_water_polo woman_rowing_boat man_rowing_boat horse_racing woman_biking man_biking woman_mountain_biking man_mountain_biking " + "woman_in_steamy_room man_in_steamy_room woman_climbing man_climbing woman_in_lotus_position man_in_lotus_position " + "running_shirt_with_sash medal military_medal first_place second_place " + "third_place trophy rosette reminder_ribbon ticket tickets circus_tent woman_juggling man_juggling performing_arts art " + "clapper microphone headphones musical_score musical_keyboard drum saxophone trumpet guitar violin game_die dart bowling " + "video_game slot_machine sled curling_stone "
                },
                travel_places: {
                    icon: "rocket",
                    title: "Travel & Places",
                    emoji: "red_car taxi blue_car bus trolleybus race_car police_car ambulance fire_engine minibus truck articulated_lorry tractor " + "scooter bike motor_scooter motorcycle rotating_light oncoming_police_car oncoming_bus oncoming_automobile oncoming_taxi " + "aerial_tramway mountain_cableway suspension_railway railway_car train mountain_railway monorail bullettrain_side " + "bullettrain_front light_rail steam_locomotive train2 metro tram station helicopter airplane_small airplane " + "airplane_departure airplane_arriving rocket satellite_orbital seat canoe sailboat motorboat speedboat cruise_ship " + "ferry ship anchor construction fuelpump busstop vertical_traffic_light traffic_light map moyai statue_of_liberty " + "fountain tokyo_tower european_castle japanese_castle stadium ferris_wheel roller_coaster carousel_horse beach_umbrella " + "beach island mountain mountain_snow mount_fuji volcano desert camping tent railway_track motorway construction_site " + "factory house house_with_garden homes house_abandoned office department_store post_office european_post_office hospital " + "bank hotel convenience_store school love_hotel wedding classical_building church mosque synagogue kaaba shinto_shrine " + "japan rice_scene park sunrise sunrise_over_mountains stars sparkler fireworks city_sunset city_dusk cityscape " + "night_with_stars milky_way bridge_at_night foggy flying_saucer"
                },
                objects: {
                    icon: "bulb",
                    title: "Objects",
                    emoji: "watch iphone calling computer keyboard desktop printer mouse_three_button trackball joystick compression minidisc " + "floppy_disk cd dvd vhs camera camera_with_flash video_camera movie_camera projector film_frames telephone_receiver " + "telephone pager fax tv radio microphone2 level_slider control_knobs stopwatch timer alarm_clock clock hourglass " + "hourglass_flowing_sand satellite battery electric_plug bulb flashlight candle wastebasket oil money_with_wings " + "dollar yen euro pound moneybag credit_card gem scales wrench hammer hammer_pick tools pick nut_and_bolt gear " + "chains gun bomb knife dagger crossed_swords shield smoking coffin urn amphora crystal_ball prayer_beads barber " + "alembic telescope microscope hole pill syringe thermometer toilet potable_water shower bathtub bath bellhop key " + "key2 door couch bed sleeping_accommodation frame_photo shopping_bags shopping_cart gift balloon flags ribbon " + "confetti_ball tada dolls izakaya_lantern wind_chime envelope envelope_with_arrow incoming_envelope e-mail " + "love_letter inbox_tray outbox_tray package label mailbox_closed mailbox mailbox_with_mail mailbox_with_no_mail " + "postbox postal_horn scroll page_with_curl page_facing_up bookmark_tabs bar_chart chart_with_upwards_trend " + "chart_with_downwards_trend notepad_spiral calendar_spiral calendar date card_index card_box ballot_box " + "file_cabinet clipboard file_folder open_file_folder dividers newspaper2 newspaper notebook " + "notebook_with_decorative_cover ledger closed_book green_book blue_book orange_book books book bookmark link " + "paperclip paperclips triangular_ruler straight_ruler pushpin round_pushpin scissors pen_ballpoint pen_fountain " + "black_nib paintbrush crayon pencil pencil2 mag mag_right lock_with_ink_pen closed_lock_with_key lock unlock"
                },
                symbols: {
                    icon: "heartpulse",
                    title: "Symbols",
                    emoji: "heart orange_heart yellow_heart green_heart blue_heart purple_heart black_heart broken_heart heart_exclamation two_hearts " + "revolving_hearts heartbeat heartpulse sparkling_heart cupid gift_heart heart_decoration peace cross star_and_crescent " + "om_symbol wheel_of_dharma star_of_david six_pointed_star menorah yin_yang orthodox_cross place_of_worship ophiuchus " + "aries taurus gemini cancer leo virgo libra scorpius sagittarius capricorn aquarius pisces id atom accept radioactive " + "biohazard mobile_phone_off vibration_mode u6709 u7121 u7533 u55b6 u6708 eight_pointed_black_star vs white_flower " + "ideograph_advantage secret congratulations u5408 u6e80 u5272 u7981 a b ab cl o2 sos x o octagonal_sign no_entry " + "name_badge no_entry_sign 100 anger hotsprings no_pedestrians do_not_litter no_bicycles non-potable_water underage " + "no_mobile_phones no_smoking exclamation grey_exclamation question grey_question bangbang interrobang low_brightness " + "high_brightness part_alternation_mark warning children_crossing trident fleur-de-lis beginner recycle " + "white_check_mark u6307 chart sparkle eight_spoked_asterisk negative_squared_cross_mark globe_with_meridians " + "diamond_shape_with_a_dot_inside m cyclone zzz atm wc wheelchair parking u7a7a sa passport_control customs " + "baggage_claim left_luggage mens womens baby_symbol restroom put_litter_in_its_place cinema signal_strength koko " + "symbols information_source abc abcd capital_abcd ng ok up cool new free zero one two three four five six seven " + "eight nine keycap_ten 1234 hash asterisk arrow_forward pause_button play_pause stop_button record_button eject " + "track_next track_previous fast_forward rewind arrow_double_up arrow_double_down arrow_backward arrow_up_small " + "arrow_down_small arrow_right arrow_left arrow_up arrow_down arrow_upper_right arrow_lower_right arrow_lower_left " + "arrow_upper_left arrow_up_down left_right_arrow arrow_right_hook leftwards_arrow_with_hook arrow_heading_up " + "arrow_heading_down twisted_rightwards_arrows repeat repeat_one arrows_counterclockwise arrows_clockwise " + "musical_note notes heavy_plus_sign heavy_minus_sign heavy_division_sign heavy_multiplication_x heavy_dollar_sign " + "currency_exchange tm copyright registered wavy_dash curly_loop loop end back on top soon heavy_check_mark " + "ballot_box_with_check radio_button white_circle black_circle red_circle blue_circle small_red_triangle " + "small_red_triangle_down small_orange_diamond small_blue_diamond large_orange_diamond large_blue_diamond " + "white_square_button black_square_button black_small_square white_small_square black_medium_small_square " + "white_medium_small_square black_medium_square white_medium_square black_large_square white_large_square speaker " + "mute sound loud_sound bell no_bell mega loudspeaker speech_left eye_in_speech_bubble speech_balloon thought_balloon " + "anger_right spades clubs hearts diamonds black_joker flower_playing_cards mahjong clock1 clock2 clock3 clock4 clock5 " + "clock6 clock7 clock8 clock9 clock10 clock11 clock12 clock130 clock230 clock330 clock430 clock530 clock630 " + "clock730 clock830 clock930 clock1030 clock1130 clock1230"
                },
                flags: {
                    icon: "flag_gb",
                    title: "Flags",
                    emoji: "flag_white flag_black checkered_flag triangular_flag_on_post rainbow_flag flag_af flag_ax flag_al flag_dz flag_as " + "flag_ad flag_ao flag_ai flag_aq flag_ag flag_ar flag_am flag_aw flag_au flag_at flag_az flag_bs flag_bh flag_bd flag_bb " + "flag_by flag_be flag_bz flag_bj flag_bm flag_bt flag_bo flag_ba flag_bw flag_br flag_io flag_vg flag_bn flag_bg flag_bf " + "flag_bi flag_kh flag_cm flag_ca flag_ic flag_cv flag_bq flag_ky flag_cf flag_td flag_cl flag_cn flag_cx flag_cc flag_co " + "flag_km flag_cg flag_cd flag_ck flag_cr flag_ci flag_hr flag_cu flag_cw flag_cy flag_cz flag_dk flag_dj flag_dm flag_do " + "flag_ec flag_eg flag_sv flag_gq flag_er flag_ee flag_et flag_eu flag_fk flag_fo flag_fj flag_fi flag_fr flag_gf flag_pf " + "flag_tf flag_ga flag_gm flag_ge flag_de flag_gh flag_gi flag_gr flag_gl flag_gd flag_gp flag_gu flag_gt flag_gg flag_gn " + "flag_gw flag_gy flag_ht flag_hn flag_hk flag_hu flag_is flag_in flag_id flag_ir flag_iq flag_ie flag_im flag_il flag_it " + "flag_jm flag_jp crossed_flags flag_je flag_jo flag_kz flag_ke flag_ki flag_xk flag_kw flag_kg flag_la flag_lv flag_lb " + "flag_ls flag_lr flag_ly flag_li flag_lt flag_lu flag_mo flag_mk flag_mg flag_mw flag_my flag_mv flag_ml flag_mt flag_mh " + "flag_mq flag_mr flag_mu flag_yt flag_mx flag_fm flag_md flag_mc flag_mn flag_me flag_ms flag_ma flag_mz flag_mm flag_na " + "flag_nr flag_np flag_nl flag_nc flag_nz flag_ni flag_ne flag_ng flag_nu flag_nf flag_kp flag_mp flag_no flag_om flag_pk " + "flag_pw flag_ps flag_pa flag_pg flag_py flag_pe flag_ph flag_pn flag_pl flag_pt flag_pr flag_qa flag_re flag_ro flag_ru " + "flag_rw flag_ws flag_sm flag_st flag_sa flag_sn flag_rs flag_sc flag_sl flag_sg flag_sx flag_sk flag_si flag_gs flag_sb " + "flag_so flag_za flag_kr flag_ss flag_es flag_lk flag_bl flag_sh flag_kn flag_lc flag_pm flag_vc flag_sd flag_sr flag_sz " + "flag_se flag_ch flag_sy flag_tw flag_tj flag_tz flag_th flag_tl flag_tg flag_tk flag_to flag_tt flag_tn flag_tr flag_tm " + "flag_tc flag_tv flag_vi flag_ug flag_ua flag_ae flag_gb flag_us flag_uy flag_uz flag_vu flag_va flag_ve flag_vn flag_wf " + "flag_eh flag_ye flag_zm flag_zw flag_ac flag_ta flag_bv flag_hm flag_sj flag_um flag_ea flag_cp flag_dg flag_mf " + "united_nations england scotland wales"
                }
            };
        } else {
            defaultOptions.filters = {
                tones: {
                    title: "Diversity",
                    emoji: "santa runner surfer swimmer lifter ear nose point_up_2 point_down point_left point_right punch " + "wave ok_hand thumbsup thumbsdown clap open_hands boy girl man woman cop bride_with_veil person_with_blond_hair " + "man_with_gua_pi_mao man_with_turban older_man grandma baby construction_worker princess angel " + "information_desk_person guardsman dancer nail_care massage haircut muscle spy hand_splayed middle_finger " + "vulcan no_good ok_woman bow raising_hand raised_hands person_frowning person_with_pouting_face pray rowboat " + "bicyclist mountain_bicyclist walking bath metal point_up basketball_player fist raised_hand v writing_hand"
                },
                recent: {
                    icon: "clock3",
                    title: "Recent",
                    emoji: ""
                },
                smileys_people: {
                    icon: "yum",
                    title: "Smileys & People",
                    emoji: "grinning grimacing grin joy smiley smile sweat_smile laughing innocent wink blush slight_smile " + "upside_down relaxed yum relieved heart_eyes kissing_heart kissing kissing_smiling_eyes " + "kissing_closed_eyes stuck_out_tongue_winking_eye stuck_out_tongue_closed_eyes stuck_out_tongue " + "money_mouth nerd sunglasses hugging smirk no_mouth neutral_face expressionless unamused rolling_eyes " + "thinking flushed disappointed worried angry rage pensive confused slight_frown frowning2 persevere " + "confounded tired_face weary triumph open_mouth scream fearful cold_sweat hushed frowning anguished " + "cry disappointed_relieved sleepy sweat sob dizzy_face astonished zipper_mouth mask thermometer_face " + "head_bandage sleeping zzz poop smiling_imp imp japanese_ogre japanese_goblin skull ghost alien robot " + "smiley_cat smile_cat joy_cat heart_eyes_cat smirk_cat kissing_cat scream_cat crying_cat_face " + "pouting_cat raised_hands clap wave thumbsup thumbsdown punch fist v ok_hand raised_hand open_hands " + "muscle pray point_up point_up_2 point_down point_left point_right middle_finger hand_splayed metal " + "vulcan writing_hand nail_care lips tongue ear nose eye eyes bust_in_silhouette busts_in_silhouette " + "speaking_head baby boy girl man woman person_with_blond_hair older_man older_woman man_with_gua_pi_mao " + "man_with_turban cop construction_worker guardsman spy santa angel princess bride_with_veil walking " + "runner dancer dancers couple two_men_holding_hands two_women_holding_hands bow information_desk_person " + "no_good ok_woman raising_hand person_with_pouting_face person_frowning haircut massage couple_with_heart " + "couple_ww couple_mm couplekiss kiss_ww kiss_mm family family_mwg family_mwgb family_mwbb family_mwgg " + "family_wwb family_wwg family_wwgb family_wwbb family_wwgg family_mmb family_mmg family_mmgb family_mmbb " + "family_mmgg womans_clothes shirt jeans necktie dress bikini kimono lipstick kiss footprints high_heel " + "sandal boot mans_shoe athletic_shoe womans_hat tophat helmet_with_cross mortar_board crown school_satchel " + "pouch purse handbag briefcase eyeglasses dark_sunglasses ring closed_umbrella"
                },
                animals_nature: {
                    icon: "hamster",
                    title: "Animals & Nature",
                    emoji: "dog cat mouse hamster rabbit bear panda_face koala tiger lion_face cow pig pig_nose frog " + "octopus monkey_face see_no_evil hear_no_evil speak_no_evil monkey chicken penguin bird baby_chick " + "hatching_chick hatched_chick wolf boar horse unicorn bee bug snail beetle ant spider scorpion crab " + "snake turtle tropical_fish fish blowfish dolphin whale whale2 crocodile leopard tiger2 water_buffalo " + "ox cow2 dromedary_camel camel elephant goat ram sheep racehorse pig2 rat mouse2 rooster turkey dove " + "dog2 poodle cat2 rabbit2 chipmunk feet dragon dragon_face cactus christmas_tree evergreen_tree " + "deciduous_tree palm_tree seedling herb shamrock four_leaf_clover bamboo tanabata_tree leaves " + "fallen_leaf maple_leaf ear_of_rice hibiscus sunflower rose tulip blossom cherry_blossom bouquet " + "mushroom chestnut jack_o_lantern shell spider_web earth_americas earth_africa earth_asia full_moon " + "waning_gibbous_moon last_quarter_moon waning_crescent_moon new_moon waxing_crescent_moon " + "first_quarter_moon waxing_gibbous_moon new_moon_with_face full_moon_with_face first_quarter_moon_with_face " + "last_quarter_moon_with_face sun_with_face crescent_moon star star2 dizzy sparkles comet sunny " + "white_sun_small_cloud partly_sunny white_sun_cloud white_sun_rain_cloud cloud cloud_rain " + "thunder_cloud_rain cloud_lightning zap fire boom snowflake cloud_snow snowman2 snowman wind_blowing_face " + "dash cloud_tornado fog umbrella2 umbrella droplet sweat_drops ocean"
                },
                food_drink: {
                    icon: "pizza",
                    title: "Food & Drink",
                    emoji: "green_apple apple pear tangerine lemon banana watermelon grapes strawberry melon cherries peach " + "pineapple tomato eggplant hot_pepper corn sweet_potato honey_pot bread cheese poultry_leg meat_on_bone " + "fried_shrimp egg hamburger fries hotdog pizza spaghetti taco burrito ramen stew fish_cake sushi bento " + "curry rice_ball rice rice_cracker oden dango shaved_ice ice_cream icecream cake birthday custard candy " + "lollipop chocolate_bar popcorn doughnut cookie beer beers wine_glass cocktail tropical_drink champagne " + "sake tea coffee baby_bottle fork_and_knife fork_knife_plate"
                },
                activity: {
                    icon: "basketball",
                    title: "Activity",
                    emoji: "soccer basketball football baseball tennis volleyball rugby_football 8ball golf golfer ping_pong " + "badminton hockey field_hockey cricket ski skier snowboarder ice_skate bow_and_arrow fishing_pole_and_fish " + "rowboat swimmer surfer bath basketball_player lifter bicyclist mountain_bicyclist horse_racing levitate " + "trophy running_shirt_with_sash medal military_medal reminder_ribbon rosette ticket tickets performing_arts " + "art circus_tent microphone headphones musical_score musical_keyboard saxophone trumpet guitar violin " + "clapper video_game space_invader dart game_die slot_machine bowling"
                },
                travel_places: {
                    icon: "rocket",
                    title: "Travel & Places",
                    emoji: "red_car taxi blue_car bus trolleybus race_car police_car ambulance fire_engine minibus truck " + "articulated_lorry tractor motorcycle bike rotating_light oncoming_police_car oncoming_bus " + "oncoming_automobile oncoming_taxi aerial_tramway mountain_cableway suspension_railway railway_car " + "train monorail bullettrain_side bullettrain_front light_rail mountain_railway steam_locomotive train2 " + "metro tram station helicopter airplane_small airplane airplane_departure airplane_arriving sailboat " + "motorboat speedboat ferry cruise_ship rocket satellite_orbital seat anchor construction fuelpump busstop " + "vertical_traffic_light traffic_light checkered_flag ship ferris_wheel roller_coaster carousel_horse " + "construction_site foggy tokyo_tower factory fountain rice_scene mountain mountain_snow mount_fuji volcano " + "japan camping tent park motorway railway_track sunrise sunrise_over_mountains desert beach island " + "city_sunset city_dusk cityscape night_with_stars bridge_at_night milky_way stars sparkler fireworks " + "rainbow homes european_castle japanese_castle stadium statue_of_liberty house house_with_garden " + "house_abandoned office department_store post_office european_post_office hospital bank hotel " + "convenience_store school love_hotel wedding classical_building church mosque synagogue kaaba shinto_shrine"
                },
                objects: {
                    icon: "bulb",
                    title: "Objects",
                    emoji: "watch iphone calling computer keyboard desktop printer mouse_three_button trackball joystick " + "compression minidisc floppy_disk cd dvd vhs camera camera_with_flash video_camera movie_camera projector " + "film_frames telephone_receiver telephone pager fax tv radio microphone2 level_slider control_knobs " + "stopwatch timer alarm_clock clock hourglass_flowing_sand hourglass satellite battery electric_plug bulb " + "flashlight candle wastebasket oil money_with_wings dollar yen euro pound moneybag credit_card gem scales " + "wrench hammer hammer_pick tools pick nut_and_bolt gear chains gun bomb knife dagger crossed_swords shield " + "smoking skull_crossbones coffin urn amphora crystal_ball prayer_beads barber alembic telescope microscope " + "hole pill syringe thermometer label bookmark toilet shower bathtub key key2 couch sleeping_accommodation " + "bed door bellhop frame_photo map beach_umbrella moyai shopping_bags balloon flags ribbon gift confetti_ball " + "tada dolls wind_chime crossed_flags izakaya_lantern envelope envelope_with_arrow incoming_envelope e-mail " + "love_letter postbox mailbox_closed mailbox mailbox_with_mail mailbox_with_no_mail package postal_horn " + "inbox_tray outbox_tray scroll page_with_curl bookmark_tabs bar_chart chart_with_upwards_trend " + "chart_with_downwards_trend page_facing_up date calendar calendar_spiral card_index card_box ballot_box " + "file_cabinet clipboard notepad_spiral file_folder open_file_folder dividers newspaper2 newspaper notebook " + "closed_book green_book blue_book orange_book notebook_with_decorative_cover ledger books book link " + "paperclip paperclips scissors triangular_ruler straight_ruler pushpin round_pushpin triangular_flag_on_post " + "flag_white flag_black closed_lock_with_key lock unlock lock_with_ink_pen pen_ballpoint pen_fountain " + "black_nib pencil pencil2 crayon paintbrush mag mag_right"
                },
                symbols: {
                    icon: "heartpulse",
                    title: "Symbols",
                    emoji: "heart yellow_heart green_heart blue_heart purple_heart broken_heart heart_exclamation two_hearts " + "revolving_hearts heartbeat heartpulse sparkling_heart cupid gift_heart heart_decoration peace cross " + "star_and_crescent om_symbol wheel_of_dharma star_of_david six_pointed_star menorah yin_yang orthodox_cross " + "place_of_worship ophiuchus aries taurus gemini cancer leo virgo libra scorpius sagittarius capricorn " + "aquarius pisces id atom u7a7a u5272 radioactive biohazard mobile_phone_off vibration_mode u6709 u7121 " + "u7533 u55b6 u6708 eight_pointed_black_star vs accept white_flower ideograph_advantage secret congratulations " + "u5408 u6e80 u7981 a b ab cl o2 sos no_entry name_badge no_entry_sign x o anger hotsprings no_pedestrians " + "do_not_litter no_bicycles non-potable_water underage no_mobile_phones exclamation grey_exclamation question " + "grey_question bangbang interrobang 100 low_brightness high_brightness trident fleur-de-lis part_alternation_mark " + "warning children_crossing beginner recycle u6307 chart sparkle eight_spoked_asterisk negative_squared_cross_mark " + "white_check_mark diamond_shape_with_a_dot_inside cyclone loop globe_with_meridians m atm sa passport_control " + "customs baggage_claim left_luggage wheelchair no_smoking wc parking potable_water mens womens baby_symbol " + "restroom put_litter_in_its_place cinema signal_strength koko ng ok up cool new free zero one two three four " + "five six seven eight nine ten 1234 arrow_forward pause_button play_pause stop_button record_button track_next " + "track_previous fast_forward rewind twisted_rightwards_arrows repeat repeat_one arrow_backward arrow_up_small " + "arrow_down_small arrow_double_up arrow_double_down arrow_right arrow_left arrow_up arrow_down arrow_upper_right " + "arrow_lower_right arrow_lower_left arrow_upper_left arrow_up_down left_right_arrow arrows_counterclockwise " + "arrow_right_hook leftwards_arrow_with_hook arrow_heading_up arrow_heading_down hash asterisk information_source " + "abc abcd capital_abcd symbols musical_note notes wavy_dash curly_loop heavy_check_mark arrows_clockwise " + "heavy_plus_sign heavy_minus_sign heavy_division_sign heavy_multiplication_x heavy_dollar_sign currency_exchange " + "copyright registered tm end back on top soon ballot_box_with_check radio_button white_circle black_circle " + "red_circle large_blue_circle small_orange_diamond small_blue_diamond large_orange_diamond large_blue_diamond " + "small_red_triangle black_small_square white_small_square black_large_square white_large_square small_red_triangle_down " + "black_medium_square white_medium_square black_medium_small_square white_medium_small_square black_square_button " + "white_square_button speaker sound loud_sound mute mega loudspeaker bell no_bell black_joker mahjong spades " + "clubs hearts diamonds flower_playing_cards thought_balloon anger_right speech_balloon clock1 clock2 clock3 " + "clock4 clock5 clock6 clock7 clock8 clock9 clock10 clock11 clock12 clock130 clock230 clock330 clock430 " + "clock530 clock630 clock730 clock830 clock930 clock1030 clock1130 clock1230 eye_in_speech_bubble"
                },
                flags: {
                    icon: "flag_gb",
                    title: "Flags",
                    emoji: "ac af al dz ad ao ai ag ar am aw au at az bs bh bd bb by be bz bj bm bt bo ba bw br bn bg bf bi " + "cv kh cm ca ky cf td flag_cl cn co km cg flag_cd cr hr cu cy cz dk dj dm do ec eg sv gq er ee et fk fo " + "fj fi fr pf ga gm ge de gh gi gr gl gd gu gt gn gw gy ht hn hk hu is in flag_id ir iq ie il it ci jm jp " + "je jo kz ke ki xk kw kg la lv lb ls lr ly li lt lu mo mk mg mw my mv ml mt mh mr mu mx fm md mc mn me " + "ms ma mz mm na nr np nl nc nz ni ne flag_ng nu kp no om pk pw ps pa pg py pe ph pl pt pr qa ro ru rw " + "sh kn lc vc ws sm st flag_sa sn rs sc sl sg sk si sb so za kr es lk sd sr sz se ch sy tw tj tz th tl " + "tg to tt tn tr flag_tm flag_tm ug ua ae gb us vi uy uz vu va ve vn wf eh ye zm zw re ax ta io bq cx " + "cc gg im yt nf pn bl pm gs tk bv hm sj um ic ea cp dg as aq vg ck cw eu gf tf gp mq mp sx ss tc "
                }
            };
        }
        return defaultOptions;
    }
    function getOptions(options) {
        var default_options = getDefaultOptions();
        if (options && options["filters"]) {
            var filters = default_options.filters;
            $.each(options["filters"], function(filter, data) {
                if (!isObject(data) || $.isEmptyObject(data)) {
                    delete filters[filter];
                    return;
                }
                $.each(data, function(key, val) {
                    filters[filter][key] = val;
                });
            });
            options["filters"] = filters;
        }
        return $.extend({}, default_options, options);
    }
    var saveSelection, restoreSelection;
    if (window.getSelection && document.createRange) {
        saveSelection = function(el) {
            var sel = window.getSelection && window.getSelection();
            if (sel && sel.rangeCount > 0) {
                return sel.getRangeAt(0);
            }
        };
        restoreSelection = function(el, sel) {
            var range = document.createRange();
            range.setStart(sel.startContainer, sel.startOffset);
            range.setEnd(sel.endContainer, sel.endOffset);
            sel = window.getSelection();
            sel.removeAllRanges();
            sel.addRange(range);
        };
    } else if (document.selection && document.body.createTextRange) {
        saveSelection = function(el) {
            return document.selection.createRange();
        };
        restoreSelection = function(el, sel) {
            var textRange = document.body.createTextRange();
            textRange.moveToElementText(el);
            textRange.setStart(sel.startContanier, sel.startOffset);
            textRange.setEnd(sel.endContainer, sel.endOffset);
            textRange.select();
        };
    }
    var uniRegexp;
    function unicodeTo(str, template) {
        return str.replace(uniRegexp, function(unicodeChar) {
            var map = emojione[emojioneSupportMode === 0 ? "jsecapeMap" : "jsEscapeMap"];
            if (typeof unicodeChar !== "undefined" && unicodeChar in map) {
                return getTemplate(template, map[unicodeChar], emojione.toShort(unicodeChar));
            }
            return unicodeChar;
        });
    }
    function htmlFromText(str, self) {
        str = str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#x27;").replace(/`/g, "&#x60;").replace(/(?:\r\n|\r|\n)/g, "\n").replace(/(\n+)/g, "<div>$1</div>").replace(/\n/g, "<br/>").replace(/<br\/><\/div>/g, "</div>");
        if (self.shortnames) {
            str = emojione.shortnameToUnicode(str);
        }
        return unicodeTo(str, self.emojiTemplate).replace(/\t/g, "&nbsp;&nbsp;&nbsp;&nbsp;").replace(/  /g, "&nbsp;&nbsp;");
    }
    function textFromHtml(str, self) {
        str = str.replace(/&#10;/g, "\n").replace(/&#09;/g, "\t").replace(/<img[^>]*alt="([^"]+)"[^>]*>/gi, "$1").replace(/\n|\r/g, "").replace(/<br[^>]*>/gi, "\n").replace(/(?:<(?:div|p|ol|ul|li|pre|code|object)[^>]*>)+/gi, "<div>").replace(/(?:<\/(?:div|p|ol|ul|li|pre|code|object)>)+/gi, "</div>").replace(/\n<div><\/div>/gi, "\n").replace(/<div><\/div>\n/gi, "\n").replace(/(?:<div>)+<\/div>/gi, "\n").replace(/([^\n])<\/div><div>/gi, "$1\n").replace(/(?:<\/div>)+/gi, "</div>").replace(/([^\n])<\/div>([^\n])/gi, "$1\n$2").replace(/<\/div>/gi, "").replace(/([^\n])<div>/gi, "$1\n").replace(/\n<div>/gi, "\n").replace(/<div>\n/gi, "\n\n").replace(/<(?:[^>]+)?>/g, "").replace(new RegExp(invisibleChar, "g"), "").replace(/&nbsp;/g, " ").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&quot;/g, '"').replace(/&#x27;/g, "'").replace(/&#x60;/g, "`").replace(/&#60;/g, "<").replace(/&#62;/g, ">").replace(/&amp;/g, "&");
        switch (self.saveEmojisAs) {
          case "image":
            str = unicodeTo(str, self.emojiTemplate);
            break;

          case "shortname":
            str = emojione.toShort(str);
        }
        return str;
    }
    function calcButtonPosition() {
        var self = this, offset = self.editor[0].offsetWidth - self.editor[0].clientWidth, current = parseInt(self.button.css("marginRight"));
        if (current !== offset) {
            self.button.css({
                marginRight: offset
            });
            if (self.floatingPicker) {
                self.picker.css({
                    right: parseInt(self.picker.css("right")) - current + offset
                });
            }
        }
    }
    function lazyLoading() {
        var self = this;
        if (!self.sprite && self.lasyEmoji[0] && self.lasyEmoji.eq(0).is(".lazy-emoji")) {
            var pickerTop = self.picker.offset().top, pickerBottom = pickerTop + self.picker.height() + 20;
            self.lasyEmoji.each(function() {
                var e = $(this), top = e.offset().top;
                if (top > pickerTop && top < pickerBottom) {
                    e.attr("src", e.data("src")).removeClass("lazy-emoji");
                }
                if (top > pickerBottom) {
                    return false;
                }
            });
            self.lasyEmoji = self.lasyEmoji.filter(".lazy-emoji");
        }
    }
    function selector(prefix, skip_dot) {
        return (skip_dot ? "" : ".") + css_class + (prefix ? "-" + prefix : "");
    }
    function div(prefix) {
        var parent = $("<div/>", isObject(prefix) ? prefix : {
            class: selector(prefix, true)
        });
        $.each(slice.call(arguments).slice(1), function(i, child) {
            if ($.isFunction(child)) {
                child = child.call(parent);
            }
            if (child) {
                $(child).appendTo(parent);
            }
        });
        return parent;
    }
    function getRecent() {
        return localStorage.getItem("recent_emojis") || "";
    }
    function updateRecent(self, show) {
        var emojis = getRecent();
        if (!self.recent || self.recent !== emojis || show) {
            if (emojis.length) {
                var skinnable = self.scrollArea.is(".skinnable"), scrollTop, height;
                if (!skinnable) {
                    scrollTop = self.scrollArea.scrollTop();
                    if (show) {
                        self.recentCategory.show();
                    }
                    height = self.recentCategory.is(":visible") ? self.recentCategory.height() : 0;
                }
                var items = shortnameTo(emojis, self.emojiBtnTemplate, true).split("|").join("");
                self.recentCategory.children(".emojibtn").remove();
                $(items).insertAfter(self.recentCategory.children(".emojionearea-category-title"));
                self.recentCategory.children(".emojibtn").on("click", function() {
                    self.trigger("emojibtn.click", $(this));
                });
                self.recentFilter.show();
                if (!skinnable) {
                    self.recentCategory.show();
                    var height2 = self.recentCategory.height();
                    if (height !== height2) {
                        self.scrollArea.scrollTop(scrollTop + height2 - height);
                    }
                }
            } else {
                if (self.recentFilter.hasClass("active")) {
                    self.recentFilter.removeClass("active").next().addClass("active");
                }
                self.recentCategory.hide();
                self.recentFilter.hide();
            }
            self.recent = emojis;
        }
    }
    function setRecent(self, emoji) {
        var recent = getRecent();
        var emojis = recent.split("|");
        var index = emojis.indexOf(emoji);
        if (index !== -1) {
            emojis.splice(index, 1);
        }
        emojis.unshift(emoji);
        if (emojis.length > 9) {
            emojis.pop();
        }
        localStorage.setItem("recent_emojis", emojis.join("|"));
        updateRecent(self);
    }
    function supportsLocalStorage() {
        var test = "test";
        try {
            localStorage.setItem(test, test);
            localStorage.removeItem(test);
            return true;
        } catch (e) {
            return false;
        }
    }
    function init(self, source, options) {
        self.options = options = getOptions(options);
        self.sprite = options.sprite && emojioneSupportMode < 3;
        self.inline = options.inline === null ? source.is("INPUT") : options.inline;
        self.shortnames = options.shortnames;
        self.saveEmojisAs = options.saveEmojisAs;
        self.standalone = options.standalone;
        self.emojiTemplate = '<img alt="{alt}" class="emojione' + (self.sprite ? '-{uni}" src="' + blankImg + '"/>' : 'emoji" src="{img}"/>');
        self.emojiTemplateAlt = self.sprite ? '<i class="emojione-{uni}"/>' : '<img class="emojioneemoji" src="{img}"/>';
        self.emojiBtnTemplate = '<i class="emojibtn" role="button" data-name="{name}" title="{friendlyName}">' + self.emojiTemplateAlt + "</i>";
        self.recentEmojis = options.recentEmojis && supportsLocalStorage();
        var pickerPosition = options.pickerPosition;
        self.floatingPicker = pickerPosition === "top" || pickerPosition === "bottom";
        self.source = source;
        if (source.is(":disabled") || source.is(".disabled")) {
            self.disable();
        }
        var sourceValFunc = source.is("TEXTAREA") || source.is("INPUT") ? "val" : "text", editor, button, picker, filters, filtersBtns, searchPanel, emojisList, categories, categoryBlocks, scrollArea, tones = div("tones", options.tones ? function() {
            this.addClass(selector("tones-" + options.tonesStyle, true));
            for (var i = 0; i <= 5; i++) {
                this.append($("<i/>", {
                    class: "btn-tone btn-tone-" + i + (!i ? " active" : ""),
                    "data-skin": i,
                    role: "button"
                }));
            }
        } : null), app = div({
            class: css_class + (self.standalone ? " " + css_class + "-standalone " : " ") + (source.attr("class") || ""),
            role: "application"
        }, editor = self.editor = div("editor").attr({
            contenteditable: self.standalone ? false : true,
            placeholder: options.placeholder || source.data("placeholder") || source.attr("placeholder") || "",
            tabindex: 0
        }), button = self.button = div("button", div("button-open"), div("button-close")).attr("title", options.buttonTitle), picker = self.picker = div("picker", div("wrapper", filters = div("filters"), options.search ? searchPanel = div("search-panel", div("search", options.search ? function() {
            self.search = $("<input/>", {
                placeholder: options.searchPlaceholder || "",
                type: "text",
                class: "search"
            });
            this.append(self.search);
        } : null), tones) : null, scrollArea = div("scroll-area", options.tones && !options.search ? div("tones-panel", tones) : null, emojisList = div("emojis-list")))).addClass(selector("picker-position-" + options.pickerPosition, true)).addClass(selector("filters-position-" + options.filtersPosition, true)).addClass(selector("search-position-" + options.searchPosition, true)).addClass("hidden"));
        if (options.search) {
            searchPanel.addClass(selector("with-search", true));
        }
        self.searchSel = null;
        editor.data(source.data());
        $.each(options.attributes, function(attr, value) {
            editor.attr(attr, value);
        });
        var mainBlock = div("category-block").attr({
            "data-tone": 0
        }).prependTo(emojisList);
        $.each(options.filters, function(filter, params) {
            var skin = 0;
            if (filter === "recent" && !self.recentEmojis) {
                return;
            }
            if (filter !== "tones") {
                $("<i/>", {
                    class: selector("filter", true) + " " + selector("filter-" + filter, true),
                    "data-filter": filter,
                    title: params.title
                }).wrapInner(shortnameTo(params.icon, self.emojiTemplateAlt)).appendTo(filters);
            } else if (options.tones) {
                skin = 5;
            } else {
                return;
            }
            do {
                var category, items = params.emoji.replace(/[\s,;]+/g, "|");
                if (skin === 0) {
                    category = div("category").attr({
                        name: filter,
                        "data-tone": skin
                    }).appendTo(mainBlock);
                } else {
                    category = div("category-block").attr({
                        name: filter,
                        "data-tone": skin
                    }).appendTo(emojisList);
                }
                if (skin > 0) {
                    category.hide();
                    items = items.split("|").join("_tone" + skin + "|") + "_tone" + skin;
                }
                if (filter === "recent") {
                    items = getRecent();
                }
                items = shortnameTo(items, self.sprite ? '<i class="emojibtn" role="button" data-name="{name}" title="{friendlyName}"><i class="emojione-{uni}"></i></i>' : '<i class="emojibtn" role="button" data-name="{name}" title="{friendlyName}"><img class="emojioneemoji lazy-emoji" data-src="{img}"/></i>', true).split("|").join("");
                category.html(items);
                $('<div class="emojionearea-category-title"/>').text(params.title).prependTo(category);
            } while (--skin > 0);
        });
        options.filters = null;
        if (!self.sprite) {
            self.lasyEmoji = emojisList.find(".lazy-emoji");
        }
        filtersBtns = filters.find(selector("filter"));
        filtersBtns.eq(0).addClass("active");
        categoryBlocks = emojisList.find(selector("category-block"));
        categories = emojisList.find(selector("category"));
        self.recentFilter = filtersBtns.filter('[data-filter="recent"]');
        self.recentCategory = categories.filter("[name=recent]");
        self.scrollArea = scrollArea;
        if (options.container) {
            $(options.container).wrapInner(app);
        } else {
            app.insertAfter(source);
        }
        if (options.hideSource) {
            source.hide();
        }
        self.setText(source[sourceValFunc]());
        source[sourceValFunc](self.getText());
        calcButtonPosition.apply(self);
        if (self.standalone && !self.getText().length) {
            var placeholder = $(source).data("emoji-placeholder") || options.emojiPlaceholder;
            self.setText(placeholder);
            editor.addClass("has-placeholder");
        }
        attach(self, emojisList.find(".emojibtn"), {
            click: "emojibtn.click"
        });
        attach(self, window, {
            resize: "!resize"
        });
        attach(self, tones.children(), {
            click: "tone.click"
        });
        attach(self, [ picker, button ], {
            mousedown: "!mousedown"
        }, editor);
        attach(self, button, {
            click: "button.click"
        });
        attach(self, editor, {
            paste: "!paste"
        }, editor);
        attach(self, editor, [ "focus", "blur" ], function() {
            return self.stayFocused ? false : editor;
        });
        attach(self, picker, {
            mousedown: "picker.mousedown",
            mouseup: "picker.mouseup",
            click: "picker.click",
            keyup: "picker.keyup",
            keydown: "picker.keydown",
            keypress: "picker.keypress"
        });
        attach(self, editor, [ "mousedown", "mouseup", "click", "keyup", "keydown", "keypress" ]);
        attach(self, picker.find(".emojionearea-filter"), {
            click: "filter.click"
        });
        attach(self, source, {
            change: "source.change"
        });
        if (options.search) {
            attach(self, self.search, {
                keyup: "search.keypress",
                focus: "search.focus",
                blur: "search.blur"
            });
        }
        var noListenScroll = false;
        scrollArea.on("scroll", function() {
            if (!noListenScroll) {
                lazyLoading.call(self);
                if (scrollArea.is(":not(.skinnable)")) {
                    var item = categories.eq(0), scrollTop = scrollArea.offset().top;
                    categories.each(function(i, e) {
                        if ($(e).offset().top - scrollTop >= 10) {
                            return false;
                        }
                        item = $(e);
                    });
                    var filter = filtersBtns.filter('[data-filter="' + item.attr("name") + '"]');
                    if (filter[0] && !filter.is(".active")) {
                        filtersBtns.removeClass("active");
                        filter.addClass("active");
                    }
                }
            }
        });
        self.on("@filter.click", function(filter) {
            var isActive = filter.is(".active");
            if (scrollArea.is(".skinnable")) {
                if (isActive) return;
                tones.children().eq(0).click();
            }
            noListenScroll = true;
            if (!isActive) {
                filtersBtns.filter(".active").removeClass("active");
                filter.addClass("active");
            }
            var headerOffset = categories.filter('[name="' + filter.data("filter") + '"]').offset().top, scroll = scrollArea.scrollTop(), offsetTop = scrollArea.offset().top;
            scrollArea.stop().animate({
                scrollTop: headerOffset + scroll - offsetTop - 2
            }, 200, "swing", function() {
                lazyLoading.call(self);
                noListenScroll = false;
            });
        }).on("@picker.show", function() {
            if (self.recentEmojis) {
                updateRecent(self);
            }
            lazyLoading.call(self);
        }).on("@tone.click", function(tone) {
            tones.children().removeClass("active");
            var skin = tone.addClass("active").data("skin");
            if (skin) {
                scrollArea.addClass("skinnable");
                categoryBlocks.hide().filter("[data-tone=" + skin + "]").show();
                filtersBtns.removeClass("active");
            } else {
                scrollArea.removeClass("skinnable");
                categoryBlocks.hide().filter("[data-tone=0]").show();
                filtersBtns.eq(0).click();
            }
            lazyLoading.call(self);
            if (options.search) {
                self.trigger("search.keypress");
            }
        }).on("@button.click", function(button) {
            if (button.is(".active")) {
                self.hidePicker();
            } else {
                self.showPicker();
                self.searchSel = null;
            }
        }).on("@!paste", function(editor, event) {
            var pasteText = function(text) {
                var caretID = "caret-" + new Date().getTime();
                var html = htmlFromText(text, self);
                pasteHtmlAtCaret(html);
                pasteHtmlAtCaret('<i id="' + caretID + '"></i>');
                editor.scrollTop(editorScrollTop);
                var caret = $("#" + caretID), top = caret.offset().top - editor.offset().top, height = editor.height();
                if (editorScrollTop + top >= height || editorScrollTop > top) {
                    editor.scrollTop(editorScrollTop + top - 2 * height / 3);
                }
                caret.remove();
                self.stayFocused = false;
                calcButtonPosition.apply(self);
                trigger(self, "paste", [ editor, text, html ]);
            };
            if (event.originalEvent.clipboardData) {
                var text = event.originalEvent.clipboardData.getData("text/plain");
                pasteText(text);
                if (event.preventDefault) {
                    event.preventDefault();
                } else {
                    event.stop();
                }
                event.returnValue = false;
                event.stopPropagation();
                return false;
            }
            self.stayFocused = true;
            pasteHtmlAtCaret("<span>" + invisibleChar + "</span>");
            var sel = saveSelection(editor[0]), editorScrollTop = editor.scrollTop(), clipboard = $("<div/>", {
                contenteditable: true
            }).css({
                position: "fixed",
                left: "-999px",
                width: "1px",
                height: "1px",
                top: "20px",
                overflow: "hidden"
            }).appendTo($("BODY")).focus();
            window.setTimeout(function() {
                editor.focus();
                restoreSelection(editor[0], sel);
                var text = textFromHtml(clipboard.html().replace(/\r\n|\n|\r/g, "<br>"), self);
                clipboard.remove();
                pasteText(text);
            }, 200);
        }).on("@emojibtn.click", function(emojibtn) {
            editor.removeClass("has-placeholder");
            if (self.searchSel !== null) {
                editor.focus();
                restoreSelection(editor[0], self.searchSel);
                self.searchSel = null;
            }
            if (self.standalone) {
                editor.html(shortnameTo(emojibtn.data("name"), self.emojiTemplate));
                self.trigger("blur");
            } else {
                saveSelection(editor[0]);
                pasteHtmlAtCaret(shortnameTo(emojibtn.data("name"), self.emojiTemplate));
            }
            if (self.recentEmojis) {
                setRecent(self, emojibtn.data("name"));
            }
            self.trigger("search.keypress");
        }).on("@!resize @keyup @emojibtn.click", calcButtonPosition).on("@!mousedown", function(editor, event) {
            if ($(event.target).hasClass("search")) {
                self.stayFocused = true;
                if (self.searchSel === null) {
                    self.searchSel = saveSelection(editor[0]);
                }
            } else {
                if (!app.is(".focused")) {
                    editor.trigger("focus");
                }
                event.preventDefault();
            }
            return false;
        }).on("@change", function() {
            var html = self.editor.html().replace(/<\/?(?:div|span|p)[^>]*>/gi, "");
            if (!html.length || /^<br[^>]*>$/i.test(html)) {
                self.editor.html(self.content = "");
            }
            source[sourceValFunc](self.getText());
        }).on("@source.change", function() {
            self.setText(source[sourceValFunc]());
            trigger("change");
        }).on("@focus", function() {
            app.addClass("focused");
        }).on("@blur", function() {
            app.removeClass("focused");
            if (options.hidePickerOnBlur) {
                self.hidePicker();
            }
            var content = self.editor.html();
            if (self.content !== content) {
                self.content = content;
                trigger(self, "change", [ self.editor ]);
                source.trigger("blur").trigger("change");
            } else {
                source.trigger("blur");
            }
            if (options.search) {
                self.search.val("");
                self.trigger("search.keypress", true);
            }
        });
        if (options.search) {
            self.on("@search.focus", function() {
                self.stayFocused = true;
                self.search.addClass("focused");
            }).on("@search.keypress", function(hide) {
                var filterBtns = picker.find(".emojionearea-filter");
                var activeTone = options.tones ? tones.find("i.active").data("skin") : 0;
                var term = self.search.val().replace(/ /g, "_").replace(/"/g, '\\"');
                if (term && term.length) {
                    if (self.recentFilter.hasClass("active")) {
                        self.recentFilter.removeClass("active").next().addClass("active");
                    }
                    self.recentCategory.hide();
                    self.recentFilter.hide();
                    categoryBlocks.each(function() {
                        var matchEmojis = function(category, activeTone) {
                            var $matched = category.find('.emojibtn[data-name*="' + term + '"]');
                            if ($matched.length === 0) {
                                if (category.data("tone") === activeTone) {
                                    category.hide();
                                }
                                filterBtns.filter('[data-filter="' + category.attr("name") + '"]').hide();
                            } else {
                                var $notMatched = category.find('.emojibtn:not([data-name*="' + term + '"])');
                                $notMatched.hide();
                                $matched.show();
                                if (category.data("tone") === activeTone) {
                                    category.show();
                                }
                                filterBtns.filter('[data-filter="' + category.attr("name") + '"]').show();
                            }
                        };
                        var $block = $(this);
                        if ($block.data("tone") === 0) {
                            categories.filter(':not([name="recent"])').each(function() {
                                matchEmojis($(this), 0);
                            });
                        } else {
                            matchEmojis($block, activeTone);
                        }
                    });
                    if (!noListenScroll) {
                        scrollArea.trigger("scroll");
                    } else {
                        lazyLoading.call(self);
                    }
                } else {
                    updateRecent(self, true);
                    categoryBlocks.filter('[data-tone="' + tones.find("i.active").data("skin") + '"]:not([name="recent"])').show();
                    $(".emojibtn", categoryBlocks).show();
                    filterBtns.show();
                    lazyLoading.call(self);
                }
            }).on("@search.blur", function() {
                self.stayFocused = false;
                self.search.removeClass("focused");
                self.trigger("blur");
            });
        }
        if (options.shortcuts) {
            self.on("@keydown", function(_, e) {
                if (!e.ctrlKey) {
                    if (e.which == 9) {
                        e.preventDefault();
                        button.click();
                    } else if (e.which == 27) {
                        e.preventDefault();
                        if (button.is(".active")) {
                            self.hidePicker();
                        }
                    }
                }
            });
        }
        if (isObject(options.events) && !$.isEmptyObject(options.events)) {
            $.each(options.events, function(event, handler) {
                self.on(event.replace(/_/g, "."), handler);
            });
        }
        if (options.autocomplete) {
            var autocomplete = function() {
                var textcompleteOptions = {
                    maxCount: options.textcomplete.maxCount,
                    placement: options.textcomplete.placement
                };
                if (options.shortcuts) {
                    textcompleteOptions.onKeydown = function(e, commands) {
                        if (!e.ctrlKey && e.which == 13) {
                            return commands.KEY_ENTER;
                        }
                    };
                }
                var map = $.map(emojione.emojioneList, function(_, emoji) {
                    return !options.autocompleteTones ? /_tone[12345]/.test(emoji) ? null : emoji : emoji;
                });
                map.sort();
                editor.textcomplete([ {
                    id: css_class,
                    match: /\B(:[\-+\w]*)$/,
                    search: function(term, callback) {
                        callback($.map(map, function(emoji) {
                            return emoji.indexOf(term) === 0 ? emoji : null;
                        }));
                    },
                    template: function(value) {
                        return shortnameTo(value, self.emojiTemplate) + " " + value.replace(/:/g, "");
                    },
                    replace: function(value) {
                        return shortnameTo(value, self.emojiTemplate);
                    },
                    cache: true,
                    index: 1
                } ], textcompleteOptions);
                if (options.textcomplete.placement) {
                    if ($(editor.data("textComplete").option.appendTo).css("position") == "static") {
                        $(editor.data("textComplete").option.appendTo).css("position", "relative");
                    }
                }
            };
            var initAutocomplete = function() {
                if (self.disabled) {
                    var enable = function() {
                        self.off("enabled", enable);
                        autocomplete();
                    };
                    self.on("enabled", enable);
                } else {
                    autocomplete();
                }
            };
            if ($.fn.textcomplete) {
                initAutocomplete();
            } else {
                $.ajax({
                    url: "https://cdn.rawgit.com/yuku-t/jquery-textcomplete/v1.3.4/dist/jquery.textcomplete.js",
                    dataType: "script",
                    cache: true,
                    success: initAutocomplete
                });
            }
        }
        if (self.inline) {
            app.addClass(selector("inline", true));
            self.on("@keydown", function(_, e) {
                if (e.which == 13) {
                    e.preventDefault();
                }
            });
        }
        if (/firefox/i.test(navigator.userAgent)) {
            document.execCommand("enableObjectResizing", false, false);
        }
        self.isReady = true;
        self.trigger("onLoad", editor);
        self.trigger("ready", editor);
    }
    var cdn = {
        defaultBase: "https://cdnjs.cloudflare.com/ajax/libs/emojione/",
        defaultBase3: "https://cdn.jsdelivr.net/",
        base: null,
        isLoading: false
    };
    function loadEmojione(options) {
        var emojioneVersion = getEmojioneVersion();
        options = getOptions(options);
        if (!cdn.isLoading) {
            if (!emojione || getSupportMode(detectVersion(emojione)) < 2) {
                cdn.isLoading = true;
                var emojioneJsCdnUrlBase;
                if (getSupportMode(emojioneVersion) > 5) {
                    emojioneJsCdnUrlBase = cdn.defaultBase3 + "npm/emojione@" + emojioneVersion;
                } else if (getSupportMode(emojioneVersion) > 4) {
                    emojioneJsCdnUrlBase = cdn.defaultBase3 + "emojione/" + emojioneVersion;
                } else {
                    emojioneJsCdnUrlBase = cdn.defaultBase + "/" + emojioneVersion;
                }
                $.ajax({
                    url: emojioneJsCdnUrlBase + "/lib/js/emojione.min.js",
                    dataType: "script",
                    cache: true,
                    success: function() {
                        emojione = window.emojione;
                        emojioneVersion = detectVersion(emojione);
                        emojioneSupportMode = getSupportMode(emojioneVersion);
                        var sprite;
                        if (emojioneSupportMode > 4) {
                            cdn.base = cdn.defaultBase3 + "emojione/assets/" + emojioneVersion;
                            sprite = cdn.base + "/sprites/emojione-sprite-" + emojione.emojiSize + ".css";
                        } else {
                            cdn.base = cdn.defaultBase + emojioneVersion + "/assets";
                            sprite = cdn.base + "/sprites/emojione.sprites.css";
                        }
                        if (options.sprite) {
                            if (document.createStyleSheet) {
                                document.createStyleSheet(sprite);
                            } else {
                                $("<link/>", {
                                    rel: "stylesheet",
                                    href: sprite
                                }).appendTo("head");
                            }
                        }
                        while (readyCallbacks.length) {
                            readyCallbacks.shift().call();
                        }
                        cdn.isLoading = false;
                    }
                });
            } else {
                emojioneVersion = detectVersion(emojione);
                emojioneSupportMode = getSupportMode(emojioneVersion);
                if (emojioneSupportMode > 4) {
                    cdn.base = cdn.defaultBase3 + "emojione/assets/" + emojioneVersion;
                } else {
                    cdn.base = cdn.defaultBase + emojioneVersion + "/assets";
                }
            }
        }
        emojioneReady(function() {
            var emojiSize = "";
            if (options.useInternalCDN) {
                if (emojioneSupportMode > 4) emojiSize = emojione.emojiSize + "/";
                emojione.imagePathPNG = cdn.base + "/png/" + emojiSize;
                emojione.imagePathSVG = cdn.base + "/svg/" + emojiSize;
                emojione.imagePathSVGSprites = cdn.base + "/sprites/emojione.sprites.svg";
                emojione.imageType = options.imageType;
            }
            if (getSupportMode(emojioneVersion) > 4) {
                uniRegexp = emojione.regUnicode;
                emojione.imageType = options.imageType || "png";
            } else {
                uniRegexp = new RegExp("<object[^>]*>.*?</object>|<span[^>]*>.*?</span>|<(?:object|embed|svg|img|div|span|p|a)[^>]*>|(" + emojione.unicodeRegexp + ")", "gi");
            }
        });
    }
    var EmojioneArea = function(element, options) {
        var self = this;
        loadEmojione(options);
        eventStorage[self.id = ++unique] = {};
        possibleEvents[self.id] = {};
        emojioneReady(function() {
            init(self, element, options);
        });
    };
    function bindEvent(self, event) {
        event = event.replace(/^@/, "");
        var id = self.id;
        if (possibleEvents[id][event]) {
            $.each(possibleEvents[id][event], function(i, ev) {
                $.each($.isArray(ev[0]) ? ev[0] : [ ev[0] ], function(i, el) {
                    $(el).on(ev[1], function() {
                        var args = slice.call(arguments), target = $.isFunction(ev[2]) ? ev[2].apply(self, [ event ].concat(args)) : ev[2];
                        if (target) {
                            trigger(self, event, [ target ].concat(args));
                        }
                    });
                });
            });
            possibleEvents[id][event] = null;
        }
    }
    EmojioneArea.prototype.on = function(events, handler) {
        if (events && $.isFunction(handler)) {
            var self = this;
            $.each(events.toLowerCase().split(" "), function(i, event) {
                bindEvent(self, event);
                (eventStorage[self.id][event] || (eventStorage[self.id][event] = [])).push(handler);
            });
        }
        return this;
    };
    EmojioneArea.prototype.off = function(events, handler) {
        if (events) {
            var id = this.id;
            $.each(events.toLowerCase().replace(/_/g, ".").split(" "), function(i, event) {
                if (eventStorage[id][event] && !/^@/.test(event)) {
                    if (handler) {
                        $.each(eventStorage[id][event], function(j, fn) {
                            if (fn === handler) {
                                eventStorage[id][event].splice(j, 1);
                            }
                        });
                    } else {
                        eventStorage[id][event] = [];
                    }
                }
            });
        }
        return this;
    };
    EmojioneArea.prototype.trigger = function() {
        var args = slice.call(arguments), call_args = [ this ].concat(args.slice(0, 1));
        call_args.push(args.slice(1));
        return trigger.apply(this, call_args);
    };
    EmojioneArea.prototype.setFocus = function() {
        var self = this;
        emojioneReady(function() {
            self.editor.focus();
        });
        return self;
    };
    EmojioneArea.prototype.setText = function(str) {
        var self = this;
        emojioneReady(function() {
            self.editor.html(htmlFromText(str, self));
            self.content = self.editor.html();
            trigger(self, "change", [ self.editor ]);
            calcButtonPosition.apply(self);
        });
        return self;
    };
    EmojioneArea.prototype.getText = function() {
        return textFromHtml(this.editor.html(), this);
    };
    EmojioneArea.prototype.showPicker = function() {
        var self = this;
        if (self._sh_timer) {
            window.clearTimeout(self._sh_timer);
        }
        self.picker.removeClass("hidden");
        self._sh_timer = window.setTimeout(function() {
            self.button.addClass("active");
        }, 50);
        trigger(self, "picker.show", [ self.picker ]);
        return self;
    };
    EmojioneArea.prototype.hidePicker = function() {
        var self = this;
        if (self._sh_timer) {
            window.clearTimeout(self._sh_timer);
        }
        self.button.removeClass("active");
        self._sh_timer = window.setTimeout(function() {
            self.picker.addClass("hidden");
        }, 500);
        trigger(self, "picker.hide", [ self.picker ]);
        return self;
    };
    EmojioneArea.prototype.enable = function() {
        var self = this;
        var next = function() {
            self.disabled = false;
            self.editor.prop("contenteditable", true);
            self.button.show();
            var editor = self[self.standalone ? "button" : "editor"];
            editor.parent().removeClass("emojionearea-disable");
            trigger(self, "enabled", [ editor ]);
        };
        self.isReady ? next() : self.on("ready", next);
        return self;
    };
    EmojioneArea.prototype.disable = function() {
        var self = this;
        self.disabled = true;
        var next = function() {
            self.editor.prop("contenteditable", false);
            self.hidePicker();
            self.button.hide();
            var editor = self[self.standalone ? "button" : "editor"];
            editor.parent().addClass("emojionearea-disable");
            trigger(self, "disabled", [ editor ]);
        };
        self.isReady ? next() : self.on("ready", next);
        return self;
    };
    $.fn.emojioneArea = function(options) {
        return this.each(function() {
            if (!!this.emojioneArea) return this.emojioneArea;
            $.data(this, "emojioneArea", this.emojioneArea = new EmojioneArea($(this), options));
            return this.emojioneArea;
        });
    };
    $.fn.emojioneArea.defaults = getDefaultOptions();
    $.fn.emojioneAreaText = function(options) {
        options = getOptions(options);
        var self = this, pseudoSelf = {
            shortnames: options && typeof options.shortnames !== "undefined" ? options.shortnames : true,
            emojiTemplate: '<img alt="{alt}" class="emojione' + (options && options.sprite && emojioneSupportMode < 3 ? '-{uni}" src="' + blankImg : 'emoji" src="{img}') + '"/>'
        };
        loadEmojione(options);
        emojioneReady(function() {
            self.each(function() {
                var $this = $(this);
                if (!$this.hasClass("emojionearea-text")) {
                    $this.addClass("emojionearea-text").html(htmlFromText($this.is("TEXTAREA") || $this.is("INPUT") ? $this.val() : $this.text(), pseudoSelf));
                }
                return $this;
            });
        });
        return this;
    };
}, window);

(function(jQuery, undefined) {
    var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color outlineColor".split(" "), rplusequals = /^([\-+])=\s*(\d+\.?\d*)/, stringParsers = [ {
        re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
        parse: function(execResult) {
            return [ execResult[1], execResult[2], execResult[3], execResult[4] ];
        }
    }, {
        re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
        parse: function(execResult) {
            return [ 2.55 * execResult[1], 2.55 * execResult[2], 2.55 * execResult[3], execResult[4] ];
        }
    }, {
        re: /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/,
        parse: function(execResult) {
            return [ parseInt(execResult[1], 16), parseInt(execResult[2], 16), parseInt(execResult[3], 16) ];
        }
    }, {
        re: /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/,
        parse: function(execResult) {
            return [ parseInt(execResult[1] + execResult[1], 16), parseInt(execResult[2] + execResult[2], 16), parseInt(execResult[3] + execResult[3], 16) ];
        }
    }, {
        re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
        space: "hsla",
        parse: function(execResult) {
            return [ execResult[1], execResult[2] / 100, execResult[3] / 100, execResult[4] ];
        }
    } ], color = jQuery.Color = function(color, green, blue, alpha) {
        return new jQuery.Color.fn.parse(color, green, blue, alpha);
    }, spaces = {
        rgba: {
            cache: "_rgba",
            props: {
                red: {
                    idx: 0,
                    type: "byte",
                    empty: true
                },
                green: {
                    idx: 1,
                    type: "byte",
                    empty: true
                },
                blue: {
                    idx: 2,
                    type: "byte",
                    empty: true
                },
                alpha: {
                    idx: 3,
                    type: "percent",
                    def: 1
                }
            }
        },
        hsla: {
            cache: "_hsla",
            props: {
                hue: {
                    idx: 0,
                    type: "degrees",
                    empty: true
                },
                saturation: {
                    idx: 1,
                    type: "percent",
                    empty: true
                },
                lightness: {
                    idx: 2,
                    type: "percent",
                    empty: true
                }
            }
        }
    }, propTypes = {
        byte: {
            floor: true,
            min: 0,
            max: 255
        },
        percent: {
            min: 0,
            max: 1
        },
        degrees: {
            mod: 360,
            floor: true
        }
    }, rgbaspace = spaces.rgba.props, support = color.support = {}, colors, each = jQuery.each;
    spaces.hsla.props.alpha = rgbaspace.alpha;
    function clamp(value, prop, alwaysAllowEmpty) {
        var type = propTypes[prop.type] || {}, allowEmpty = prop.empty || alwaysAllowEmpty;
        if (allowEmpty && value == null) {
            return null;
        }
        if (prop.def && value == null) {
            return prop.def;
        }
        if (type.floor) {
            value = ~~value;
        } else {
            value = parseFloat(value);
        }
        if (value == null || isNaN(value)) {
            return prop.def;
        }
        if (type.mod) {
            value = value % type.mod;
            return value < 0 ? type.mod + value : value;
        }
        return type.min > value ? type.min : type.max < value ? type.max : value;
    }
    function stringParse(string) {
        var inst = color(), rgba = inst._rgba = [];
        string = string.toLowerCase();
        each(stringParsers, function(i, parser) {
            var match = parser.re.exec(string), values = match && parser.parse(match), parsed, spaceName = parser.space || "rgba", cache = spaces[spaceName].cache;
            if (values) {
                parsed = inst[spaceName](values);
                inst[cache] = parsed[cache];
                rgba = inst._rgba = parsed._rgba;
                return false;
            }
        });
        if (rgba.length !== 0) {
            if (Math.max.apply(Math, rgba) === 0) {
                jQuery.extend(rgba, colors.transparent);
            }
            return inst;
        }
        if (string = colors[string]) {
            return string;
        }
    }
    color.fn = color.prototype = {
        constructor: color,
        parse: function(red, green, blue, alpha) {
            if (red === undefined) {
                this._rgba = [ null, null, null, null ];
                return this;
            }
            if (red instanceof jQuery || red.nodeType) {
                red = red instanceof jQuery ? red.css(green) : jQuery(red).css(green);
                green = undefined;
            }
            var inst = this, type = jQuery.type(red), rgba = this._rgba = [], source;
            if (green !== undefined) {
                red = [ red, green, blue, alpha ];
                type = "array";
            }
            if (type === "string") {
                return this.parse(stringParse(red) || colors._default);
            }
            if (type === "array") {
                each(rgbaspace, function(key, prop) {
                    rgba[prop.idx] = clamp(red[prop.idx], prop);
                });
                return this;
            }
            if (type === "object") {
                if (red instanceof color) {
                    each(spaces, function(spaceName, space) {
                        if (red[space.cache]) {
                            inst[space.cache] = red[space.cache].slice();
                        }
                    });
                } else {
                    each(spaces, function(spaceName, space) {
                        each(space.props, function(key, prop) {
                            var cache = space.cache;
                            if (!inst[cache] && space.to) {
                                if (red[key] == null || key === "alpha") {
                                    return;
                                }
                                inst[cache] = space.to(inst._rgba);
                            }
                            inst[cache][prop.idx] = clamp(red[key], prop, true);
                        });
                    });
                }
                return this;
            }
        },
        is: function(compare) {
            var is = color(compare), same = true, myself = this;
            each(spaces, function(_, space) {
                var isCache = is[space.cache], localCache;
                if (isCache) {
                    localCache = myself[space.cache] || space.to && space.to(myself._rgba) || [];
                    each(space.props, function(_, prop) {
                        if (isCache[prop.idx] != null) {
                            same = isCache[prop.idx] === localCache[prop.idx];
                            return same;
                        }
                    });
                }
                return same;
            });
            return same;
        },
        _space: function() {
            var used = [], inst = this;
            each(spaces, function(spaceName, space) {
                if (inst[space.cache]) {
                    used.push(spaceName);
                }
            });
            return used.pop();
        },
        transition: function(other, distance) {
            var end = color(other), spaceName = end._space(), space = spaces[spaceName], start = this[space.cache] || space.to(this._rgba), result = start.slice();
            end = end[space.cache];
            each(space.props, function(key, prop) {
                var index = prop.idx, startValue = start[index], endValue = end[index], type = propTypes[prop.type] || {};
                if (endValue === null) {
                    return;
                }
                if (startValue === null) {
                    result[index] = endValue;
                } else {
                    if (type.mod) {
                        if (endValue - startValue > type.mod / 2) {
                            startValue += type.mod;
                        } else if (startValue - endValue > type.mod / 2) {
                            startValue -= type.mod;
                        }
                    }
                    result[prop.idx] = clamp((endValue - startValue) * distance + startValue, prop);
                }
            });
            return this[spaceName](result);
        },
        blend: function(opaque) {
            if (this._rgba[3] === 1) {
                return this;
            }
            var rgb = this._rgba.slice(), a = rgb.pop(), blend = color(opaque)._rgba;
            return color(jQuery.map(rgb, function(v, i) {
                return (1 - a) * blend[i] + a * v;
            }));
        },
        toRgbaString: function() {
            var prefix = "rgba(", rgba = jQuery.map(this._rgba, function(v, i) {
                return v == null ? i > 2 ? 1 : 0 : v;
            });
            if (rgba[3] === 1) {
                rgba.pop();
                prefix = "rgb(";
            }
            return prefix + rgba.join(",") + ")";
        },
        toHslaString: function() {
            var prefix = "hsla(", hsla = jQuery.map(this.hsla(), function(v, i) {
                if (v == null) {
                    v = i > 2 ? 1 : 0;
                }
                if (i && i < 3) {
                    v = Math.round(v * 100) + "%";
                }
                return v;
            });
            if (hsla[3] === 1) {
                hsla.pop();
                prefix = "hsl(";
            }
            return prefix + hsla.join(",") + ")";
        },
        toHexString: function(includeAlpha) {
            var rgba = this._rgba.slice(), alpha = rgba.pop();
            if (includeAlpha) {
                rgba.push(~~(alpha * 255));
            }
            return "#" + jQuery.map(rgba, function(v, i) {
                v = (v || 0).toString(16);
                return v.length === 1 ? "0" + v : v;
            }).join("");
        },
        toString: function() {
            return this._rgba[3] === 0 ? "transparent" : this.toRgbaString();
        }
    };
    color.fn.parse.prototype = color.fn;
    function hue2rgb(p, q, h) {
        h = (h + 1) % 1;
        if (h * 6 < 1) {
            return p + (q - p) * 6 * h;
        }
        if (h * 2 < 1) {
            return q;
        }
        if (h * 3 < 2) {
            return p + (q - p) * (2 / 3 - h) * 6;
        }
        return p;
    }
    spaces.hsla.to = function(rgba) {
        if (rgba[0] == null || rgba[1] == null || rgba[2] == null) {
            return [ null, null, null, rgba[3] ];
        }
        var r = rgba[0] / 255, g = rgba[1] / 255, b = rgba[2] / 255, a = rgba[3], max = Math.max(r, g, b), min = Math.min(r, g, b), diff = max - min, add = max + min, l = add * .5, h, s;
        if (min === max) {
            h = 0;
        } else if (r === max) {
            h = 60 * (g - b) / diff + 360;
        } else if (g === max) {
            h = 60 * (b - r) / diff + 120;
        } else {
            h = 60 * (r - g) / diff + 240;
        }
        if (l === 0 || l === 1) {
            s = l;
        } else if (l <= .5) {
            s = diff / add;
        } else {
            s = diff / (2 - add);
        }
        return [ Math.round(h) % 360, s, l, a == null ? 1 : a ];
    };
    spaces.hsla.from = function(hsla) {
        if (hsla[0] == null || hsla[1] == null || hsla[2] == null) {
            return [ null, null, null, hsla[3] ];
        }
        var h = hsla[0] / 360, s = hsla[1], l = hsla[2], a = hsla[3], q = l <= .5 ? l * (1 + s) : l + s - l * s, p = 2 * l - q, r, g, b;
        return [ Math.round(hue2rgb(p, q, h + 1 / 3) * 255), Math.round(hue2rgb(p, q, h) * 255), Math.round(hue2rgb(p, q, h - 1 / 3) * 255), a ];
    };
    each(spaces, function(spaceName, space) {
        var props = space.props, cache = space.cache, to = space.to, from = space.from;
        color.fn[spaceName] = function(value) {
            if (to && !this[cache]) {
                this[cache] = to(this._rgba);
            }
            if (value === undefined) {
                return this[cache].slice();
            }
            var type = jQuery.type(value), arr = type === "array" || type === "object" ? value : arguments, local = this[cache].slice(), ret;
            each(props, function(key, prop) {
                var val = arr[type === "object" ? key : prop.idx];
                if (val == null) {
                    val = local[prop.idx];
                }
                local[prop.idx] = clamp(val, prop);
            });
            if (from) {
                ret = color(from(local));
                ret[cache] = local;
                return ret;
            } else {
                return color(local);
            }
        };
        each(props, function(key, prop) {
            if (color.fn[key]) {
                return;
            }
            color.fn[key] = function(value) {
                var vtype = jQuery.type(value), fn = key === "alpha" ? this._hsla ? "hsla" : "rgba" : spaceName, local = this[fn](), cur = local[prop.idx], match;
                if (vtype === "undefined") {
                    return cur;
                }
                if (vtype === "function") {
                    value = value.call(this, cur);
                    vtype = jQuery.type(value);
                }
                if (value == null && prop.empty) {
                    return this;
                }
                if (vtype === "string") {
                    match = rplusequals.exec(value);
                    if (match) {
                        value = cur + parseFloat(match[2]) * (match[1] === "+" ? 1 : -1);
                    }
                }
                local[prop.idx] = value;
                return this[fn](local);
            };
        });
    });
    each(stepHooks, function(i, hook) {
        jQuery.cssHooks[hook] = {
            set: function(elem, value) {
                var parsed, backgroundColor, curElem;
                if (jQuery.type(value) !== "string" || (parsed = stringParse(value))) {
                    value = color(parsed || value);
                    if (!support.rgba && value._rgba[3] !== 1) {
                        curElem = hook === "backgroundColor" ? elem.parentNode : elem;
                        do {
                            backgroundColor = jQuery.curCSS(curElem, "backgroundColor");
                        } while ((backgroundColor === "" || backgroundColor === "transparent") && (curElem = curElem.parentNode) && curElem.style);
                        value = value.blend(backgroundColor && backgroundColor !== "transparent" ? backgroundColor : "_default");
                    }
                    value = value.toRgbaString();
                }
                elem.style[hook] = value;
            }
        };
        jQuery.fx.step[hook] = function(fx) {
            if (!fx.colorInit) {
                fx.start = color(fx.elem, hook);
                fx.end = color(fx.end);
                fx.colorInit = true;
            }
            jQuery.cssHooks[hook].set(fx.elem, fx.start.transition(fx.end, fx.pos));
        };
    });
    jQuery(function() {
        var div = document.createElement("div"), div_style = div.style;
        div_style.cssText = "background-color:rgba(1,1,1,.5)";
        support.rgba = div_style.backgroundColor.indexOf("rgba") > -1;
    });
    colors = jQuery.Color.names = {
        aqua: "#00ffff",
        azure: "#f0ffff",
        beige: "#f5f5dc",
        black: "#000000",
        blue: "#0000ff",
        brown: "#a52a2a",
        cyan: "#00ffff",
        darkblue: "#00008b",
        darkcyan: "#008b8b",
        darkgrey: "#a9a9a9",
        darkgreen: "#006400",
        darkkhaki: "#bdb76b",
        darkmagenta: "#8b008b",
        darkolivegreen: "#556b2f",
        darkorange: "#ff8c00",
        darkorchid: "#9932cc",
        darkred: "#8b0000",
        darksalmon: "#e9967a",
        darkviolet: "#9400d3",
        fuchsia: "#ff00ff",
        gold: "#ffd700",
        green: "#008000",
        indigo: "#4b0082",
        khaki: "#f0e68c",
        lightblue: "#add8e6",
        lightcyan: "#e0ffff",
        lightgreen: "#90ee90",
        lightgrey: "#d3d3d3",
        lightpink: "#ffb6c1",
        lightyellow: "#ffffe0",
        lime: "#00ff00",
        magenta: "#ff00ff",
        maroon: "#800000",
        navy: "#000080",
        olive: "#808000",
        orange: "#ffa500",
        pink: "#ffc0cb",
        purple: "#800080",
        violet: "#800080",
        red: "#ff0000",
        silver: "#c0c0c0",
        white: "#ffffff",
        yellow: "#ffff00",
        transparent: [ null, null, null, 0 ],
        _default: "#ffffff"
    };
})(jQuery);

(function($) {
    $.Jcrop = function(obj, opt) {
        var options = $.extend({}, $.Jcrop.defaults), docOffset, _ua = navigator.userAgent.toLowerCase(), is_msie = /msie/.test(_ua), ie6mode = /msie [1-6]\./.test(_ua);
        function px(n) {
            return Math.round(n) + "px";
        }
        function cssClass(cl) {
            return options.baseClass + "-" + cl;
        }
        function supportsColorFade() {
            return $.fx.step.hasOwnProperty("backgroundColor");
        }
        function getPos(obj) {
            var pos = $(obj).offset();
            return [ pos.left, pos.top ];
        }
        function mouseAbs(e) {
            return [ e.pageX - docOffset[0], e.pageY - docOffset[1] ];
        }
        function setOptions(opt) {
            if (typeof opt !== "object") opt = {};
            options = $.extend(options, opt);
            $.each([ "onChange", "onSelect", "onRelease", "onDblClick" ], function(i, e) {
                if (typeof options[e] !== "function") options[e] = function() {};
            });
        }
        function startDragMode(mode, pos, touch) {
            docOffset = getPos($img);
            Tracker.setCursor(mode === "move" ? mode : mode + "-resize");
            if (mode === "move") {
                return Tracker.activateHandlers(createMover(pos), doneSelect, touch);
            }
            var fc = Coords.getFixed();
            var opp = oppLockCorner(mode);
            var opc = Coords.getCorner(oppLockCorner(opp));
            Coords.setPressed(Coords.getCorner(opp));
            Coords.setCurrent(opc);
            Tracker.activateHandlers(dragmodeHandler(mode, fc), doneSelect, touch);
        }
        function dragmodeHandler(mode, f) {
            return function(pos) {
                if (!options.aspectRatio) {
                    switch (mode) {
                      case "e":
                        pos[1] = f.y2;
                        break;

                      case "w":
                        pos[1] = f.y2;
                        break;

                      case "n":
                        pos[0] = f.x2;
                        break;

                      case "s":
                        pos[0] = f.x2;
                        break;
                    }
                } else {
                    switch (mode) {
                      case "e":
                        pos[1] = f.y + 1;
                        break;

                      case "w":
                        pos[1] = f.y + 1;
                        break;

                      case "n":
                        pos[0] = f.x + 1;
                        break;

                      case "s":
                        pos[0] = f.x + 1;
                        break;
                    }
                }
                Coords.setCurrent(pos);
                Selection.update();
            };
        }
        function createMover(pos) {
            var lloc = pos;
            KeyManager.watchKeys();
            return function(pos) {
                Coords.moveOffset([ pos[0] - lloc[0], pos[1] - lloc[1] ]);
                lloc = pos;
                Selection.update();
            };
        }
        function oppLockCorner(ord) {
            switch (ord) {
              case "n":
                return "sw";

              case "s":
                return "nw";

              case "e":
                return "nw";

              case "w":
                return "ne";

              case "ne":
                return "sw";

              case "nw":
                return "se";

              case "se":
                return "nw";

              case "sw":
                return "ne";
            }
        }
        function createDragger(ord) {
            return function(e) {
                if (options.disabled) {
                    return false;
                }
                if (ord === "move" && !options.allowMove) {
                    return false;
                }
                docOffset = getPos($img);
                btndown = true;
                startDragMode(ord, mouseAbs(e));
                e.stopPropagation();
                e.preventDefault();
                return false;
            };
        }
        function presize($obj, w, h) {
            var nw = $obj.width(), nh = $obj.height();
            if (nw > w && w > 0) {
                nw = w;
                nh = w / $obj.width() * $obj.height();
            }
            if (nh > h && h > 0) {
                nh = h;
                nw = h / $obj.height() * $obj.width();
            }
            xscale = $obj.width() / nw;
            yscale = $obj.height() / nh;
            $obj.width(nw).height(nh);
        }
        function unscale(c) {
            return {
                x: c.x * xscale,
                y: c.y * yscale,
                x2: c.x2 * xscale,
                y2: c.y2 * yscale,
                w: c.w * xscale,
                h: c.h * yscale
            };
        }
        function doneSelect(pos) {
            var c = Coords.getFixed();
            if (c.w > options.minSelect[0] && c.h > options.minSelect[1]) {
                Selection.enableHandles();
                Selection.done();
            } else {
                Selection.release();
            }
            Tracker.setCursor(options.allowSelect ? "crosshair" : "default");
        }
        function newSelection(e) {
            if (options.disabled) {
                return false;
            }
            if (!options.allowSelect) {
                return false;
            }
            btndown = true;
            docOffset = getPos($img);
            Selection.disableHandles();
            Tracker.setCursor("crosshair");
            var pos = mouseAbs(e);
            Coords.setPressed(pos);
            Selection.update();
            Tracker.activateHandlers(selectDrag, doneSelect, e.type.substring(0, 5) === "touch");
            KeyManager.watchKeys();
            e.stopPropagation();
            e.preventDefault();
            return false;
        }
        function selectDrag(pos) {
            Coords.setCurrent(pos);
            Selection.update();
        }
        function newTracker() {
            var trk = $("<div></div>").addClass(cssClass("tracker"));
            if (is_msie) {
                trk.css({
                    opacity: 0,
                    backgroundColor: "white"
                });
            }
            return trk;
        }
        if (typeof obj !== "object") {
            obj = $(obj)[0];
        }
        if (typeof opt !== "object") {
            opt = {};
        }
        setOptions(opt);
        var img_css = {
            border: "none",
            visibility: "visible",
            margin: 0,
            padding: 0,
            position: "absolute",
            top: 0,
            left: 0
        };
        var $origimg = $(obj), img_mode = true;
        if (obj.tagName == "IMG") {
            if ($origimg[0].width != 0 && $origimg[0].height != 0) {
                $origimg.width($origimg[0].width);
                $origimg.height($origimg[0].height);
            } else {
                var tempImage = new Image();
                tempImage.src = $origimg[0].src;
                $origimg.width(tempImage.width);
                $origimg.height(tempImage.height);
            }
            var $img = $origimg.clone().removeAttr("id").css(img_css).show();
            $img.width($origimg.width());
            $img.height($origimg.height());
            $origimg.after($img).hide();
        } else {
            $img = $origimg.css(img_css).show();
            img_mode = false;
            if (options.shade === null) {
                options.shade = true;
            }
        }
        presize($img, options.boxWidth, options.boxHeight);
        var boundx = $img.width(), boundy = $img.height(), $div = $("<div />").width(boundx).height(boundy).addClass(cssClass("holder")).css({
            position: "relative",
            backgroundColor: options.bgColor
        }).insertAfter($origimg).append($img);
        if (options.addClass) {
            $div.addClass(options.addClass);
        }
        var $img2 = $("<div />"), $img_holder = $("<div />").width("100%").height("100%").css({
            zIndex: 310,
            position: "absolute",
            overflow: "hidden"
        }), $hdl_holder = $("<div />").width("100%").height("100%").css("zIndex", 320), $sel = $("<div />").css({
            position: "absolute",
            zIndex: 600
        }).dblclick(function() {
            var c = Coords.getFixed();
            options.onDblClick.call(api, c);
        }).insertBefore($img).append($img_holder, $hdl_holder);
        if (img_mode) {
            $img2 = $("<img />").attr("src", $img.attr("src")).css(img_css).width(boundx).height(boundy), 
            $img_holder.append($img2);
        }
        if (ie6mode) {
            $sel.css({
                overflowY: "hidden"
            });
        }
        var bound = options.boundary;
        var $trk = newTracker().width(boundx + bound * 2).height(boundy + bound * 2).css({
            position: "absolute",
            top: px(-bound),
            left: px(-bound),
            zIndex: 290
        }).mousedown(newSelection);
        var bgcolor = options.bgColor, bgopacity = options.bgOpacity, xlimit, ylimit, xmin, ymin, xscale, yscale, enabled = true, btndown, animating, shift_down;
        docOffset = getPos($img);
        var Touch = function() {
            function hasTouchSupport() {
                var support = {}, events = [ "touchstart", "touchmove", "touchend" ], el = document.createElement("div"), i;
                try {
                    for (i = 0; i < events.length; i++) {
                        var eventName = events[i];
                        eventName = "on" + eventName;
                        var isSupported = eventName in el;
                        if (!isSupported) {
                            el.setAttribute(eventName, "return;");
                            isSupported = typeof el[eventName] == "function";
                        }
                        support[events[i]] = isSupported;
                    }
                    return support.touchstart && support.touchend && support.touchmove;
                } catch (err) {
                    return false;
                }
            }
            function detectSupport() {
                if (options.touchSupport === true || options.touchSupport === false) return options.touchSupport; else return hasTouchSupport();
            }
            return {
                createDragger: function(ord) {
                    return function(e) {
                        if (options.disabled) {
                            return false;
                        }
                        if (ord === "move" && !options.allowMove) {
                            return false;
                        }
                        docOffset = getPos($img);
                        btndown = true;
                        startDragMode(ord, mouseAbs(Touch.cfilter(e)), true);
                        e.stopPropagation();
                        e.preventDefault();
                        return false;
                    };
                },
                newSelection: function(e) {
                    return newSelection(Touch.cfilter(e));
                },
                cfilter: function(e) {
                    e.pageX = e.originalEvent.changedTouches[0].pageX;
                    e.pageY = e.originalEvent.changedTouches[0].pageY;
                    return e;
                },
                isSupported: hasTouchSupport,
                support: detectSupport()
            };
        }();
        var Coords = function() {
            var x1 = 0, y1 = 0, x2 = 0, y2 = 0, ox, oy;
            function setPressed(pos) {
                pos = rebound(pos);
                x2 = x1 = pos[0];
                y2 = y1 = pos[1];
            }
            function setCurrent(pos) {
                pos = rebound(pos);
                ox = pos[0] - x2;
                oy = pos[1] - y2;
                x2 = pos[0];
                y2 = pos[1];
            }
            function getOffset() {
                return [ ox, oy ];
            }
            function moveOffset(offset) {
                var ox = offset[0], oy = offset[1];
                if (0 > x1 + ox) {
                    ox -= ox + x1;
                }
                if (0 > y1 + oy) {
                    oy -= oy + y1;
                }
                if (boundy < y2 + oy) {
                    oy += boundy - (y2 + oy);
                }
                if (boundx < x2 + ox) {
                    ox += boundx - (x2 + ox);
                }
                x1 += ox;
                x2 += ox;
                y1 += oy;
                y2 += oy;
            }
            function getCorner(ord) {
                var c = getFixed();
                switch (ord) {
                  case "ne":
                    return [ c.x2, c.y ];

                  case "nw":
                    return [ c.x, c.y ];

                  case "se":
                    return [ c.x2, c.y2 ];

                  case "sw":
                    return [ c.x, c.y2 ];
                }
            }
            function getFixed() {
                if (!options.aspectRatio) {
                    return getRect();
                }
                var aspect = options.aspectRatio, min_x = options.minSize[0] / xscale, max_x = options.maxSize[0] / xscale, max_y = options.maxSize[1] / yscale, rw = x2 - x1, rh = y2 - y1, rwa = Math.abs(rw), rha = Math.abs(rh), real_ratio = rwa / rha, xx, yy, w, h;
                if (max_x === 0) {
                    max_x = boundx * 10;
                }
                if (max_y === 0) {
                    max_y = boundy * 10;
                }
                if (real_ratio < aspect) {
                    yy = y2;
                    w = rha * aspect;
                    xx = rw < 0 ? x1 - w : w + x1;
                    if (xx < 0) {
                        xx = 0;
                        h = Math.abs((xx - x1) / aspect);
                        yy = rh < 0 ? y1 - h : h + y1;
                    } else if (xx > boundx) {
                        xx = boundx;
                        h = Math.abs((xx - x1) / aspect);
                        yy = rh < 0 ? y1 - h : h + y1;
                    }
                } else {
                    xx = x2;
                    h = rwa / aspect;
                    yy = rh < 0 ? y1 - h : y1 + h;
                    if (yy < 0) {
                        yy = 0;
                        w = Math.abs((yy - y1) * aspect);
                        xx = rw < 0 ? x1 - w : w + x1;
                    } else if (yy > boundy) {
                        yy = boundy;
                        w = Math.abs(yy - y1) * aspect;
                        xx = rw < 0 ? x1 - w : w + x1;
                    }
                }
                if (xx > x1) {
                    if (xx - x1 < min_x) {
                        xx = x1 + min_x;
                    } else if (xx - x1 > max_x) {
                        xx = x1 + max_x;
                    }
                    if (yy > y1) {
                        yy = y1 + (xx - x1) / aspect;
                    } else {
                        yy = y1 - (xx - x1) / aspect;
                    }
                } else if (xx < x1) {
                    if (x1 - xx < min_x) {
                        xx = x1 - min_x;
                    } else if (x1 - xx > max_x) {
                        xx = x1 - max_x;
                    }
                    if (yy > y1) {
                        yy = y1 + (x1 - xx) / aspect;
                    } else {
                        yy = y1 - (x1 - xx) / aspect;
                    }
                }
                if (xx < 0) {
                    x1 -= xx;
                    xx = 0;
                } else if (xx > boundx) {
                    x1 -= xx - boundx;
                    xx = boundx;
                }
                if (yy < 0) {
                    y1 -= yy;
                    yy = 0;
                } else if (yy > boundy) {
                    y1 -= yy - boundy;
                    yy = boundy;
                }
                return makeObj(flipCoords(x1, y1, xx, yy));
            }
            function rebound(p) {
                if (p[0] < 0) p[0] = 0;
                if (p[1] < 0) p[1] = 0;
                if (p[0] > boundx) p[0] = boundx;
                if (p[1] > boundy) p[1] = boundy;
                return [ Math.round(p[0]), Math.round(p[1]) ];
            }
            function flipCoords(x1, y1, x2, y2) {
                var xa = x1, xb = x2, ya = y1, yb = y2;
                if (x2 < x1) {
                    xa = x2;
                    xb = x1;
                }
                if (y2 < y1) {
                    ya = y2;
                    yb = y1;
                }
                return [ xa, ya, xb, yb ];
            }
            function getRect() {
                var xsize = x2 - x1, ysize = y2 - y1, delta;
                if (xlimit && Math.abs(xsize) > xlimit) {
                    x2 = xsize > 0 ? x1 + xlimit : x1 - xlimit;
                }
                if (ylimit && Math.abs(ysize) > ylimit) {
                    y2 = ysize > 0 ? y1 + ylimit : y1 - ylimit;
                }
                if (ymin / yscale && Math.abs(ysize) < ymin / yscale) {
                    y2 = ysize > 0 ? y1 + ymin / yscale : y1 - ymin / yscale;
                }
                if (xmin / xscale && Math.abs(xsize) < xmin / xscale) {
                    x2 = xsize > 0 ? x1 + xmin / xscale : x1 - xmin / xscale;
                }
                if (x1 < 0) {
                    x2 -= x1;
                    x1 -= x1;
                }
                if (y1 < 0) {
                    y2 -= y1;
                    y1 -= y1;
                }
                if (x2 < 0) {
                    x1 -= x2;
                    x2 -= x2;
                }
                if (y2 < 0) {
                    y1 -= y2;
                    y2 -= y2;
                }
                if (x2 > boundx) {
                    delta = x2 - boundx;
                    x1 -= delta;
                    x2 -= delta;
                }
                if (y2 > boundy) {
                    delta = y2 - boundy;
                    y1 -= delta;
                    y2 -= delta;
                }
                if (x1 > boundx) {
                    delta = x1 - boundy;
                    y2 -= delta;
                    y1 -= delta;
                }
                if (y1 > boundy) {
                    delta = y1 - boundy;
                    y2 -= delta;
                    y1 -= delta;
                }
                return makeObj(flipCoords(x1, y1, x2, y2));
            }
            function makeObj(a) {
                return {
                    x: a[0],
                    y: a[1],
                    x2: a[2],
                    y2: a[3],
                    w: a[2] - a[0],
                    h: a[3] - a[1]
                };
            }
            return {
                flipCoords: flipCoords,
                setPressed: setPressed,
                setCurrent: setCurrent,
                getOffset: getOffset,
                moveOffset: moveOffset,
                getCorner: getCorner,
                getFixed: getFixed
            };
        }();
        var Shade = function() {
            var enabled = false, holder = $("<div />").css({
                position: "absolute",
                zIndex: 240,
                opacity: 0
            }), shades = {
                top: createShade(),
                left: createShade().height(boundy),
                right: createShade().height(boundy),
                bottom: createShade()
            };
            function resizeShades(w, h) {
                shades.left.css({
                    height: px(h)
                });
                shades.right.css({
                    height: px(h)
                });
            }
            function updateAuto() {
                return updateShade(Coords.getFixed());
            }
            function updateShade(c) {
                shades.top.css({
                    left: px(c.x),
                    width: px(c.w),
                    height: px(c.y)
                });
                shades.bottom.css({
                    top: px(c.y2),
                    left: px(c.x),
                    width: px(c.w),
                    height: px(boundy - c.y2)
                });
                shades.right.css({
                    left: px(c.x2),
                    width: px(boundx - c.x2)
                });
                shades.left.css({
                    width: px(c.x)
                });
            }
            function createShade() {
                return $("<div />").css({
                    position: "absolute",
                    backgroundColor: options.shadeColor || options.bgColor
                }).appendTo(holder);
            }
            function enableShade() {
                if (!enabled) {
                    enabled = true;
                    holder.insertBefore($img);
                    updateAuto();
                    Selection.setBgOpacity(1, 0, 1);
                    $img2.hide();
                    setBgColor(options.shadeColor || options.bgColor, 1);
                    if (Selection.isAwake()) {
                        setOpacity(options.bgOpacity, 1);
                    } else setOpacity(1, 1);
                }
            }
            function setBgColor(color, now) {
                colorChangeMacro(getShades(), color, now);
            }
            function disableShade() {
                if (enabled) {
                    holder.remove();
                    $img2.show();
                    enabled = false;
                    if (Selection.isAwake()) {
                        Selection.setBgOpacity(options.bgOpacity, 1, 1);
                    } else {
                        Selection.setBgOpacity(1, 1, 1);
                        Selection.disableHandles();
                    }
                    colorChangeMacro($div, 0, 1);
                }
            }
            function setOpacity(opacity, now) {
                if (enabled) {
                    if (options.bgFade && !now) {
                        holder.animate({
                            opacity: 1 - opacity
                        }, {
                            queue: false,
                            duration: options.fadeTime
                        });
                    } else holder.css({
                        opacity: 1 - opacity
                    });
                }
            }
            function refreshAll() {
                options.shade ? enableShade() : disableShade();
                if (Selection.isAwake()) setOpacity(options.bgOpacity);
            }
            function getShades() {
                return holder.children();
            }
            return {
                update: updateAuto,
                updateRaw: updateShade,
                getShades: getShades,
                setBgColor: setBgColor,
                enable: enableShade,
                disable: disableShade,
                resize: resizeShades,
                refresh: refreshAll,
                opacity: setOpacity
            };
        }();
        var Selection = function() {
            var awake, hdep = 370, borders = {}, handle = {}, dragbar = {}, seehandles = false;
            function insertBorder(type) {
                var jq = $("<div />").css({
                    position: "absolute",
                    opacity: options.borderOpacity
                }).addClass(cssClass(type));
                $img_holder.append(jq);
                return jq;
            }
            function dragDiv(ord, zi) {
                var jq = $("<div />").mousedown(createDragger(ord)).css({
                    cursor: ord + "-resize",
                    position: "absolute",
                    zIndex: zi
                }).addClass("ord-" + ord);
                if (Touch.support) {
                    jq.bind("touchstart.jcrop", Touch.createDragger(ord));
                }
                $hdl_holder.append(jq);
                return jq;
            }
            function insertHandle(ord) {
                var hs = options.handleSize, div = dragDiv(ord, hdep++).css({
                    opacity: options.handleOpacity
                }).addClass(cssClass("handle"));
                if (hs) {
                    div.width(hs).height(hs);
                }
                return div;
            }
            function insertDragbar(ord) {
                return dragDiv(ord, hdep++).addClass("jcrop-dragbar");
            }
            function createDragbars(li) {
                var i;
                for (i = 0; i < li.length; i++) {
                    dragbar[li[i]] = insertDragbar(li[i]);
                }
            }
            function createBorders(li) {
                var cl, i;
                for (i = 0; i < li.length; i++) {
                    switch (li[i]) {
                      case "n":
                        cl = "hline";
                        break;

                      case "s":
                        cl = "hline bottom";
                        break;

                      case "e":
                        cl = "vline right";
                        break;

                      case "w":
                        cl = "vline";
                        break;
                    }
                    borders[li[i]] = insertBorder(cl);
                }
            }
            function createHandles(li) {
                var i;
                for (i = 0; i < li.length; i++) {
                    handle[li[i]] = insertHandle(li[i]);
                }
            }
            function moveto(x, y) {
                if (!options.shade) {
                    $img2.css({
                        top: px(-y),
                        left: px(-x)
                    });
                }
                $sel.css({
                    top: px(y),
                    left: px(x)
                });
            }
            function resize(w, h) {
                $sel.width(Math.round(w)).height(Math.round(h));
            }
            function refresh() {
                var c = Coords.getFixed();
                Coords.setPressed([ c.x, c.y ]);
                Coords.setCurrent([ c.x2, c.y2 ]);
                updateVisible();
            }
            function updateVisible(select) {
                if (awake) {
                    return update(select);
                }
            }
            function update(select) {
                var c = Coords.getFixed();
                resize(c.w, c.h);
                moveto(c.x, c.y);
                if (options.shade) Shade.updateRaw(c);
                awake || show();
                if (select) {
                    options.onSelect.call(api, unscale(c));
                } else {
                    options.onChange.call(api, unscale(c));
                }
            }
            function setBgOpacity(opacity, force, now) {
                if (!awake && !force) return;
                if (options.bgFade && !now) {
                    $img.animate({
                        opacity: opacity
                    }, {
                        queue: false,
                        duration: options.fadeTime
                    });
                } else {
                    $img.css("opacity", opacity);
                }
            }
            function show() {
                $sel.show();
                if (options.shade) Shade.opacity(bgopacity); else setBgOpacity(bgopacity, true);
                awake = true;
            }
            function release() {
                disableHandles();
                $sel.hide();
                if (options.shade) Shade.opacity(1); else setBgOpacity(1);
                awake = false;
                options.onRelease.call(api);
            }
            function showHandles() {
                if (seehandles) {
                    $hdl_holder.show();
                }
            }
            function enableHandles() {
                seehandles = true;
                if (options.allowResize) {
                    $hdl_holder.show();
                    return true;
                }
            }
            function disableHandles() {
                seehandles = false;
                $hdl_holder.hide();
            }
            function animMode(v) {
                if (v) {
                    animating = true;
                    disableHandles();
                } else {
                    animating = false;
                    enableHandles();
                }
            }
            function done() {
                animMode(false);
                refresh();
            }
            if (options.dragEdges && $.isArray(options.createDragbars)) createDragbars(options.createDragbars);
            if ($.isArray(options.createHandles)) createHandles(options.createHandles);
            if (options.drawBorders && $.isArray(options.createBorders)) createBorders(options.createBorders);
            $(document).bind("touchstart.jcrop-ios", function(e) {
                if ($(e.currentTarget).hasClass("jcrop-tracker")) e.stopPropagation();
            });
            var $track = newTracker().mousedown(createDragger("move")).css({
                cursor: "move",
                position: "absolute",
                zIndex: 360
            });
            if (Touch.support) {
                $track.bind("touchstart.jcrop", Touch.createDragger("move"));
            }
            $img_holder.append($track);
            disableHandles();
            return {
                updateVisible: updateVisible,
                update: update,
                release: release,
                refresh: refresh,
                isAwake: function() {
                    return awake;
                },
                setCursor: function(cursor) {
                    $track.css("cursor", cursor);
                },
                enableHandles: enableHandles,
                enableOnly: function() {
                    seehandles = true;
                },
                showHandles: showHandles,
                disableHandles: disableHandles,
                animMode: animMode,
                setBgOpacity: setBgOpacity,
                done: done
            };
        }();
        var Tracker = function() {
            var onMove = function() {}, onDone = function() {}, trackDoc = options.trackDocument;
            function toFront(touch) {
                $trk.css({
                    zIndex: 450
                });
                if (touch) $(document).bind("touchmove.jcrop", trackTouchMove).bind("touchend.jcrop", trackTouchEnd); else if (trackDoc) $(document).bind("mousemove.jcrop", trackMove).bind("mouseup.jcrop", trackUp);
            }
            function toBack() {
                $trk.css({
                    zIndex: 290
                });
                $(document).unbind(".jcrop");
            }
            function trackMove(e) {
                onMove(mouseAbs(e));
                return false;
            }
            function trackUp(e) {
                e.preventDefault();
                e.stopPropagation();
                if (btndown) {
                    btndown = false;
                    onDone(mouseAbs(e));
                    if (Selection.isAwake()) {
                        options.onSelect.call(api, unscale(Coords.getFixed()));
                    }
                    toBack();
                    onMove = function() {};
                    onDone = function() {};
                }
                return false;
            }
            function activateHandlers(move, done, touch) {
                btndown = true;
                onMove = move;
                onDone = done;
                toFront(touch);
                return false;
            }
            function trackTouchMove(e) {
                onMove(mouseAbs(Touch.cfilter(e)));
                return false;
            }
            function trackTouchEnd(e) {
                return trackUp(Touch.cfilter(e));
            }
            function setCursor(t) {
                $trk.css("cursor", t);
            }
            if (!trackDoc) {
                $trk.mousemove(trackMove).mouseup(trackUp).mouseout(trackUp);
            }
            $img.before($trk);
            return {
                activateHandlers: activateHandlers,
                setCursor: setCursor
            };
        }();
        var KeyManager = function() {
            var $keymgr = $('<input type="radio" />').css({
                position: "fixed",
                left: "-120px",
                width: "12px"
            }).addClass("jcrop-keymgr"), $keywrap = $("<div />").css({
                position: "absolute",
                overflow: "hidden"
            }).append($keymgr);
            function watchKeys() {
                if (options.keySupport) {}
            }
            function onBlur(e) {
                $keymgr.hide();
            }
            function doNudge(e, x, y) {
                if (options.allowMove) {
                    Coords.moveOffset([ x, y ]);
                    Selection.updateVisible(true);
                }
                e.preventDefault();
                e.stopPropagation();
            }
            function parseKey(e) {
                if (e.ctrlKey || e.metaKey) {
                    return true;
                }
                shift_down = e.shiftKey ? true : false;
                var nudge = shift_down ? 10 : 1;
                switch (e.keyCode) {
                  case 37:
                    doNudge(e, -nudge, 0);
                    break;

                  case 39:
                    doNudge(e, nudge, 0);
                    break;

                  case 38:
                    doNudge(e, 0, -nudge);
                    break;

                  case 40:
                    doNudge(e, 0, nudge);
                    break;

                  case 27:
                    if (options.allowSelect) Selection.release();
                    break;

                  case 9:
                    return true;
                }
                return false;
            }
            if (options.keySupport) {
                $keymgr.keydown(parseKey).blur(onBlur);
                if (ie6mode || !options.fixedSupport) {
                    $keymgr.css({
                        position: "absolute",
                        left: "-20px"
                    });
                    $keywrap.append($keymgr).insertBefore($img);
                } else {
                    $keymgr.insertBefore($img);
                }
                $keymgr.hide();
            }
            return {
                watchKeys: watchKeys
            };
        }();
        function setClass(cname) {
            $div.removeClass().addClass(cssClass("holder")).addClass(cname);
        }
        function animateTo(a, callback) {
            var x1 = a[0] / xscale, y1 = a[1] / yscale, x2 = a[2] / xscale, y2 = a[3] / yscale;
            if (animating) {
                return;
            }
            var animto = Coords.flipCoords(x1, y1, x2, y2), c = Coords.getFixed(), initcr = [ c.x, c.y, c.x2, c.y2 ], animat = initcr, interv = options.animationDelay, ix1 = animto[0] - initcr[0], iy1 = animto[1] - initcr[1], ix2 = animto[2] - initcr[2], iy2 = animto[3] - initcr[3], pcent = 0, velocity = options.swingSpeed;
            x1 = animat[0];
            y1 = animat[1];
            x2 = animat[2];
            y2 = animat[3];
            Selection.animMode(true);
            var anim_timer;
            function queueAnimator() {
                window.setTimeout(animator, interv);
            }
            var animator = function() {
                return function() {
                    pcent += (100 - pcent) / velocity;
                    animat[0] = Math.round(x1 + pcent / 100 * ix1);
                    animat[1] = Math.round(y1 + pcent / 100 * iy1);
                    animat[2] = Math.round(x2 + pcent / 100 * ix2);
                    animat[3] = Math.round(y2 + pcent / 100 * iy2);
                    if (pcent >= 99.8) {
                        pcent = 100;
                    }
                    if (pcent < 100) {
                        setSelectRaw(animat);
                        queueAnimator();
                    } else {
                        Selection.done();
                        Selection.animMode(false);
                        if (typeof callback === "function") {
                            callback.call(api);
                        }
                    }
                };
            }();
            queueAnimator();
        }
        function setSelect(rect) {
            setSelectRaw([ rect[0] / xscale, rect[1] / yscale, rect[2] / xscale, rect[3] / yscale ]);
            options.onSelect.call(api, unscale(Coords.getFixed()));
            Selection.enableHandles();
        }
        function setSelectRaw(l) {
            Coords.setPressed([ l[0], l[1] ]);
            Coords.setCurrent([ l[2], l[3] ]);
            Selection.update();
        }
        function tellSelect() {
            return unscale(Coords.getFixed());
        }
        function tellScaled() {
            return Coords.getFixed();
        }
        function setOptionsNew(opt) {
            setOptions(opt);
            interfaceUpdate();
        }
        function disableCrop() {
            options.disabled = true;
            Selection.disableHandles();
            Selection.setCursor("default");
            Tracker.setCursor("default");
        }
        function enableCrop() {
            options.disabled = false;
            interfaceUpdate();
        }
        function cancelCrop() {
            Selection.done();
            Tracker.activateHandlers(null, null);
        }
        function destroy() {
            $div.remove();
            $origimg.show();
            $origimg.css("visibility", "visible");
            $(obj).removeData("Jcrop");
        }
        function setImage(src, callback) {
            Selection.release();
            disableCrop();
            var img = new Image();
            img.onload = function() {
                var iw = img.width;
                var ih = img.height;
                var bw = options.boxWidth;
                var bh = options.boxHeight;
                $img.width(iw).height(ih);
                $img.attr("src", src);
                $img2.attr("src", src);
                presize($img, bw, bh);
                boundx = $img.width();
                boundy = $img.height();
                $img2.width(boundx).height(boundy);
                $trk.width(boundx + bound * 2).height(boundy + bound * 2);
                $div.width(boundx).height(boundy);
                Shade.resize(boundx, boundy);
                enableCrop();
                if (typeof callback === "function") {
                    callback.call(api);
                }
            };
            img.src = src;
        }
        function colorChangeMacro($obj, color, now) {
            var mycolor = color || options.bgColor;
            if (options.bgFade && supportsColorFade() && options.fadeTime && !now) {
                $obj.animate({
                    backgroundColor: mycolor
                }, {
                    queue: false,
                    duration: options.fadeTime
                });
            } else {
                $obj.css("backgroundColor", mycolor);
            }
        }
        function interfaceUpdate(alt) {
            if (options.allowResize) {
                if (alt) {
                    Selection.enableOnly();
                } else {
                    Selection.enableHandles();
                }
            } else {
                Selection.disableHandles();
            }
            Tracker.setCursor(options.allowSelect ? "crosshair" : "default");
            Selection.setCursor(options.allowMove ? "move" : "default");
            if (options.hasOwnProperty("trueSize")) {
                xscale = options.trueSize[0] / boundx;
                yscale = options.trueSize[1] / boundy;
            }
            if (options.hasOwnProperty("setSelect")) {
                setSelect(options.setSelect);
                Selection.done();
                delete options.setSelect;
            }
            Shade.refresh();
            if (options.bgColor != bgcolor) {
                colorChangeMacro(options.shade ? Shade.getShades() : $div, options.shade ? options.shadeColor || options.bgColor : options.bgColor);
                bgcolor = options.bgColor;
            }
            if (bgopacity != options.bgOpacity) {
                bgopacity = options.bgOpacity;
                if (options.shade) Shade.refresh(); else Selection.setBgOpacity(bgopacity);
            }
            xlimit = options.maxSize[0] || 0;
            ylimit = options.maxSize[1] || 0;
            xmin = options.minSize[0] || 0;
            ymin = options.minSize[1] || 0;
            if (options.hasOwnProperty("outerImage")) {
                $img.attr("src", options.outerImage);
                delete options.outerImage;
            }
            Selection.refresh();
        }
        if (Touch.support) $trk.bind("touchstart.jcrop", Touch.newSelection);
        $hdl_holder.hide();
        interfaceUpdate(true);
        var api = {
            setImage: setImage,
            animateTo: animateTo,
            setSelect: setSelect,
            setOptions: setOptionsNew,
            tellSelect: tellSelect,
            tellScaled: tellScaled,
            setClass: setClass,
            disable: disableCrop,
            enable: enableCrop,
            cancel: cancelCrop,
            release: Selection.release,
            destroy: destroy,
            focus: KeyManager.watchKeys,
            getBounds: function() {
                return [ boundx * xscale, boundy * yscale ];
            },
            getWidgetSize: function() {
                return [ boundx, boundy ];
            },
            getScaleFactor: function() {
                return [ xscale, yscale ];
            },
            getOptions: function() {
                return options;
            },
            ui: {
                holder: $div,
                selection: $sel
            }
        };
        if (is_msie) $div.bind("selectstart", function() {
            return false;
        });
        $origimg.data("Jcrop", api);
        return api;
    };
    $.fn.Jcrop = function(options, callback) {
        var api;
        this.each(function() {
            if ($(this).data("Jcrop")) {
                if (options === "api") return $(this).data("Jcrop"); else $(this).data("Jcrop").setOptions(options);
            } else {
                if (this.tagName == "IMG") $.Jcrop.Loader(this, function() {
                    $(this).css({
                        display: "block",
                        visibility: "hidden"
                    });
                    api = $.Jcrop(this, options);
                    if ($.isFunction(callback)) callback.call(api);
                }); else {
                    $(this).css({
                        display: "block",
                        visibility: "hidden"
                    });
                    api = $.Jcrop(this, options);
                    if ($.isFunction(callback)) callback.call(api);
                }
            }
        });
        return this;
    };
    $.Jcrop.Loader = function(imgobj, success, error) {
        var $img = $(imgobj), img = $img[0];
        function completeCheck() {
            if (img.complete) {
                $img.unbind(".jcloader");
                if ($.isFunction(success)) success.call(img);
            } else window.setTimeout(completeCheck, 50);
        }
        $img.bind("load.jcloader", completeCheck).bind("error.jcloader", function(e) {
            $img.unbind(".jcloader");
            if ($.isFunction(error)) error.call(img);
        });
        if (img.complete && $.isFunction(success)) {
            $img.unbind(".jcloader");
            success.call(img);
        }
    };
    $.Jcrop.defaults = {
        allowSelect: true,
        allowMove: true,
        allowResize: true,
        trackDocument: true,
        baseClass: "jcrop",
        addClass: null,
        bgColor: "black",
        bgOpacity: .6,
        bgFade: false,
        borderOpacity: .4,
        handleOpacity: .5,
        handleSize: null,
        aspectRatio: 0,
        keySupport: true,
        createHandles: [ "n", "s", "e", "w", "nw", "ne", "se", "sw" ],
        createDragbars: [ "n", "s", "e", "w" ],
        createBorders: [ "n", "s", "e", "w" ],
        drawBorders: true,
        dragEdges: true,
        fixedSupport: true,
        touchSupport: null,
        shade: null,
        boxWidth: 0,
        boxHeight: 0,
        boundary: 2,
        fadeTime: 400,
        animationDelay: 20,
        swingSpeed: 3,
        minSelect: [ 0, 0 ],
        maxSize: [ 0, 0 ],
        minSize: [ 0, 0 ],
        onChange: function() {},
        onSelect: function() {},
        onDblClick: function() {},
        onRelease: function() {}
    };
})(jQuery);

(function(root, factory) {
    if (typeof define === "function" && define.amd) {
        define([ "jquery" ], factory);
    } else {
        factory(root.jQuery);
    }
})(this, function($) {
    "use strict";
    $.extendext = function() {
        var options, name, src, copy, copyIsArray, clone, target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, arrayMode = "default";
        if (typeof target === "boolean") {
            deep = target;
            target = arguments[i++] || {};
        }
        if (typeof target === "string") {
            arrayMode = $([ target.toLowerCase(), "default" ]).filter([ "default", "concat", "replace", "extend" ])[0];
            target = arguments[i++] || {};
        }
        if (typeof target !== "object" && !$.isFunction(target)) {
            target = {};
        }
        if (i === length) {
            target = this;
            i--;
        }
        for (;i < length; i++) {
            if ((options = arguments[i]) !== null) {
                if ($.isArray(options) && arrayMode !== "default") {
                    clone = target && $.isArray(target) ? target : [];
                    switch (arrayMode) {
                      case "concat":
                        target = clone.concat($.extend(deep, [], options));
                        break;

                      case "replace":
                        target = $.extend(deep, [], options);
                        break;

                      case "extend":
                        options.forEach(function(e, i) {
                            if (typeof e === "object") {
                                var type = $.isArray(e) ? [] : {};
                                clone[i] = $.extendext(deep, arrayMode, clone[i] || type, e);
                            } else if (clone.indexOf(e) === -1) {
                                clone.push(e);
                            }
                        });
                        target = clone;
                        break;
                    }
                } else {
                    for (name in options) {
                        src = target[name];
                        copy = options[name];
                        if (target === copy) {
                            continue;
                        }
                        if (deep && copy && ($.isPlainObject(copy) || (copyIsArray = $.isArray(copy)))) {
                            if (copyIsArray) {
                                copyIsArray = false;
                                clone = src && $.isArray(src) ? src : [];
                            } else {
                                clone = src && $.isPlainObject(src) ? src : {};
                            }
                            target[name] = $.extendext(deep, arrayMode, clone, copy);
                        } else if (copy !== undefined) {
                            target[name] = copy;
                        }
                    }
                }
            }
        }
        return target;
    };
});

(function() {
    "use strict";
    var doT = {
        version: "1.0.3",
        templateSettings: {
            evaluate: /\{\{([\s\S]+?(\}?)+)\}\}/g,
            interpolate: /\{\{=([\s\S]+?)\}\}/g,
            encode: /\{\{!([\s\S]+?)\}\}/g,
            use: /\{\{#([\s\S]+?)\}\}/g,
            useParams: /(^|[^\w$])def(?:\.|\[[\'\"])([\w$\.]+)(?:[\'\"]\])?\s*\:\s*([\w$\.]+|\"[^\"]+\"|\'[^\']+\'|\{[^\}]+\})/g,
            define: /\{\{##\s*([\w\.$]+)\s*(\:|=)([\s\S]+?)#\}\}/g,
            defineParams: /^\s*([\w$]+):([\s\S]+)/,
            conditional: /\{\{\?(\?)?\s*([\s\S]*?)\s*\}\}/g,
            iterate: /\{\{~\s*(?:\}\}|([\s\S]+?)\s*\:\s*([\w$]+)\s*(?:\:\s*([\w$]+))?\s*\}\})/g,
            varname: "it",
            strip: true,
            append: true,
            selfcontained: false,
            doNotSkipEncoded: false
        },
        template: undefined,
        compile: undefined
    }, _globals;
    doT.encodeHTMLSource = function(doNotSkipEncoded) {
        var encodeHTMLRules = {
            "&": "&#38;",
            "<": "&#60;",
            ">": "&#62;",
            '"': "&#34;",
            "'": "&#39;",
            "/": "&#47;"
        }, matchHTML = doNotSkipEncoded ? /[&<>"'\/]/g : /&(?!#?\w+;)|<|>|"|'|\//g;
        return function(code) {
            return code ? code.toString().replace(matchHTML, function(m) {
                return encodeHTMLRules[m] || m;
            }) : "";
        };
    };
    _globals = function() {
        return this || (0, eval)("this");
    }();
    if (typeof module !== "undefined" && module.exports) {
        module.exports = doT;
    } else if (typeof define === "function" && define.amd) {
        define(function() {
            return doT;
        });
    } else {
        _globals.doT = doT;
    }
    var startend = {
        append: {
            start: "'+(",
            end: ")+'",
            startencode: "'+encodeHTML("
        },
        split: {
            start: "';out+=(",
            end: ");out+='",
            startencode: "';out+=encodeHTML("
        }
    }, skip = /$^/;
    function resolveDefs(c, block, def) {
        return (typeof block === "string" ? block : block.toString()).replace(c.define || skip, function(m, code, assign, value) {
            if (code.indexOf("def.") === 0) {
                code = code.substring(4);
            }
            if (!(code in def)) {
                if (assign === ":") {
                    if (c.defineParams) value.replace(c.defineParams, function(m, param, v) {
                        def[code] = {
                            arg: param,
                            text: v
                        };
                    });
                    if (!(code in def)) def[code] = value;
                } else {
                    new Function("def", "def['" + code + "']=" + value)(def);
                }
            }
            return "";
        }).replace(c.use || skip, function(m, code) {
            if (c.useParams) code = code.replace(c.useParams, function(m, s, d, param) {
                if (def[d] && def[d].arg && param) {
                    var rw = (d + ":" + param).replace(/'|\\/g, "_");
                    def.__exp = def.__exp || {};
                    def.__exp[rw] = def[d].text.replace(new RegExp("(^|[^\\w$])" + def[d].arg + "([^\\w$])", "g"), "$1" + param + "$2");
                    return s + "def.__exp['" + rw + "']";
                }
            });
            var v = new Function("def", "return " + code)(def);
            return v ? resolveDefs(c, v, def) : v;
        });
    }
    function unescape(code) {
        return code.replace(/\\('|\\)/g, "$1").replace(/[\r\t\n]/g, " ");
    }
    doT.template = function(tmpl, c, def) {
        c = c || doT.templateSettings;
        var cse = c.append ? startend.append : startend.split, needhtmlencode, sid = 0, indv, str = c.use || c.define ? resolveDefs(c, tmpl, def || {}) : tmpl;
        str = ("var out='" + (c.strip ? str.replace(/(^|\r|\n)\t* +| +\t*(\r|\n|$)/g, " ").replace(/\r|\n|\t|\/\*[\s\S]*?\*\//g, "") : str).replace(/'|\\/g, "\\$&").replace(c.interpolate || skip, function(m, code) {
            return cse.start + unescape(code) + cse.end;
        }).replace(c.encode || skip, function(m, code) {
            needhtmlencode = true;
            return cse.startencode + unescape(code) + cse.end;
        }).replace(c.conditional || skip, function(m, elsecase, code) {
            return elsecase ? code ? "';}else if(" + unescape(code) + "){out+='" : "';}else{out+='" : code ? "';if(" + unescape(code) + "){out+='" : "';}out+='";
        }).replace(c.iterate || skip, function(m, iterate, vname, iname) {
            if (!iterate) return "';} } out+='";
            sid += 1;
            indv = iname || "i" + sid;
            iterate = unescape(iterate);
            return "';var arr" + sid + "=" + iterate + ";if(arr" + sid + "){var " + vname + "," + indv + "=-1,l" + sid + "=arr" + sid + ".length-1;while(" + indv + "<l" + sid + "){" + vname + "=arr" + sid + "[" + indv + "+=1];out+='";
        }).replace(c.evaluate || skip, function(m, code) {
            return "';" + unescape(code) + "out+='";
        }) + "';return out;").replace(/\n/g, "\\n").replace(/\t/g, "\\t").replace(/\r/g, "\\r").replace(/(\s|;|\}|^|\{)out\+='';/g, "$1").replace(/\+''/g, "");
        if (needhtmlencode) {
            if (!c.selfcontained && _globals && !_globals._encodeHTML) _globals._encodeHTML = doT.encodeHTMLSource(c.doNotSkipEncoded);
            str = "var encodeHTML = typeof _encodeHTML !== 'undefined' ? _encodeHTML : (" + doT.encodeHTMLSource.toString() + "(" + (c.doNotSkipEncoded || "") + "));" + str;
        }
        try {
            return new Function(c.varname, str);
        } catch (e) {
            if (typeof console !== "undefined") console.log("Could not create a template function: " + str);
            throw e;
        }
    };
    doT.compile = function(tmpl, def) {
        return doT.template(tmpl, null, def);
    };
})();

(function webpackUniversalModuleDefinition(root, factory) {
    if (typeof exports === "object" && typeof module === "object") module.exports = factory(); else if (typeof define === "function" && define.amd) define([], factory); else if (typeof exports === "object") exports["agGrid"] = factory(); else root["agGrid"] = factory();
})(this, function() {
    return function(modules) {
        var installedModules = {};
        function __webpack_require__(moduleId) {
            if (installedModules[moduleId]) {
                return installedModules[moduleId].exports;
            }
            var module = installedModules[moduleId] = {
                i: moduleId,
                l: false,
                exports: {}
            };
            modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
            module.l = true;
            return module.exports;
        }
        __webpack_require__.m = modules;
        __webpack_require__.c = installedModules;
        __webpack_require__.d = function(exports, name, getter) {
            if (!__webpack_require__.o(exports, name)) {
                Object.defineProperty(exports, name, {
                    configurable: false,
                    enumerable: true,
                    get: getter
                });
            }
        };
        __webpack_require__.n = function(module) {
            var getter = module && module.__esModule ? function getDefault() {
                return module["default"];
            } : function getModuleExports() {
                return module;
            };
            __webpack_require__.d(getter, "a", getter);
            return getter;
        };
        __webpack_require__.o = function(object, property) {
            return Object.prototype.hasOwnProperty.call(object, property);
        };
        __webpack_require__.p = "";
        return __webpack_require__(__webpack_require__.s = 119);
    }([ function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var Context = function() {
            function Context(params, logger) {
                this.beans = {};
                this.componentsMappedByName = {};
                this.destroyed = false;
                if (!params || !params.beans) {
                    return;
                }
                this.contextParams = params;
                this.logger = logger;
                this.logger.log(">> creating ag-Application Context");
                this.setupComponents();
                this.createBeans();
                var beans = utils_1.Utils.mapObject(this.beans, function(beanEntry) {
                    return beanEntry.beanInstance;
                });
                this.wireBeans(beans);
                this.logger.log(">> ag-Application Context ready - component is alive");
            }
            Context.prototype.setupComponents = function() {
                var _this = this;
                if (this.contextParams.components) {
                    this.contextParams.components.forEach(function(componentMeta) {
                        return _this.addComponent(componentMeta);
                    });
                }
            };
            Context.prototype.addComponent = function(componentMeta) {
                var classEscaped = componentMeta.componentName.replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase();
                var classUpperCase = classEscaped.toUpperCase();
                this.componentsMappedByName[classUpperCase] = componentMeta.theClass;
            };
            Context.prototype.createComponent = function(element, afterPreCreateCallback) {
                var key = element.nodeName;
                if (this.componentsMappedByName && this.componentsMappedByName[key]) {
                    var newComponent = new this.componentsMappedByName[key]();
                    this.wireBean(newComponent, afterPreCreateCallback);
                    return newComponent;
                } else {
                    return null;
                }
            };
            Context.prototype.wireBean = function(bean, afterPreCreateCallback) {
                if (!bean) {
                    throw Error("Can't wire to bean since it is null");
                }
                this.wireBeans([ bean ], afterPreCreateCallback);
            };
            Context.prototype.wireBeans = function(beans, afterPreCreateCallback) {
                this.autoWireBeans(beans);
                this.methodWireBeans(beans);
                this.preConstruct(beans);
                if (utils_1.Utils.exists(afterPreCreateCallback)) {
                    beans.forEach(afterPreCreateCallback);
                }
                this.postConstruct(beans);
            };
            Context.prototype.createBeans = function() {
                var _this = this;
                this.contextParams.beans.forEach(this.createBeanEntry.bind(this));
                if (this.contextParams.overrideBeans) {
                    this.contextParams.overrideBeans.forEach(this.createBeanEntry.bind(this));
                }
                utils_1.Utils.iterateObject(this.beans, function(key, beanEntry) {
                    var constructorParamsMeta;
                    if (beanEntry.bean.__agBeanMetaData && beanEntry.bean.__agBeanMetaData.autowireMethods && beanEntry.bean.__agBeanMetaData.autowireMethods.agConstructor) {
                        constructorParamsMeta = beanEntry.bean.__agBeanMetaData.autowireMethods.agConstructor;
                    }
                    var constructorParams = _this.getBeansForParameters(constructorParamsMeta, beanEntry.bean.name);
                    var newInstance = applyToConstructor(beanEntry.bean, constructorParams);
                    beanEntry.beanInstance = newInstance;
                    _this.logger.log("bean " + _this.getBeanName(newInstance) + " created");
                });
            };
            Context.prototype.createBeanEntry = function(Bean) {
                var metaData = Bean.__agBeanMetaData;
                if (!metaData) {
                    var beanName = void 0;
                    if (Bean.prototype.constructor) {
                        beanName = Bean.prototype.constructor.name;
                    } else {
                        beanName = "" + Bean;
                    }
                    console.error("context item " + beanName + " is not a bean");
                    return;
                }
                var beanEntry = {
                    bean: Bean,
                    beanInstance: null,
                    beanName: metaData.beanName
                };
                this.beans[metaData.beanName] = beanEntry;
            };
            Context.prototype.autoWireBeans = function(beans) {
                var _this = this;
                beans.forEach(function(bean) {
                    return _this.autoWireBean(bean);
                });
            };
            Context.prototype.methodWireBeans = function(beans) {
                var _this = this;
                beans.forEach(function(bean) {
                    if (!bean) {
                        throw Error("Can't wire to bean since it is null");
                    }
                    return _this.methodWireBean(bean);
                });
            };
            Context.prototype.autoWireBean = function(bean) {
                var _this = this;
                var currentBean = bean;
                var _loop_1 = function() {
                    var currentConstructor = currentBean.constructor;
                    if (currentConstructor.__agBeanMetaData && currentConstructor.__agBeanMetaData.agClassAttributes) {
                        var attributes = currentConstructor.__agBeanMetaData.agClassAttributes;
                        if (!attributes) {
                            return {
                                value: void 0
                            };
                        }
                        var beanName_1 = this_1.getBeanName(currentConstructor);
                        attributes.forEach(function(attribute) {
                            var otherBean = _this.lookupBeanInstance(beanName_1, attribute.beanName, attribute.optional);
                            bean[attribute.attributeName] = otherBean;
                        });
                    }
                    currentBean = Object.getPrototypeOf(currentBean) ? Object.getPrototypeOf(currentBean) : null;
                };
                var this_1 = this;
                while (currentBean != null) {
                    var state_1 = _loop_1();
                    if (typeof state_1 === "object") return state_1.value;
                }
            };
            Context.prototype.getBeanName = function(constructor) {
                if (constructor.__agBeanMetaData && constructor.__agBeanMetaData.beanName) {
                    return constructor.__agBeanMetaData.beanName;
                }
                var constructorString = constructor.toString();
                var beanName = constructorString.substring(9, constructorString.indexOf("("));
                return beanName;
            };
            Context.prototype.methodWireBean = function(bean) {
                var _this = this;
                var autowiredMethods;
                if (bean.constructor.__agBeanMetaData && bean.constructor.__agBeanMetaData.autowireMethods) {
                    autowiredMethods = bean.constructor.__agBeanMetaData.autowireMethods;
                }
                utils_1.Utils.iterateObject(autowiredMethods, function(methodName, wireParams) {
                    if (methodName === "agConstructor") {
                        return;
                    }
                    var beanName = _this.getBeanName(bean.constructor);
                    var initParams = _this.getBeansForParameters(wireParams, beanName);
                    bean[methodName].apply(bean, initParams);
                });
            };
            Context.prototype.getBeansForParameters = function(parameters, beanName) {
                var _this = this;
                var beansList = [];
                if (parameters) {
                    utils_1.Utils.iterateObject(parameters, function(paramIndex, otherBeanName) {
                        var otherBean = _this.lookupBeanInstance(beanName, otherBeanName);
                        beansList[Number(paramIndex)] = otherBean;
                    });
                }
                return beansList;
            };
            Context.prototype.lookupBeanInstance = function(wiringBean, beanName, optional) {
                if (optional === void 0) {
                    optional = false;
                }
                if (beanName === "context") {
                    return this;
                } else if (this.contextParams.seed && this.contextParams.seed.hasOwnProperty(beanName)) {
                    return this.contextParams.seed[beanName];
                } else {
                    var beanEntry = this.beans[beanName];
                    if (beanEntry) {
                        return beanEntry.beanInstance;
                    }
                    if (!optional) {
                        console.error("ag-Grid: unable to find bean reference " + beanName + " while initialising " + wiringBean);
                    }
                    return null;
                }
            };
            Context.prototype.postConstruct = function(beans) {
                beans.forEach(function(bean) {
                    if (bean.constructor.__agBeanMetaData && bean.constructor.__agBeanMetaData.postConstructMethods) {
                        bean.constructor.__agBeanMetaData && bean.constructor.__agBeanMetaData.postConstructMethods.forEach(function(methodName) {
                            return bean[methodName]();
                        });
                    }
                });
            };
            Context.prototype.preConstruct = function(beans) {
                beans.forEach(function(bean) {
                    if (bean.constructor.__agBeanMetaData && bean.constructor.__agBeanMetaData.preConstructMethods) {
                        bean.constructor.__agBeanMetaData.preConstructMethods.forEach(function(methodName) {
                            return bean[methodName]();
                        });
                    }
                });
            };
            Context.prototype.getBean = function(name) {
                return this.lookupBeanInstance("getBean", name, true);
            };
            Context.prototype.destroy = function() {
                if (this.destroyed) {
                    return;
                }
                this.logger.log(">> Shutting down ag-Application Context");
                utils_1.Utils.iterateObject(this.beans, function(key, beanEntry) {
                    var bean = beanEntry.beanInstance;
                    if (bean.constructor.__agBeanMetaData && bean.constructor.__agBeanMetaData.preDestroyMethods) {
                        bean.constructor.__agBeanMetaData.preDestroyMethods.forEach(function(methodName) {
                            return bean[methodName]();
                        });
                    }
                });
                this.destroyed = true;
                this.logger.log(">> ag-Application Context shut down - component is dead");
            };
            return Context;
        }();
        exports.Context = Context;
        function applyToConstructor(constructor, argArray) {
            var args = [ null ].concat(argArray);
            var factoryFunction = constructor.bind.apply(constructor, args);
            return new factoryFunction();
        }
        function PreConstruct(target, methodName, descriptor) {
            var props = getOrCreateProps(target.constructor);
            if (!props.postConstructMethods) {
                props.preConstructMethods = [];
            }
            props.preConstructMethods.push(methodName);
        }
        exports.PreConstruct = PreConstruct;
        function PostConstruct(target, methodName, descriptor) {
            var props = getOrCreateProps(target.constructor);
            if (!props.postConstructMethods) {
                props.postConstructMethods = [];
            }
            props.postConstructMethods.push(methodName);
        }
        exports.PostConstruct = PostConstruct;
        function PreDestroy(target, methodName, descriptor) {
            var props = getOrCreateProps(target.constructor);
            if (!props.preDestroyMethods) {
                props.preDestroyMethods = [];
            }
            props.preDestroyMethods.push(methodName);
        }
        exports.PreDestroy = PreDestroy;
        function Bean(beanName) {
            return function(classConstructor) {
                var props = getOrCreateProps(classConstructor);
                props.beanName = beanName;
            };
        }
        exports.Bean = Bean;
        function Autowired(name) {
            return function(target, propertyKey, descriptor) {
                autowiredFunc(target, name, false, target, propertyKey, null);
            };
        }
        exports.Autowired = Autowired;
        function Optional(name) {
            return function(target, propertyKey, descriptor) {
                autowiredFunc(target, name, true, target, propertyKey, null);
            };
        }
        exports.Optional = Optional;
        function autowiredFunc(target, name, optional, classPrototype, methodOrAttributeName, index) {
            if (name === null) {
                console.error("ag-Grid: Autowired name should not be null");
                return;
            }
            if (typeof index === "number") {
                console.error("ag-Grid: Autowired should be on an attribute");
                return;
            }
            var props = getOrCreateProps(target.constructor);
            if (!props.agClassAttributes) {
                props.agClassAttributes = [];
            }
            props.agClassAttributes.push({
                attributeName: methodOrAttributeName,
                beanName: name,
                optional: optional
            });
        }
        function Qualifier(name) {
            return function(classPrototype, methodOrAttributeName, index) {
                var constructor = typeof classPrototype == "function" ? classPrototype : classPrototype.constructor;
                var props;
                if (typeof index === "number") {
                    var methodName = void 0;
                    if (methodOrAttributeName) {
                        props = getOrCreateProps(constructor);
                        methodName = methodOrAttributeName;
                    } else {
                        props = getOrCreateProps(constructor);
                        methodName = "agConstructor";
                    }
                    if (!props.autowireMethods) {
                        props.autowireMethods = {};
                    }
                    if (!props.autowireMethods[methodName]) {
                        props.autowireMethods[methodName] = {};
                    }
                    props.autowireMethods[methodName][index] = name;
                }
            };
        }
        exports.Qualifier = Qualifier;
        function getOrCreateProps(target) {
            if (!target.hasOwnProperty("__agBeanMetaData")) {
                target.__agBeanMetaData = {};
            }
            return target.__agBeanMetaData;
        }
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var constants_1 = __webpack_require__(9);
        var FUNCTION_STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/gm;
        var FUNCTION_ARGUMENT_NAMES = /([^\s,]+)/g;
        var AG_GRID_STOP_PROPAGATION = "__ag_Grid_Stop_Propagation";
        var Timer = function() {
            function Timer() {
                this.timestamp = new Date().getTime();
            }
            Timer.prototype.print = function(msg) {
                var duration = new Date().getTime() - this.timestamp;
                console.log(msg + " = " + duration);
                this.timestamp = new Date().getTime();
            };
            return Timer;
        }();
        exports.Timer = Timer;
        var HTML_ESCAPES = {
            "&": "&amp;",
            "<": "&lt;",
            ">": "&gt;",
            '"': "&quot;",
            "'": "&#39;"
        };
        var reUnescapedHtml = /[&<>"']/g;
        var Utils = function() {
            function Utils() {}
            Utils.doOnce = function(func, key) {
                if (this.doOnceFlags[key]) {
                    return;
                }
                func();
                this.doOnceFlags[key] = true;
            };
            Utils.areEventsNear = function(e1, e2, pixelCount) {
                if (pixelCount === 0) {
                    return false;
                }
                var diffX = Math.abs(e1.clientX - e2.clientX);
                var diffY = Math.abs(e1.clientY - e2.clientY);
                return Math.max(diffX, diffY) <= pixelCount;
            };
            Utils.shallowCompare = function(arr1, arr2) {
                if (this.missing(arr1) && this.missing(arr2)) {
                    return true;
                }
                if (this.missing(arr1) || this.missing(arr2)) {
                    return false;
                }
                if (arr1.length !== arr2.length) {
                    return false;
                }
                for (var i = 0; i < arr1.length; i++) {
                    if (arr1[i] !== arr2[i]) {
                        return false;
                    }
                }
                return true;
            };
            Utils.getNameOfClass = function(TheClass) {
                var funcNameRegex = /function (.{1,})\(/;
                var funcAsString = TheClass.toString();
                var results = funcNameRegex.exec(funcAsString);
                return results && results.length > 1 ? results[1] : "";
            };
            Utils.values = function(object) {
                var result = [];
                this.iterateObject(object, function(key, value) {
                    result.push(value);
                });
                return result;
            };
            Utils.getValueUsingField = function(data, field, fieldContainsDots) {
                if (!field || !data) {
                    return;
                }
                if (!fieldContainsDots) {
                    return data[field];
                } else {
                    var fields = field.split(".");
                    var currentObject = data;
                    for (var i = 0; i < fields.length; i++) {
                        currentObject = currentObject[fields[i]];
                        if (this.missing(currentObject)) {
                            return null;
                        }
                    }
                    return currentObject;
                }
            };
            Utils.getScrollLeft = function(element, rtl) {
                var scrollLeft = element.scrollLeft;
                if (rtl) {
                    scrollLeft = Math.abs(scrollLeft);
                    if (this.isBrowserSafari() || this.isBrowserChrome()) {
                        scrollLeft = element.scrollWidth - element.clientWidth - scrollLeft;
                    }
                }
                return scrollLeft;
            };
            Utils.cleanNumber = function(value) {
                if (typeof value === "string") {
                    value = parseInt(value);
                }
                if (typeof value === "number") {
                    value = Math.floor(value);
                } else {
                    value = null;
                }
                return value;
            };
            Utils.setScrollLeft = function(element, value, rtl) {
                if (rtl) {
                    if (this.isBrowserSafari() || this.isBrowserChrome()) {
                        value = element.scrollWidth - element.clientWidth - value;
                    }
                    if (this.isBrowserFirefox()) {
                        value *= -1;
                    }
                }
                element.scrollLeft = value;
            };
            Utils.iterateNamedNodeMap = function(map, callback) {
                if (!map) {
                    return;
                }
                for (var i = 0; i < map.length; i++) {
                    var attr = map[i];
                    callback(attr.name, attr.value);
                }
            };
            Utils.iterateObject = function(object, callback) {
                if (this.missing(object)) {
                    return;
                }
                if (Array.isArray(object)) {
                    object.forEach(function(value, index) {
                        callback(index + "", value);
                    });
                } else {
                    var keys = Object.keys(object);
                    for (var i = 0; i < keys.length; i++) {
                        var key = keys[i];
                        var value = object[key];
                        callback(key, value);
                    }
                }
            };
            Utils.cloneObject = function(object) {
                var copy = {};
                var keys = Object.keys(object);
                for (var i = 0; i < keys.length; i++) {
                    var key = keys[i];
                    var value = object[key];
                    copy[key] = value;
                }
                return copy;
            };
            Utils.map = function(array, callback) {
                var result = [];
                for (var i = 0; i < array.length; i++) {
                    var item = array[i];
                    var mappedItem = callback(item);
                    result.push(mappedItem);
                }
                return result;
            };
            Utils.mapObject = function(object, callback) {
                var result = [];
                Utils.iterateObject(object, function(key, value) {
                    result.push(callback(value));
                });
                return result;
            };
            Utils.forEach = function(array, callback) {
                if (!array) {
                    return;
                }
                for (var i = 0; i < array.length; i++) {
                    var value = array[i];
                    callback(value, i);
                }
            };
            Utils.filter = function(array, callback) {
                var result = [];
                array.forEach(function(item) {
                    if (callback(item)) {
                        result.push(item);
                    }
                });
                return result;
            };
            Utils.getAllKeysInObjects = function(objects) {
                var allValues = {};
                objects.forEach(function(obj) {
                    if (obj) {
                        Object.keys(obj).forEach(function(key) {
                            return allValues[key] = null;
                        });
                    }
                });
                return Object.keys(allValues);
            };
            Utils.mergeDeep = function(dest, source) {
                if (this.exists(source)) {
                    this.iterateObject(source, function(key, newValue) {
                        var oldValue = dest[key];
                        if (oldValue === newValue) {
                            return;
                        }
                        if (typeof oldValue === "object" && typeof newValue === "object") {
                            Utils.mergeDeep(oldValue, newValue);
                        } else {
                            dest[key] = newValue;
                        }
                    });
                }
            };
            Utils.assign = function(object) {
                var _this = this;
                var sources = [];
                for (var _i = 1; _i < arguments.length; _i++) {
                    sources[_i - 1] = arguments[_i];
                }
                sources.forEach(function(source) {
                    if (_this.exists(source)) {
                        _this.iterateObject(source, function(key, value) {
                            object[key] = value;
                        });
                    }
                });
                return object;
            };
            Utils.parseYyyyMmDdToDate = function(yyyyMmDd, separator) {
                try {
                    if (!yyyyMmDd) return null;
                    if (yyyyMmDd.indexOf(separator) === -1) return null;
                    var fields = yyyyMmDd.split(separator);
                    if (fields.length != 3) return null;
                    return new Date(Number(fields[0]), Number(fields[1]) - 1, Number(fields[2]));
                } catch (e) {
                    return null;
                }
            };
            Utils.serializeDateToYyyyMmDd = function(date, separator) {
                if (!date) return null;
                return date.getFullYear() + separator + Utils.pad(date.getMonth() + 1, 2) + separator + Utils.pad(date.getDate(), 2);
            };
            Utils.pad = function(num, totalStringSize) {
                var asString = num + "";
                while (asString.length < totalStringSize) asString = "0" + asString;
                return asString;
            };
            Utils.pushAll = function(target, source) {
                if (this.missing(source) || this.missing(target)) {
                    return;
                }
                source.forEach(function(func) {
                    return target.push(func);
                });
            };
            Utils.createArrayOfNumbers = function(first, last) {
                var result = [];
                for (var i = first; i <= last; i++) {
                    result.push(i);
                }
                return result;
            };
            Utils.getFunctionParameters = function(func) {
                var fnStr = func.toString().replace(FUNCTION_STRIP_COMMENTS, "");
                var result = fnStr.slice(fnStr.indexOf("(") + 1, fnStr.indexOf(")")).match(FUNCTION_ARGUMENT_NAMES);
                if (result === null) {
                    return [];
                } else {
                    return result;
                }
            };
            Utils.find = function(collection, predicate, value) {
                if (collection === null || collection === undefined) {
                    return null;
                }
                if (!Array.isArray(collection)) {
                    var objToArray = this.values(collection);
                    return this.find(objToArray, predicate, value);
                }
                var collectionAsArray = collection;
                var firstMatchingItem;
                for (var i = 0; i < collectionAsArray.length; i++) {
                    var item = collectionAsArray[i];
                    if (typeof predicate === "string") {
                        if (item[predicate] === value) {
                            firstMatchingItem = item;
                            break;
                        }
                    } else {
                        var callback = predicate;
                        if (callback(item)) {
                            firstMatchingItem = item;
                            break;
                        }
                    }
                }
                return firstMatchingItem;
            };
            Utils.toStrings = function(array) {
                return this.map(array, function(item) {
                    if (item === undefined || item === null || !item.toString) {
                        return null;
                    } else {
                        return item.toString();
                    }
                });
            };
            Utils.iterateArray = function(array, callback) {
                for (var index = 0; index < array.length; index++) {
                    var value = array[index];
                    callback(value, index);
                }
            };
            Utils.isNode = function(o) {
                return typeof Node === "function" ? o instanceof Node : o && typeof o === "object" && typeof o.nodeType === "number" && typeof o.nodeName === "string";
            };
            Utils.isElement = function(o) {
                return typeof HTMLElement === "function" ? o instanceof HTMLElement : o && typeof o === "object" && o !== null && o.nodeType === 1 && typeof o.nodeName === "string";
            };
            Utils.isNodeOrElement = function(o) {
                return this.isNode(o) || this.isElement(o);
            };
            Utils.copyNodeList = function(nodeList) {
                var childCount = nodeList ? nodeList.length : 0;
                var res = [];
                for (var i = 0; i < childCount; i++) {
                    res.push(nodeList[i]);
                }
                return res;
            };
            Utils.isEventFromPrintableCharacter = function(event) {
                var pressedChar = String.fromCharCode(event.charCode);
                if (this.isKeyPressed(event, constants_1.Constants.KEY_NEW_LINE)) {
                    return false;
                }
                if (exports._.exists(event.key)) {
                    var printableCharacter = event.key.length === 1;
                    var numpadDelWithNumlockOnForEdgeOrIe = Utils.isNumpadDelWithNumlockOnForEdgeOrIe(event);
                    return printableCharacter || numpadDelWithNumlockOnForEdgeOrIe;
                } else {
                    return Utils.PRINTABLE_CHARACTERS.indexOf(pressedChar) >= 0;
                }
            };
            Utils.addChangeListener = function(element, listener) {
                element.addEventListener("changed", listener);
                element.addEventListener("paste", listener);
                element.addEventListener("input", listener);
                element.addEventListener("keydown", listener);
                element.addEventListener("keyup", listener);
            };
            Utils.makeNull = function(value) {
                var valueNoType = value;
                if (value === null || value === undefined || valueNoType === "") {
                    return null;
                } else {
                    return value;
                }
            };
            Utils.missing = function(value) {
                return !this.exists(value);
            };
            Utils.missingOrEmpty = function(value) {
                return this.missing(value) || value.length === 0;
            };
            Utils.missingOrEmptyObject = function(value) {
                return this.missing(value) || Object.keys(value).length === 0;
            };
            Utils.exists = function(value) {
                if (value === null || value === undefined || value === "") {
                    return false;
                } else {
                    return true;
                }
            };
            Utils.firstExistingValue = function() {
                var values = [];
                for (var _i = 0; _i < arguments.length; _i++) {
                    values[_i] = arguments[_i];
                }
                for (var i = 0; i < values.length; i++) {
                    var value = values[i];
                    if (exports._.exists(value)) return value;
                }
                return null;
            };
            Utils.anyExists = function(values) {
                if (values) {
                    for (var i = 0; i < values.length; i++) {
                        if (this.exists(values[i])) {
                            return true;
                        }
                    }
                }
                return false;
            };
            Utils.existsAndNotEmpty = function(value) {
                return this.exists(value) && value.length > 0;
            };
            Utils.removeAllChildren = function(node) {
                if (node) {
                    while (node.hasChildNodes()) {
                        node.removeChild(node.lastChild);
                    }
                }
            };
            Utils.removeElement = function(parent, cssSelector) {
                this.removeFromParent(parent.querySelector(cssSelector));
            };
            Utils.removeFromParent = function(node) {
                if (node && node.parentNode) {
                    node.parentNode.removeChild(node);
                }
            };
            Utils.isVisible = function(element) {
                return element.offsetParent !== null;
            };
            Utils.loadTemplate = function(template) {
                var tempDiv = document.createElement("div");
                tempDiv.innerHTML = template;
                return tempDiv.firstChild;
            };
            Utils.appendHtml = function(eContainer, htmlTemplate) {
                if (eContainer.lastChild) {
                    eContainer.insertAdjacentHTML("afterbegin", htmlTemplate);
                } else {
                    eContainer.innerHTML = htmlTemplate;
                }
            };
            Utils.addOrRemoveCssClass = function(element, className, addOrRemove) {
                if (addOrRemove) {
                    this.addCssClass(element, className);
                } else {
                    this.removeCssClass(element, className);
                }
            };
            Utils.callIfPresent = function(func) {
                if (func) {
                    func();
                }
            };
            Utils.addCssClass = function(element, className) {
                var _this = this;
                if (!className || className.length === 0) {
                    return;
                }
                if (className.indexOf(" ") >= 0) {
                    className.split(" ").forEach(function(value) {
                        return _this.addCssClass(element, value);
                    });
                    return;
                }
                if (element.classList) {
                    if (!element.classList.contains(className)) {
                        element.classList.add(className);
                    }
                } else {
                    if (element.className && element.className.length > 0) {
                        var cssClasses = element.className.split(" ");
                        if (cssClasses.indexOf(className) < 0) {
                            cssClasses.push(className);
                            element.className = cssClasses.join(" ");
                        }
                    } else {
                        element.className = className;
                    }
                }
            };
            Utils.containsClass = function(element, className) {
                if (element.classList) {
                    return element.classList.contains(className);
                } else if (element.className) {
                    var onlyClass = element.className === className;
                    var contains = element.className.indexOf(" " + className + " ") >= 0;
                    var startsWithClass = element.className.indexOf(className + " ") === 0;
                    var endsWithClass = element.className.lastIndexOf(" " + className) === element.className.length - className.length - 1;
                    return onlyClass || contains || startsWithClass || endsWithClass;
                } else {
                    return false;
                }
            };
            Utils.getElementAttribute = function(element, attributeName) {
                if (element.attributes) {
                    if (element.attributes[attributeName]) {
                        var attribute = element.attributes[attributeName];
                        return attribute.value;
                    } else {
                        return null;
                    }
                } else {
                    return null;
                }
            };
            Utils.offsetHeight = function(element) {
                return element && element.clientHeight ? element.clientHeight : 0;
            };
            Utils.offsetWidth = function(element) {
                return element && element.clientWidth ? element.clientWidth : 0;
            };
            Utils.sortNumberArray = function(numberArray) {
                numberArray.sort(function(a, b) {
                    return a - b;
                });
            };
            Utils.removeCssClass = function(element, className) {
                if (element.classList) {
                    if (element.classList.contains(className)) {
                        element.classList.remove(className);
                    }
                } else {
                    if (element.className && element.className.length > 0) {
                        var cssClasses = element.className.split(" ");
                        if (cssClasses.indexOf(className) >= 0) {
                            while (cssClasses.indexOf(className) >= 0) {
                                cssClasses.splice(cssClasses.indexOf(className), 1);
                            }
                            element.className = cssClasses.join(" ");
                        }
                    }
                }
            };
            Utils.removeRepeatsFromArray = function(array, object) {
                if (!array) {
                    return;
                }
                for (var index = array.length - 2; index >= 0; index--) {
                    var thisOneMatches = array[index] === object;
                    var nextOneMatches = array[index + 1] === object;
                    if (thisOneMatches && nextOneMatches) {
                        array.splice(index + 1, 1);
                    }
                }
            };
            Utils.removeFromArray = function(array, object) {
                if (array.indexOf(object) >= 0) {
                    array.splice(array.indexOf(object), 1);
                }
            };
            Utils.removeAllFromArray = function(array, toRemove) {
                toRemove.forEach(function(item) {
                    if (array.indexOf(item) >= 0) {
                        array.splice(array.indexOf(item), 1);
                    }
                });
            };
            Utils.insertIntoArray = function(array, object, toIndex) {
                array.splice(toIndex, 0, object);
            };
            Utils.insertArrayIntoArray = function(dest, src, toIndex) {
                if (this.missing(dest) || this.missing(src)) {
                    return;
                }
                for (var i = src.length - 1; i >= 0; i--) {
                    var item = src[i];
                    this.insertIntoArray(dest, item, toIndex);
                }
            };
            Utils.moveInArray = function(array, objectsToMove, toIndex) {
                var _this = this;
                objectsToMove.forEach(function(obj) {
                    _this.removeFromArray(array, obj);
                });
                objectsToMove.slice().reverse().forEach(function(obj) {
                    _this.insertIntoArray(array, obj, toIndex);
                });
            };
            Utils.defaultComparator = function(valueA, valueB, accentedCompare) {
                if (accentedCompare === void 0) {
                    accentedCompare = false;
                }
                var valueAMissing = valueA === null || valueA === undefined;
                var valueBMissing = valueB === null || valueB === undefined;
                if (valueA && valueA.toNumber) {
                    valueA = valueA.toNumber();
                }
                if (valueB && valueB.toNumber) {
                    valueB = valueB.toNumber();
                }
                if (valueAMissing && valueBMissing) {
                    return 0;
                }
                if (valueAMissing) {
                    return -1;
                }
                if (valueBMissing) {
                    return 1;
                }
                if (typeof valueA === "string") {
                    if (!accentedCompare) {
                        return doQuickCompare(valueA, valueB);
                    } else {
                        try {
                            return valueA.localeCompare(valueB);
                        } catch (e) {
                            return doQuickCompare(valueA, valueB);
                        }
                    }
                }
                if (valueA < valueB) {
                    return -1;
                } else if (valueA > valueB) {
                    return 1;
                } else {
                    return 0;
                }
                function doQuickCompare(a, b) {
                    return a > b ? 1 : a < b ? -1 : 0;
                }
            };
            Utils.compareArrays = function(array1, array2) {
                if (this.missing(array1) && this.missing(array2)) {
                    return true;
                }
                if (this.missing(array1) || this.missing(array2)) {
                    return false;
                }
                if (array1.length !== array2.length) {
                    return false;
                }
                for (var i = 0; i < array1.length; i++) {
                    if (array1[i] !== array2[i]) {
                        return false;
                    }
                }
                return true;
            };
            Utils.ensureDomOrder = function(eContainer, eChild, eChildBefore) {
                if (eChildBefore && eChildBefore.nextSibling === eChild) {
                    return;
                }
                if (eChildBefore) {
                    if (eChildBefore.nextSibling) {
                        eContainer.insertBefore(eChild, eChildBefore.nextSibling);
                    } else {
                        eContainer.appendChild(eChild);
                    }
                } else {
                    if (eContainer.firstChild) {
                        eContainer.insertBefore(eChild, eContainer.firstChild);
                    }
                }
            };
            Utils.insertWithDomOrder = function(eContainer, eChild, eChildBefore) {
                if (eChildBefore) {
                    if (eChildBefore.nextSibling) {
                        eContainer.insertBefore(eChild, eChildBefore.nextSibling);
                    } else {
                        eContainer.appendChild(eChild);
                    }
                } else {
                    if (eContainer.firstChild) {
                        eContainer.insertBefore(eChild, eContainer.firstChild);
                    } else {
                        eContainer.appendChild(eChild);
                    }
                }
            };
            Utils.insertTemplateWithDomOrder = function(eContainer, htmlTemplate, eChildBefore) {
                var res;
                if (eChildBefore) {
                    eChildBefore.insertAdjacentHTML("afterend", htmlTemplate);
                    res = eChildBefore.nextSibling;
                } else {
                    if (eContainer.firstChild) {
                        eContainer.insertAdjacentHTML("afterbegin", htmlTemplate);
                    } else {
                        eContainer.innerHTML = htmlTemplate;
                    }
                    res = eContainer.firstChild;
                }
                return res;
            };
            Utils.every = function(items, callback) {
                if (!items || items.length === 0) {
                    return true;
                }
                for (var i = 0; i < items.length; i++) {
                    if (!callback(items[i])) {
                        return false;
                    }
                }
                return true;
            };
            Utils.toStringOrNull = function(value) {
                if (this.exists(value) && value.toString) {
                    return value.toString();
                } else {
                    return null;
                }
            };
            Utils.formatWidth = function(width) {
                if (typeof width === "number") {
                    return width + "px";
                } else {
                    return width;
                }
            };
            Utils.formatNumberTwoDecimalPlacesAndCommas = function(value) {
                if (typeof value !== "number") {
                    return "";
                }
                return (Math.round(value * 100) / 100).toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,");
            };
            Utils.formatNumberCommas = function(value) {
                if (typeof value !== "number") {
                    return "";
                }
                return value.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,");
            };
            Utils.prependDC = function(parent, documentFragment) {
                if (this.exists(parent.firstChild)) {
                    parent.insertBefore(documentFragment, parent.firstChild);
                } else {
                    parent.appendChild(documentFragment);
                }
            };
            Utils.createIcon = function(iconName, gridOptionsWrapper, column) {
                var iconContents = this.createIconNoSpan(iconName, gridOptionsWrapper, column);
                if (iconContents.className.indexOf("ag-icon") > -1) {
                    return iconContents;
                } else {
                    var eResult = document.createElement("span");
                    eResult.appendChild(iconContents);
                    return eResult;
                }
            };
            Utils.createIconNoSpan = function(iconName, gridOptionsWrapper, column) {
                var userProvidedIcon;
                if (column && column.getColDef().icons) {
                    userProvidedIcon = column.getColDef().icons[iconName];
                }
                if (!userProvidedIcon && gridOptionsWrapper.getIcons()) {
                    userProvidedIcon = gridOptionsWrapper.getIcons()[iconName];
                }
                if (userProvidedIcon) {
                    var rendererResult = void 0;
                    if (typeof userProvidedIcon === "function") {
                        rendererResult = userProvidedIcon();
                    } else if (typeof userProvidedIcon === "string") {
                        rendererResult = userProvidedIcon;
                    } else {
                        throw "icon from grid options needs to be a string or a function";
                    }
                    if (typeof rendererResult === "string") {
                        return this.loadTemplate(rendererResult);
                    } else if (this.isNodeOrElement(rendererResult)) {
                        return rendererResult;
                    } else {
                        throw "iconRenderer should return back a string or a dom object";
                    }
                } else {
                    var span = document.createElement("span");
                    var cssClass = this.iconNameClassMap[iconName];
                    if (!cssClass) {
                        throw new Error(iconName + " did not find class");
                    }
                    span.setAttribute("class", "ag-icon ag-icon-" + cssClass);
                    return span;
                }
            };
            Utils.addStylesToElement = function(eElement, styles) {
                var _this = this;
                if (!styles) {
                    return;
                }
                Object.keys(styles).forEach(function(key) {
                    var keyCamelCase = _this.hyphenToCamelCase(key);
                    eElement.style[keyCamelCase] = styles[key];
                });
            };
            Utils.isHorizontalScrollShowing = function(element) {
                return element.clientWidth < element.scrollWidth;
            };
            Utils.isVerticalScrollShowing = function(element) {
                return element.clientHeight < element.scrollHeight;
            };
            Utils.getMaxDivHeight = function() {
                if (!document.body) {
                    return -1;
                }
                var res = 1e6;
                var testUpTo = navigator.userAgent.toLowerCase().match(/firefox/) ? 6e6 : 1e9;
                var div = this.loadTemplate("<div/>");
                document.body.appendChild(div);
                while (true) {
                    var test = res * 2;
                    div.style.height = test + "px";
                    if (test > testUpTo || div.clientHeight !== test) {
                        break;
                    } else {
                        res = test;
                    }
                }
                document.body.removeChild(div);
                return res;
            };
            Utils.getScrollbarWidth = function() {
                var outer = document.createElement("div");
                outer.style.visibility = "hidden";
                outer.style.width = "100px";
                outer.style.msOverflowStyle = "scrollbar";
                document.body.appendChild(outer);
                var widthNoScroll = outer.offsetWidth;
                outer.style.overflow = "scroll";
                var inner = document.createElement("div");
                inner.style.width = "100%";
                outer.appendChild(inner);
                var widthWithScroll = inner.offsetWidth;
                outer.parentNode.removeChild(outer);
                return widthNoScroll - widthWithScroll;
            };
            Utils.isKeyPressed = function(event, keyToCheck) {
                var pressedKey = event.which || event.keyCode;
                return pressedKey === keyToCheck;
            };
            Utils.setVisible = function(element, visible) {
                this.addOrRemoveCssClass(element, "ag-hidden", !visible);
            };
            Utils.setHidden = function(element, hidden) {
                this.addOrRemoveCssClass(element, "ag-visibility-hidden", hidden);
            };
            Utils.isBrowserIE = function() {
                if (this.isIE === undefined) {
                    this.isIE = false || !!document.documentMode;
                }
                return this.isIE;
            };
            Utils.isBrowserEdge = function() {
                if (this.isEdge === undefined) {
                    this.isEdge = !this.isBrowserIE() && !!window.StyleMedia;
                }
                return this.isEdge;
            };
            Utils.isBrowserSafari = function() {
                if (this.isSafari === undefined) {
                    var anyWindow = window;
                    this.isSafari = Object.prototype.toString.call(anyWindow.HTMLElement).indexOf("Constructor") > 0 || function(p) {
                        return p.toString() === "[object SafariRemoteNotification]";
                    }(!anyWindow.safari || anyWindow.safari.pushNotification);
                }
                return this.isSafari;
            };
            Utils.isBrowserChrome = function() {
                if (this.isChrome === undefined) {
                    var anyWindow = window;
                    this.isChrome = !!anyWindow.chrome && !!anyWindow.chrome.webstore;
                }
                return this.isChrome;
            };
            Utils.isBrowserFirefox = function() {
                if (this.isFirefox === undefined) {
                    var anyWindow = window;
                    this.isFirefox = typeof anyWindow.InstallTrigger !== "undefined";
                }
                return this.isFirefox;
            };
            Utils.isUserAgentIPad = function() {
                if (this.isIPad === undefined) {
                    this.isIPad = navigator.userAgent.match(/iPad|iPhone/i) != null;
                }
                return this.isIPad;
            };
            Utils.getTarget = function(event) {
                var eventNoType = event;
                return eventNoType.target || eventNoType.srcElement;
            };
            Utils.isElementInEventPath = function(element, event) {
                if (!event || !element) {
                    return false;
                }
                var path = exports._.getEventPath(event);
                return path.indexOf(element) >= 0;
            };
            Utils.createEventPath = function(event) {
                var res = [];
                var pointer = exports._.getTarget(event);
                while (pointer) {
                    res.push(pointer);
                    pointer = pointer.parentElement;
                }
                return res;
            };
            Utils.addAgGridEventPath = function(event) {
                event.__agGridEventPath = this.getEventPath(event);
            };
            Utils.getEventPath = function(event) {
                var eventNoType = event;
                if (event.deepPath) {
                    return event.deepPath();
                } else if (eventNoType.path) {
                    return eventNoType.path;
                } else if (eventNoType.composedPath) {
                    return eventNoType.composedPath();
                } else if (eventNoType.__agGridEventPath) {
                    return eventNoType.__agGridEventPath;
                } else {
                    return this.createEventPath(event);
                }
            };
            Utils.forEachSnapshotFirst = function(list, callback) {
                if (list) {
                    var arrayCopy = list.slice(0);
                    arrayCopy.forEach(callback);
                }
            };
            Utils.getBodyWidth = function() {
                if (document.body) {
                    return document.body.clientWidth;
                }
                if (window.innerHeight) {
                    return window.innerWidth;
                }
                if (document.documentElement && document.documentElement.clientWidth) {
                    return document.documentElement.clientWidth;
                }
                return -1;
            };
            Utils.getBodyHeight = function() {
                if (document.body) {
                    return document.body.clientHeight;
                }
                if (window.innerHeight) {
                    return window.innerHeight;
                }
                if (document.documentElement && document.documentElement.clientHeight) {
                    return document.documentElement.clientHeight;
                }
                return -1;
            };
            Utils.setCheckboxState = function(eCheckbox, state) {
                if (typeof state === "boolean") {
                    eCheckbox.checked = state;
                    eCheckbox.indeterminate = false;
                } else {
                    eCheckbox.indeterminate = true;
                }
            };
            Utils.traverseNodesWithKey = function(nodes, callback) {
                var keyParts = [];
                recursiveSearchNodes(nodes);
                function recursiveSearchNodes(nodes) {
                    nodes.forEach(function(node) {
                        if (node.group || node.hasChildren()) {
                            keyParts.push(node.key);
                            var key = keyParts.join("|");
                            callback(node, key);
                            recursiveSearchNodes(node.childrenAfterGroup);
                            keyParts.pop();
                        }
                    });
                }
            };
            Utils.camelCaseToHyphen = function(str) {
                if (str === null || str === undefined) {
                    return null;
                }
                return str.replace(/([A-Z])/g, function(g) {
                    return "-" + g[0].toLowerCase();
                });
            };
            Utils.hyphenToCamelCase = function(str) {
                if (str === null || str === undefined) {
                    return null;
                }
                return str.replace(/-([a-z])/g, function(g) {
                    return g[1].toUpperCase();
                });
            };
            Utils.cssStyleObjectToMarkup = function(stylesToUse) {
                var _this = this;
                if (!stylesToUse) {
                    return "";
                }
                var resParts = [];
                this.iterateObject(stylesToUse, function(styleKey, styleValue) {
                    var styleKeyDashed = _this.camelCaseToHyphen(styleKey);
                    resParts.push(styleKeyDashed + ": " + styleValue + ";");
                });
                return resParts.join(" ");
            };
            Utils.isNumeric = function(value) {
                if (value === "") return false;
                return !isNaN(parseFloat(value)) && isFinite(value);
            };
            Utils.escape = function(toEscape) {
                if (toEscape === null || toEscape === undefined || !toEscape.replace) {
                    return toEscape;
                }
                return toEscape.replace(reUnescapedHtml, function(chr) {
                    return HTML_ESCAPES[chr];
                });
            };
            Utils.normalizeWheel = function(event) {
                var PIXEL_STEP = 10;
                var LINE_HEIGHT = 40;
                var PAGE_HEIGHT = 800;
                var sX = 0;
                var sY = 0;
                var pX = 0;
                var pY = 0;
                if ("detail" in event) {
                    sY = event.detail;
                }
                if ("wheelDelta" in event) {
                    sY = -event.wheelDelta / 120;
                }
                if ("wheelDeltaY" in event) {
                    sY = -event.wheelDeltaY / 120;
                }
                if ("wheelDeltaX" in event) {
                    sX = -event.wheelDeltaX / 120;
                }
                if ("axis" in event && event.axis === event.HORIZONTAL_AXIS) {
                    sX = sY;
                    sY = 0;
                }
                pX = sX * PIXEL_STEP;
                pY = sY * PIXEL_STEP;
                if ("deltaY" in event) {
                    pY = event.deltaY;
                }
                if ("deltaX" in event) {
                    pX = event.deltaX;
                }
                if ((pX || pY) && event.deltaMode) {
                    if (event.deltaMode == 1) {
                        pX *= LINE_HEIGHT;
                        pY *= LINE_HEIGHT;
                    } else {
                        pX *= PAGE_HEIGHT;
                        pY *= PAGE_HEIGHT;
                    }
                }
                if (pX && !sX) {
                    sX = pX < 1 ? -1 : 1;
                }
                if (pY && !sY) {
                    sY = pY < 1 ? -1 : 1;
                }
                return {
                    spinX: sX,
                    spinY: sY,
                    pixelX: pX,
                    pixelY: pY
                };
            };
            Utils.debounce = function(func, wait, immediate) {
                if (immediate === void 0) {
                    immediate = false;
                }
                var timeout;
                return function() {
                    var context = this, args = arguments;
                    var callNow = immediate && !timeout;
                    clearTimeout(timeout);
                    timeout = setTimeout(function() {
                        timeout = null;
                        if (!immediate) {
                            func.apply(context, args);
                        }
                    }, wait);
                    if (callNow) func.apply(context, args);
                };
            };
            Utils.stopPropagationForAgGrid = function(event) {
                event[AG_GRID_STOP_PROPAGATION] = true;
            };
            Utils.isStopPropagationForAgGrid = function(event) {
                return event[AG_GRID_STOP_PROPAGATION] === true;
            };
            Utils.executeInAWhile = function(funcs) {
                this.executeAfter(funcs, 400);
            };
            Utils.executeNextVMTurn = function(funcs) {
                this.executeAfter(funcs, 0);
            };
            Utils.executeAfter = function(funcs, millis) {
                if (funcs.length > 0) {
                    setTimeout(function() {
                        funcs.forEach(function(func) {
                            return func();
                        });
                    }, millis);
                }
            };
            Utils.referenceCompare = function(left, right) {
                if (left == null && right == null) return true;
                if (left == null && right) return false;
                if (left && right == null) return false;
                return left === right;
            };
            Utils.get = function(source, expression, defaultValue) {
                if (source == null) return defaultValue;
                if (expression.indexOf(".") > -1) {
                    var fields = expression.split(".");
                    var thisKey = fields[0];
                    var nextValue = source[thisKey];
                    if (nextValue != null) {
                        return Utils.get(nextValue, fields.slice(1, fields.length).join("."), defaultValue);
                    } else {
                        return defaultValue;
                    }
                } else {
                    var nextValue = source[expression];
                    return nextValue != null ? nextValue : defaultValue;
                }
            };
            Utils.addSafePassiveEventListener = function(eElement, event, listener) {
                eElement.addEventListener(event, listener, Utils.passiveEvents.indexOf(event) > -1 ? {
                    passive: true
                } : undefined);
            };
            Utils.camelCaseToHumanText = function(camelCase) {
                if (camelCase == null) return null;
                var rex = /([A-Z])([A-Z])([a-z])|([a-z])([A-Z])/g;
                var words = camelCase.replace(rex, "$1$4 $2$3$5").replace(".", " ").split(" ");
                return words.map(function(word) {
                    return word.substring(0, 1).toUpperCase() + (word.length > 1 ? word.substring(1, word.length) : "");
                }).join(" ");
            };
            Utils.message = function(msg) {
                var eMessage = document.createElement("div");
                eMessage.innerHTML = msg;
                var eBox = document.querySelector("#__ag__message");
                if (!eBox) {
                    var template = '<div id="__ag__message" style="display: inline-block; position: absolute; top: 0px; left: 0px; color: white; background-color: black; z-index: 20; padding: 2px; border: 1px solid darkred; height: 200px; overflow-y: auto;"></div>';
                    eBox = this.loadTemplate(template);
                    if (document.body) {
                        document.body.appendChild(eBox);
                    }
                }
                eBox.appendChild(eMessage);
            };
            Utils.sortRowNodesByOrder = function(rowNodes, rowNodeOrder) {
                if (!rowNodes) {
                    return;
                }
                rowNodes.sort(function(nodeA, nodeB) {
                    var positionA = rowNodeOrder[nodeA.id];
                    var positionB = rowNodeOrder[nodeB.id];
                    var aHasIndex = positionA !== undefined;
                    var bHasIndex = positionB !== undefined;
                    var bothNodesAreUserNodes = aHasIndex && bHasIndex;
                    var bothNodesAreFillerNodes = !aHasIndex && !bHasIndex;
                    if (bothNodesAreUserNodes) {
                        return positionA - positionB;
                    } else if (bothNodesAreFillerNodes) {
                        return nodeA.id > nodeB.id ? 1 : -1;
                    } else if (aHasIndex) {
                        return 1;
                    } else {
                        return -1;
                    }
                });
            };
            Utils.fuzzyCheckStrings = function(inputValues, validValues, allSuggestions) {
                var _this = this;
                var fuzzyMatches = {};
                var invalidInputs = inputValues.filter(function(inputValue) {
                    return !validValues.some(function(validValue) {
                        return validValue === inputValue;
                    });
                });
                if (invalidInputs.length > 0) {
                    invalidInputs.forEach(function(invalidInput) {
                        return fuzzyMatches[invalidInput] = _this.fuzzySuggestions(invalidInput, validValues, allSuggestions);
                    });
                }
                return fuzzyMatches;
            };
            Utils.fuzzySuggestions = function(inputValue, validValues, allSuggestions) {
                var thisSuggestions = allSuggestions.slice(0);
                thisSuggestions.sort(function(suggestedValueLeft, suggestedValueRight) {
                    var leftDifference = exports._.string_similarity(suggestedValueLeft.toLowerCase(), inputValue.toLowerCase());
                    var rightDifference = exports._.string_similarity(suggestedValueRight.toLowerCase(), inputValue.toLowerCase());
                    return leftDifference > rightDifference ? -1 : leftDifference === rightDifference ? 0 : 1;
                });
                return thisSuggestions;
            };
            Utils.get_bigrams = function(from) {
                var i, j, ref, s, v;
                s = from.toLowerCase();
                v = new Array(s.length - 1);
                for (i = j = 0, ref = v.length; j <= ref; i = j += 1) {
                    v[i] = s.slice(i, i + 2);
                }
                return v;
            };
            Utils.isNumpadDelWithNumlockOnForEdgeOrIe = function(event) {
                if (Utils.isBrowserEdge() || Utils.isBrowserIE()) {
                    return event.key === Utils.NUMPAD_DEL_NUMLOCK_ON_KEY && event.charCode === Utils.NUMPAD_DEL_NUMLOCK_ON_CHARCODE;
                }
                return false;
            };
            Utils.PRINTABLE_CHARACTERS = "qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM1234567890!\"£$%^&*()_+-=[];'#,./\\|<>?:@~{}";
            Utils.NUMPAD_DEL_NUMLOCK_ON_KEY = "Del";
            Utils.NUMPAD_DEL_NUMLOCK_ON_CHARCODE = 46;
            Utils.doOnceFlags = {};
            Utils.iconNameClassMap = {
                columnMovePin: "pin",
                columnMoveAdd: "plus",
                columnMoveHide: "eye-slash",
                columnMoveMove: "arrows",
                columnMoveLeft: "left",
                columnMoveRight: "right",
                columnMoveGroup: "group",
                columnMoveValue: "aggregation",
                columnMovePivot: "pivot",
                dropNotAllowed: "not-allowed",
                groupContracted: "expanded",
                groupExpanded: "contracted",
                checkboxChecked: "checkbox-checked",
                checkboxUnchecked: "checkbox-unchecked",
                checkboxIndeterminate: "checkbox-indeterminate",
                checkboxCheckedReadOnly: "checkbox-checked-readonly",
                checkboxUncheckedReadOnly: "checkbox-unchecked-readonly",
                checkboxIndeterminateReadOnly: "checkbox-indeterminate-readonly",
                groupLoading: "loading",
                menu: "menu",
                filter: "filter",
                columns: "columns",
                menuPin: "pin",
                menuValue: "aggregation",
                menuAddRowGroup: "group",
                menuRemoveRowGroup: "group",
                clipboardCopy: "copy",
                clipboardCut: "cut",
                clipboardPaste: "paste",
                pivotPanel: "pivot",
                rowGroupPanel: "group",
                valuePanel: "aggregation",
                columnGroupOpened: "expanded",
                columnGroupClosed: "contracted",
                columnSelectClosed: "tree-closed",
                columnSelectOpen: "tree-open",
                sortAscending: "asc",
                sortDescending: "desc",
                sortUnSort: "none"
            };
            Utils.passiveEvents = [ "touchstart", "touchend", "touchmove", "touchcancel" ];
            Utils.string_similarity = function(str1, str2) {
                var hit_count, j, k, len, len1, pairs1, pairs2, union, x, y;
                if (str1.length > 0 && str2.length > 0) {
                    pairs1 = Utils.get_bigrams(str1);
                    pairs2 = Utils.get_bigrams(str2);
                    union = pairs1.length + pairs2.length;
                    hit_count = 0;
                    for (j = 0, len = pairs1.length; j < len; j++) {
                        x = pairs1[j];
                        for (k = 0, len1 = pairs2.length; k < len1; k++) {
                            y = pairs2[k];
                            if (x === y) {
                                hit_count++;
                            }
                        }
                    }
                    if (hit_count > 0) {
                        return 2 * hit_count / union;
                    }
                }
                return 0;
            };
            return Utils;
        }();
        exports.Utils = Utils;
        var NumberSequence = function() {
            function NumberSequence(initValue, step) {
                if (initValue === void 0) {
                    initValue = 0;
                }
                if (step === void 0) {
                    step = 1;
                }
                this.nextValue = initValue;
                this.step = step;
            }
            NumberSequence.prototype.next = function() {
                var valToReturn = this.nextValue;
                this.nextValue += this.step;
                return valToReturn;
            };
            NumberSequence.prototype.peek = function() {
                return this.nextValue;
            };
            NumberSequence.prototype.skip = function(count) {
                this.nextValue += count;
            };
            return NumberSequence;
        }();
        exports.NumberSequence = NumberSequence;
        exports._ = Utils;
        var PromiseStatus;
        (function(PromiseStatus) {
            PromiseStatus[PromiseStatus["IN_PROGRESS"] = 0] = "IN_PROGRESS";
            PromiseStatus[PromiseStatus["RESOLVED"] = 1] = "RESOLVED";
        })(PromiseStatus = exports.PromiseStatus || (exports.PromiseStatus = {}));
        var Promise = function() {
            function Promise(callback) {
                this.status = PromiseStatus.IN_PROGRESS;
                this.resolution = null;
                this.listOfWaiters = [];
                callback(this.onDone.bind(this), this.onReject.bind(this));
            }
            Promise.all = function(toCombine) {
                return new Promise(function(resolve) {
                    var combinedValues = [];
                    var remainingToResolve = toCombine.length;
                    toCombine.forEach(function(source, index) {
                        source.then(function(sourceResolved) {
                            remainingToResolve--;
                            combinedValues[index] = sourceResolved;
                            if (remainingToResolve == 0) {
                                resolve(combinedValues);
                            }
                        });
                        combinedValues.push(null);
                    });
                });
            };
            Promise.resolve = function(value) {
                return new Promise(function(resolve) {
                    return resolve(value);
                });
            };
            Promise.external = function() {
                var capture;
                var promise = new Promise(function(resolve) {
                    capture = resolve;
                });
                return {
                    promise: promise,
                    resolve: function(value) {
                        capture(value);
                    }
                };
            };
            Promise.prototype.then = function(func) {
                if (this.status === PromiseStatus.IN_PROGRESS) {
                    this.listOfWaiters.push(func);
                } else {
                    func(this.resolution);
                }
            };
            Promise.prototype.firstOneOnly = function(func) {
                if (this.status === PromiseStatus.IN_PROGRESS) {
                    if (this.listOfWaiters.length === 0) {
                        this.listOfWaiters.push(func);
                    }
                } else {
                    func(this.resolution);
                }
            };
            Promise.prototype.map = function(adapter) {
                var _this = this;
                return new Promise(function(resolve) {
                    _this.then(function(unmapped) {
                        resolve(adapter(unmapped));
                    });
                });
            };
            Promise.prototype.resolveNow = function(ifNotResolvedValue, ifResolved) {
                if (this.status == PromiseStatus.IN_PROGRESS) return ifNotResolvedValue;
                return ifResolved(this.resolution);
            };
            Promise.prototype.onDone = function(value) {
                this.status = PromiseStatus.RESOLVED;
                this.resolution = value;
                this.listOfWaiters.forEach(function(waiter) {
                    return waiter(value);
                });
            };
            Promise.prototype.onReject = function(params) {
                console.warn("TBI");
            };
            return Promise;
        }();
        exports.Promise = Promise;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        var __param = this && this.__param || function(paramIndex, decorator) {
            return function(target, key) {
                decorator(target, key, paramIndex);
            };
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var eventService_1 = __webpack_require__(3);
        var constants_1 = __webpack_require__(9);
        var componentUtil_1 = __webpack_require__(62);
        var gridApi_1 = __webpack_require__(6);
        var context_1 = __webpack_require__(0);
        var columnApi_1 = __webpack_require__(7);
        var columnController_1 = __webpack_require__(4);
        var utils_1 = __webpack_require__(1);
        var environment_1 = __webpack_require__(41);
        var propertyKeys_1 = __webpack_require__(90);
        var colDefUtil_1 = __webpack_require__(106);
        var eventKeys_1 = __webpack_require__(25);
        var autoHeightCalculator_1 = __webpack_require__(79);
        var DEFAULT_ROW_HEIGHT = 25;
        var DEFAULT_DETAIL_ROW_HEIGHT = 300;
        var DEFAULT_VIEWPORT_ROW_MODEL_PAGE_SIZE = 5;
        var DEFAULT_VIEWPORT_ROW_MODEL_BUFFER_SIZE = 5;
        var legacyThemes = [ "ag-fresh", "ag-bootstrap", "ag-blue", "ag-dark", "ag-material" ];
        function isTrue(value) {
            return value === true || value === "true";
        }
        function zeroOrGreater(value, defaultValue) {
            if (value >= 0) {
                return value;
            } else {
                return defaultValue;
            }
        }
        function oneOrGreater(value, defaultValue) {
            if (value > 0) {
                return value;
            } else {
                return defaultValue;
            }
        }
        var GridOptionsWrapper = function() {
            function GridOptionsWrapper() {
                this.propertyEventService = new eventService_1.EventService();
                this.domDataKey = "__AG_" + Math.random().toString();
            }
            GridOptionsWrapper_1 = GridOptionsWrapper;
            GridOptionsWrapper.prototype.agWire = function(gridApi, columnApi) {
                this.gridOptions.api = gridApi;
                this.gridOptions.columnApi = columnApi;
                this.checkForDeprecated();
            };
            GridOptionsWrapper.prototype.destroy = function() {
                this.gridOptions.api = null;
                this.gridOptions.columnApi = null;
            };
            GridOptionsWrapper.prototype.init = function() {
                if (!(this.gridOptions.suppressPropertyNamesCheck === true)) {
                    this.checkGridOptionsProperties();
                    this.checkColumnDefProperties();
                }
                var async = this.useAsyncEvents();
                this.eventService.addGlobalListener(this.globalEventHandler.bind(this), async);
                if (this.isGroupSelectsChildren() && this.isSuppressParentsInRowNodes()) {
                    console.warn("ag-Grid: groupSelectsChildren does not work wth suppressParentsInRowNodes, this selection method needs the part in rowNode to work");
                }
                if (this.isGroupSelectsChildren()) {
                    if (!this.isRowSelectionMulti()) {
                        console.warn("ag-Grid: rowSelection must be 'multiple' for groupSelectsChildren to make sense");
                    }
                    if (this.isRowModelServerSide()) {
                        console.warn("ag-Grid: group selects children is NOT support for Server Side Row Model. " + "This is because the rows are lazy loaded, so selecting a group is not possible as" + "the grid has no way of knowing what the children are.");
                    }
                }
                if (this.isGroupRemoveSingleChildren() && this.isGroupHideOpenParents()) {
                    console.warn("ag-Grid: groupRemoveSingleChildren and groupHideOpenParents do not work with each other, you need to pick one. And don't ask us how to us these together on our support forum either you will get the same answer!");
                }
            };
            GridOptionsWrapper.prototype.checkColumnDefProperties = function() {
                var _this = this;
                if (this.gridOptions.columnDefs == null) return;
                this.gridOptions.columnDefs.forEach(function(colDef) {
                    var userProperties = Object.getOwnPropertyNames(colDef);
                    var validProperties = colDefUtil_1.ColDefUtil.ALL_PROPERTIES;
                    _this.checkProperties(userProperties, validProperties, validProperties, "colDef", "https://www.ag-grid.com/javascript-grid-column-properties/");
                });
            };
            GridOptionsWrapper.prototype.checkGridOptionsProperties = function() {
                var userProperties = Object.getOwnPropertyNames(this.gridOptions);
                var validProperties = propertyKeys_1.PropertyKeys.ALL_PROPERTIES;
                Object.keys(eventKeys_1.Events).forEach(function(it) {
                    return validProperties.push(componentUtil_1.ComponentUtil.getCallbackForEvent(eventKeys_1.Events[it]));
                });
                var validPropertiesAndExceptions = validProperties.concat("api", "columnApi");
                this.checkProperties(userProperties, validPropertiesAndExceptions, validProperties, "gridOptions", "https://www.ag-grid.com/javascript-grid-properties/");
            };
            GridOptionsWrapper.prototype.checkProperties = function(userProperties, validPropertiesAndExceptions, validProperties, containerName, docsUrl) {
                var invalidProperties = utils_1.Utils.fuzzyCheckStrings(userProperties, validPropertiesAndExceptions, validProperties);
                var invalidPropertyKeys = Object.keys(invalidProperties);
                invalidPropertyKeys.forEach(function(invalidPropertyKey) {
                    var fuzzySuggestions = invalidProperties[invalidPropertyKey];
                    console.warn("ag-grid: invalid " + containerName + " property '" + invalidPropertyKey + "' did you mean any of these: " + fuzzySuggestions.slice(0, 8).join(","));
                });
                if (invalidPropertyKeys.length > 0) {
                    console.warn("ag-grid: to see all the valid " + containerName + " properties please check: " + docsUrl);
                }
            };
            GridOptionsWrapper.prototype.getDomData = function(element, key) {
                var domData = element[this.domDataKey];
                if (domData) {
                    return domData[key];
                } else {
                    return undefined;
                }
            };
            GridOptionsWrapper.prototype.setDomData = function(element, key, value) {
                var domData = element[this.domDataKey];
                if (utils_1.Utils.missing(domData)) {
                    domData = {};
                    element[this.domDataKey] = domData;
                }
                domData[key] = value;
            };
            GridOptionsWrapper.prototype.isEnterprise = function() {
                return this.enterprise;
            };
            GridOptionsWrapper.prototype.isRowSelection = function() {
                return this.gridOptions.rowSelection === "single" || this.gridOptions.rowSelection === "multiple";
            };
            GridOptionsWrapper.prototype.isRowDeselection = function() {
                return isTrue(this.gridOptions.rowDeselection);
            };
            GridOptionsWrapper.prototype.isRowSelectionMulti = function() {
                return this.gridOptions.rowSelection === "multiple";
            };
            GridOptionsWrapper.prototype.isRowMultiSelectWithClick = function() {
                return isTrue(this.gridOptions.rowMultiSelectWithClick);
            };
            GridOptionsWrapper.prototype.getContext = function() {
                return this.gridOptions.context;
            };
            GridOptionsWrapper.prototype.isPivotMode = function() {
                return isTrue(this.gridOptions.pivotMode);
            };
            GridOptionsWrapper.prototype.isPivotTotals = function() {
                return isTrue(this.gridOptions.pivotTotals);
            };
            GridOptionsWrapper.prototype.getPivotColumnGroupTotals = function() {
                return this.gridOptions.pivotColumnGroupTotals;
            };
            GridOptionsWrapper.prototype.getPivotRowTotals = function() {
                return this.gridOptions.pivotRowTotals;
            };
            GridOptionsWrapper.prototype.isRowModelInfinite = function() {
                return this.gridOptions.rowModelType === constants_1.Constants.ROW_MODEL_TYPE_INFINITE;
            };
            GridOptionsWrapper.prototype.isRowModelViewport = function() {
                return this.gridOptions.rowModelType === constants_1.Constants.ROW_MODEL_TYPE_VIEWPORT;
            };
            GridOptionsWrapper.prototype.isRowModelServerSide = function() {
                return this.gridOptions.rowModelType === constants_1.Constants.ROW_MODEL_TYPE_SERVER_SIDE;
            };
            GridOptionsWrapper.prototype.isRowModelDefault = function() {
                return utils_1.Utils.missing(this.gridOptions.rowModelType) || this.gridOptions.rowModelType === constants_1.Constants.ROW_MODEL_TYPE_CLIENT_SIDE || this.gridOptions.rowModelType === constants_1.Constants.DEPRECATED_ROW_MODEL_TYPE_NORMAL;
            };
            GridOptionsWrapper.prototype.isFullRowEdit = function() {
                return this.gridOptions.editType === "fullRow";
            };
            GridOptionsWrapper.prototype.isSuppressFocusAfterRefresh = function() {
                return isTrue(this.gridOptions.suppressFocusAfterRefresh);
            };
            GridOptionsWrapper.prototype.isShowToolPanel = function() {
                return isTrue(this.gridOptions.showToolPanel);
            };
            GridOptionsWrapper.prototype.isToolPanelSuppressValues = function() {
                return isTrue(this.gridOptions.toolPanelSuppressValues);
            };
            GridOptionsWrapper.prototype.isToolPanelSuppressPivots = function() {
                return isTrue(this.gridOptions.toolPanelSuppressPivots) || this.isTreeData();
            };
            GridOptionsWrapper.prototype.isToolPanelSuppressRowGroups = function() {
                return isTrue(this.gridOptions.toolPanelSuppressRowGroups) || this.isTreeData();
            };
            GridOptionsWrapper.prototype.isToolPanelSuppressSideButtons = function() {
                return isTrue(this.gridOptions.toolPanelSuppressSideButtons);
            };
            GridOptionsWrapper.prototype.isToolPanelSuppressPivotMode = function() {
                return isTrue(this.gridOptions.toolPanelSuppressPivotMode) || this.isTreeData();
            };
            GridOptionsWrapper.prototype.isContractColumnSelection = function() {
                return isTrue(this.gridOptions.contractColumnSelection);
            };
            GridOptionsWrapper.prototype.isToolPanelSuppressColumnFilter = function() {
                return isTrue(this.gridOptions.toolPanelSuppressColumnFilter);
            };
            GridOptionsWrapper.prototype.isToolPanelSuppressColumnSelectAll = function() {
                return isTrue(this.gridOptions.toolPanelSuppressColumnSelectAll);
            };
            GridOptionsWrapper.prototype.isToolPanelSuppressColumnExpandAll = function() {
                return isTrue(this.gridOptions.toolPanelSuppressColumnExpandAll);
            };
            GridOptionsWrapper.prototype.isSuppressTouch = function() {
                return isTrue(this.gridOptions.suppressTouch);
            };
            GridOptionsWrapper.prototype.isSuppressRowTransform = function() {
                return isTrue(this.gridOptions.suppressRowTransform);
            };
            GridOptionsWrapper.prototype.useAsyncEvents = function() {
                return !isTrue(this.gridOptions.suppressAsyncEvents);
            };
            GridOptionsWrapper.prototype.isEnableCellChangeFlash = function() {
                return isTrue(this.gridOptions.enableCellChangeFlash);
            };
            GridOptionsWrapper.prototype.isGroupSelectsChildren = function() {
                var result = isTrue(this.gridOptions.groupSelectsChildren);
                if (result && this.isTreeData()) {
                    console.warn("ag-Grid: groupSelectsChildren does not work with tree data");
                    return false;
                } else {
                    return result;
                }
            };
            GridOptionsWrapper.prototype.isSuppressRowHoverHighlight = function() {
                return isTrue(this.gridOptions.suppressRowHoverHighlight);
            };
            GridOptionsWrapper.prototype.isGroupSelectsFiltered = function() {
                return isTrue(this.gridOptions.groupSelectsFiltered);
            };
            GridOptionsWrapper.prototype.isGroupHideOpenParents = function() {
                return isTrue(this.gridOptions.groupHideOpenParents);
            };
            GridOptionsWrapper.prototype.isGroupMultiAutoColumn = function() {
                return isTrue(this.gridOptions.groupMultiAutoColumn) || isTrue(this.gridOptions.groupHideOpenParents);
            };
            GridOptionsWrapper.prototype.isGroupRemoveSingleChildren = function() {
                return isTrue(this.gridOptions.groupRemoveSingleChildren);
            };
            GridOptionsWrapper.prototype.isGroupRemoveLowestSingleChildren = function() {
                return isTrue(this.gridOptions.groupRemoveLowestSingleChildren);
            };
            GridOptionsWrapper.prototype.isGroupIncludeFooter = function() {
                return isTrue(this.gridOptions.groupIncludeFooter);
            };
            GridOptionsWrapper.prototype.isGroupIncludeTotalFooter = function() {
                return isTrue(this.gridOptions.groupIncludeTotalFooter);
            };
            GridOptionsWrapper.prototype.isGroupSuppressBlankHeader = function() {
                return isTrue(this.gridOptions.groupSuppressBlankHeader);
            };
            GridOptionsWrapper.prototype.isSuppressRowClickSelection = function() {
                return isTrue(this.gridOptions.suppressRowClickSelection);
            };
            GridOptionsWrapper.prototype.isSuppressCellSelection = function() {
                return isTrue(this.gridOptions.suppressCellSelection);
            };
            GridOptionsWrapper.prototype.isSuppressMultiSort = function() {
                return isTrue(this.gridOptions.suppressMultiSort);
            };
            GridOptionsWrapper.prototype.isMultiSortKeyCtrl = function() {
                return this.gridOptions.multiSortKey === "ctrl";
            };
            GridOptionsWrapper.prototype.isGroupSuppressAutoColumn = function() {
                return isTrue(this.gridOptions.groupSuppressAutoColumn);
            };
            GridOptionsWrapper.prototype.isSuppressDragLeaveHidesColumns = function() {
                return isTrue(this.gridOptions.suppressDragLeaveHidesColumns);
            };
            GridOptionsWrapper.prototype.isSuppressScrollOnNewData = function() {
                return isTrue(this.gridOptions.suppressScrollOnNewData);
            };
            GridOptionsWrapper.prototype.isRowDragManaged = function() {
                return isTrue(this.gridOptions.rowDragManaged);
            };
            GridOptionsWrapper.prototype.isSuppressRowDrag = function() {
                return isTrue(this.gridOptions.suppressRowDrag);
            };
            GridOptionsWrapper.prototype.isGridAutoHeight = function() {
                return isTrue(this.gridOptions.gridAutoHeight);
            };
            GridOptionsWrapper.prototype.isSuppressHorizontalScroll = function() {
                return isTrue(this.gridOptions.suppressHorizontalScroll);
            };
            GridOptionsWrapper.prototype.isSuppressLoadingOverlay = function() {
                return isTrue(this.gridOptions.suppressLoadingOverlay);
            };
            GridOptionsWrapper.prototype.isSuppressNoRowsOverlay = function() {
                return isTrue(this.gridOptions.suppressNoRowsOverlay);
            };
            GridOptionsWrapper.prototype.isSuppressFieldDotNotation = function() {
                return isTrue(this.gridOptions.suppressFieldDotNotation);
            };
            GridOptionsWrapper.prototype.getPinnedTopRowData = function() {
                return this.gridOptions.pinnedTopRowData;
            };
            GridOptionsWrapper.prototype.getPinnedBottomRowData = function() {
                return this.gridOptions.pinnedBottomRowData;
            };
            GridOptionsWrapper.prototype.isFunctionsPassive = function() {
                return isTrue(this.gridOptions.functionsPassive);
            };
            GridOptionsWrapper.prototype.isSuppressTabbing = function() {
                return isTrue(this.gridOptions.suppressTabbing);
            };
            GridOptionsWrapper.prototype.isSuppressChangeDetection = function() {
                return isTrue(this.gridOptions.suppressChangeDetection);
            };
            GridOptionsWrapper.prototype.isSuppressAnimationFrame = function() {
                return isTrue(this.gridOptions.suppressAnimationFrame);
            };
            GridOptionsWrapper.prototype.getQuickFilterText = function() {
                return this.gridOptions.quickFilterText;
            };
            GridOptionsWrapper.prototype.isCacheQuickFilter = function() {
                return isTrue(this.gridOptions.cacheQuickFilter);
            };
            GridOptionsWrapper.prototype.isUnSortIcon = function() {
                return isTrue(this.gridOptions.unSortIcon);
            };
            GridOptionsWrapper.prototype.isSuppressMenuHide = function() {
                return isTrue(this.gridOptions.suppressMenuHide);
            };
            GridOptionsWrapper.prototype.isEnterMovesDownAfterEdit = function() {
                return isTrue(this.gridOptions.enterMovesDownAfterEdit);
            };
            GridOptionsWrapper.prototype.isEnterMovesDown = function() {
                return isTrue(this.gridOptions.enterMovesDown);
            };
            GridOptionsWrapper.prototype.getRowStyle = function() {
                return this.gridOptions.rowStyle;
            };
            GridOptionsWrapper.prototype.getRowClass = function() {
                return this.gridOptions.rowClass;
            };
            GridOptionsWrapper.prototype.getRowStyleFunc = function() {
                return this.gridOptions.getRowStyle;
            };
            GridOptionsWrapper.prototype.getRowClassFunc = function() {
                return this.gridOptions.getRowClass;
            };
            GridOptionsWrapper.prototype.rowClassRules = function() {
                return this.gridOptions.rowClassRules;
            };
            GridOptionsWrapper.prototype.getPopupParent = function() {
                return this.gridOptions.popupParent;
            };
            GridOptionsWrapper.prototype.getPostProcessPopupFunc = function() {
                return this.gridOptions.postProcessPopup;
            };
            GridOptionsWrapper.prototype.getDoesDataFlowerFunc = function() {
                return this.gridOptions.doesDataFlower;
            };
            GridOptionsWrapper.prototype.getPaginationNumberFormatterFunc = function() {
                return this.gridOptions.paginationNumberFormatter;
            };
            GridOptionsWrapper.prototype.getChildCountFunc = function() {
                return this.gridOptions.getChildCount;
            };
            GridOptionsWrapper.prototype.getDefaultGroupSortComparator = function() {
                return this.gridOptions.defaultGroupSortComparator;
            };
            GridOptionsWrapper.prototype.getIsFullWidthCellFunc = function() {
                return this.gridOptions.isFullWidthCell;
            };
            GridOptionsWrapper.prototype.getFullWidthCellRendererParams = function() {
                return this.gridOptions.fullWidthCellRendererParams;
            };
            GridOptionsWrapper.prototype.isEmbedFullWidthRows = function() {
                return isTrue(this.gridOptions.embedFullWidthRows);
            };
            GridOptionsWrapper.prototype.getBusinessKeyForNodeFunc = function() {
                return this.gridOptions.getBusinessKeyForNode;
            };
            GridOptionsWrapper.prototype.getApi = function() {
                return this.gridOptions.api;
            };
            GridOptionsWrapper.prototype.getColumnApi = function() {
                return this.gridOptions.columnApi;
            };
            GridOptionsWrapper.prototype.isDeltaRowDataMode = function() {
                return isTrue(this.gridOptions.deltaRowDataMode);
            };
            GridOptionsWrapper.prototype.isEnsureDomOrder = function() {
                return isTrue(this.gridOptions.ensureDomOrder);
            };
            GridOptionsWrapper.prototype.isEnableColResize = function() {
                return isTrue(this.gridOptions.enableColResize);
            };
            GridOptionsWrapper.prototype.isSingleClickEdit = function() {
                return isTrue(this.gridOptions.singleClickEdit);
            };
            GridOptionsWrapper.prototype.isSuppressClickEdit = function() {
                return isTrue(this.gridOptions.suppressClickEdit);
            };
            GridOptionsWrapper.prototype.isStopEditingWhenGridLosesFocus = function() {
                return isTrue(this.gridOptions.stopEditingWhenGridLosesFocus);
            };
            GridOptionsWrapper.prototype.getGroupDefaultExpanded = function() {
                return this.gridOptions.groupDefaultExpanded;
            };
            GridOptionsWrapper.prototype.getMaxConcurrentDatasourceRequests = function() {
                return this.gridOptions.maxConcurrentDatasourceRequests;
            };
            GridOptionsWrapper.prototype.getMaxBlocksInCache = function() {
                return this.gridOptions.maxBlocksInCache;
            };
            GridOptionsWrapper.prototype.getCacheOverflowSize = function() {
                return this.gridOptions.cacheOverflowSize;
            };
            GridOptionsWrapper.prototype.getPaginationPageSize = function() {
                return this.gridOptions.paginationPageSize;
            };
            GridOptionsWrapper.prototype.getCacheBlockSize = function() {
                return this.gridOptions.cacheBlockSize;
            };
            GridOptionsWrapper.prototype.getInfiniteInitialRowCount = function() {
                return this.gridOptions.infiniteInitialRowCount;
            };
            GridOptionsWrapper.prototype.isPurgeClosedRowNodes = function() {
                return isTrue(this.gridOptions.purgeClosedRowNodes);
            };
            GridOptionsWrapper.prototype.isSuppressPaginationPanel = function() {
                return isTrue(this.gridOptions.suppressPaginationPanel);
            };
            GridOptionsWrapper.prototype.getRowData = function() {
                return this.gridOptions.rowData;
            };
            GridOptionsWrapper.prototype.isGroupUseEntireRow = function() {
                return isTrue(this.gridOptions.groupUseEntireRow);
            };
            GridOptionsWrapper.prototype.isEnableRtl = function() {
                return isTrue(this.gridOptions.enableRtl);
            };
            GridOptionsWrapper.prototype.getAutoGroupColumnDef = function() {
                return this.gridOptions.autoGroupColumnDef;
            };
            GridOptionsWrapper.prototype.isGroupSuppressRow = function() {
                return isTrue(this.gridOptions.groupSuppressRow);
            };
            GridOptionsWrapper.prototype.getRowGroupPanelShow = function() {
                return this.gridOptions.rowGroupPanelShow;
            };
            GridOptionsWrapper.prototype.getPivotPanelShow = function() {
                return this.gridOptions.pivotPanelShow;
            };
            GridOptionsWrapper.prototype.isAngularCompileRows = function() {
                return isTrue(this.gridOptions.angularCompileRows);
            };
            GridOptionsWrapper.prototype.isAngularCompileFilters = function() {
                return isTrue(this.gridOptions.angularCompileFilters);
            };
            GridOptionsWrapper.prototype.isAngularCompileHeaders = function() {
                return isTrue(this.gridOptions.angularCompileHeaders);
            };
            GridOptionsWrapper.prototype.isDebug = function() {
                return isTrue(this.gridOptions.debug);
            };
            GridOptionsWrapper.prototype.getColumnDefs = function() {
                return this.gridOptions.columnDefs;
            };
            GridOptionsWrapper.prototype.getColumnTypes = function() {
                return this.gridOptions.columnTypes;
            };
            GridOptionsWrapper.prototype.getDatasource = function() {
                return this.gridOptions.datasource;
            };
            GridOptionsWrapper.prototype.getViewportDatasource = function() {
                return this.gridOptions.viewportDatasource;
            };
            GridOptionsWrapper.prototype.getServerSideDatasource = function() {
                return this.gridOptions.serverSideDatasource;
            };
            GridOptionsWrapper.prototype.isEnableSorting = function() {
                return isTrue(this.gridOptions.enableSorting) || isTrue(this.gridOptions.enableServerSideSorting);
            };
            GridOptionsWrapper.prototype.isAccentedSort = function() {
                return isTrue(this.gridOptions.accentedSort);
            };
            GridOptionsWrapper.prototype.isEnableCellExpressions = function() {
                return isTrue(this.gridOptions.enableCellExpressions);
            };
            GridOptionsWrapper.prototype.isEnableGroupEdit = function() {
                return isTrue(this.gridOptions.enableGroupEdit);
            };
            GridOptionsWrapper.prototype.isSuppressMiddleClickScrolls = function() {
                return isTrue(this.gridOptions.suppressMiddleClickScrolls);
            };
            GridOptionsWrapper.prototype.isSuppressPreventDefaultOnMouseWheel = function() {
                return isTrue(this.gridOptions.suppressPreventDefaultOnMouseWheel);
            };
            GridOptionsWrapper.prototype.isSuppressColumnVirtualisation = function() {
                return isTrue(this.gridOptions.suppressColumnVirtualisation);
            };
            GridOptionsWrapper.prototype.isSuppressContextMenu = function() {
                return isTrue(this.gridOptions.suppressContextMenu);
            };
            GridOptionsWrapper.prototype.isAllowContextMenuWithControlKey = function() {
                return isTrue(this.gridOptions.allowContextMenuWithControlKey);
            };
            GridOptionsWrapper.prototype.isSuppressCopyRowsToClipboard = function() {
                return isTrue(this.gridOptions.suppressCopyRowsToClipboard);
            };
            GridOptionsWrapper.prototype.isSuppressClipboardPaste = function() {
                return isTrue(this.gridOptions.suppressClipboardPaste);
            };
            GridOptionsWrapper.prototype.isEnableFilter = function() {
                return isTrue(this.gridOptions.enableFilter) || isTrue(this.gridOptions.enableServerSideFilter);
            };
            GridOptionsWrapper.prototype.isPagination = function() {
                return isTrue(this.gridOptions.pagination);
            };
            GridOptionsWrapper.prototype.isSuppressEnterpriseResetOnNewColumns = function() {
                return isTrue(this.gridOptions.suppressEnterpriseResetOnNewColumns);
            };
            GridOptionsWrapper.prototype.getProcessDataFromClipboardFunc = function() {
                return this.gridOptions.processDataFromClipboard;
            };
            GridOptionsWrapper.prototype.getBatchUpdateWaitMillis = function() {
                return utils_1.Utils.exists(this.gridOptions.batchUpdateWaitMillis) ? this.gridOptions.batchUpdateWaitMillis : constants_1.Constants.BATCH_WAIT_MILLIS;
            };
            GridOptionsWrapper.prototype.isEnableServerSideFilter = function() {
                return this.gridOptions.enableServerSideFilter;
            };
            GridOptionsWrapper.prototype.isEnableServerSideSorting = function() {
                return isTrue(this.gridOptions.enableServerSideSorting);
            };
            GridOptionsWrapper.prototype.isSuppressMovableColumns = function() {
                return isTrue(this.gridOptions.suppressMovableColumns);
            };
            GridOptionsWrapper.prototype.isAnimateRows = function() {
                if (this.isEnsureDomOrder()) {
                    return false;
                }
                return isTrue(this.gridOptions.animateRows);
            };
            GridOptionsWrapper.prototype.isSuppressColumnMoveAnimation = function() {
                return isTrue(this.gridOptions.suppressColumnMoveAnimation);
            };
            GridOptionsWrapper.prototype.isSuppressAggFuncInHeader = function() {
                return isTrue(this.gridOptions.suppressAggFuncInHeader);
            };
            GridOptionsWrapper.prototype.isSuppressAggAtRootLevel = function() {
                return isTrue(this.gridOptions.suppressAggAtRootLevel);
            };
            GridOptionsWrapper.prototype.isEnableRangeSelection = function() {
                return isTrue(this.gridOptions.enableRangeSelection);
            };
            GridOptionsWrapper.prototype.isSuppressMultiRangeSelection = function() {
                return isTrue(this.gridOptions.suppressMultiRangeSelection);
            };
            GridOptionsWrapper.prototype.isPaginationAutoPageSize = function() {
                return isTrue(this.gridOptions.paginationAutoPageSize);
            };
            GridOptionsWrapper.prototype.isRememberGroupStateWhenNewData = function() {
                return isTrue(this.gridOptions.rememberGroupStateWhenNewData);
            };
            GridOptionsWrapper.prototype.getIcons = function() {
                return this.gridOptions.icons;
            };
            GridOptionsWrapper.prototype.getAggFuncs = function() {
                return this.gridOptions.aggFuncs;
            };
            GridOptionsWrapper.prototype.getSortingOrder = function() {
                return this.gridOptions.sortingOrder;
            };
            GridOptionsWrapper.prototype.getAlignedGrids = function() {
                return this.gridOptions.alignedGrids;
            };
            GridOptionsWrapper.prototype.isMasterDetail = function() {
                var _this = this;
                var usingMasterDetail = isTrue(this.gridOptions.masterDetail);
                utils_1.Utils.doOnce(function() {
                    if (usingMasterDetail && !_this.enterprise) {
                        console.warn("ag-grid: Master Detail is an Enterprise feature of ag-Grid.");
                    }
                }, "MasterDetailEnterpriseCheck");
                return usingMasterDetail && this.enterprise;
            };
            GridOptionsWrapper.prototype.getIsRowMasterFunc = function() {
                return this.gridOptions.isRowMaster;
            };
            GridOptionsWrapper.prototype.getIsRowSelectableFunc = function() {
                return this.gridOptions.isRowSelectable;
            };
            GridOptionsWrapper.prototype.getGroupRowRendererParams = function() {
                return this.gridOptions.groupRowRendererParams;
            };
            GridOptionsWrapper.prototype.getOverlayLoadingTemplate = function() {
                return this.gridOptions.overlayLoadingTemplate;
            };
            GridOptionsWrapper.prototype.getOverlayNoRowsTemplate = function() {
                return this.gridOptions.overlayNoRowsTemplate;
            };
            GridOptionsWrapper.prototype.isSuppressAutoSize = function() {
                return isTrue(this.gridOptions.suppressAutoSize);
            };
            GridOptionsWrapper.prototype.isSuppressParentsInRowNodes = function() {
                return isTrue(this.gridOptions.suppressParentsInRowNodes);
            };
            GridOptionsWrapper.prototype.isEnableStatusBar = function() {
                return isTrue(this.gridOptions.enableStatusBar);
            };
            GridOptionsWrapper.prototype.isAlwaysShowStatusBar = function() {
                return isTrue(this.gridOptions.alwaysShowStatusBar);
            };
            GridOptionsWrapper.prototype.isFunctionsReadOnly = function() {
                return isTrue(this.gridOptions.functionsReadOnly);
            };
            GridOptionsWrapper.prototype.isFloatingFilter = function() {
                return this.gridOptions.floatingFilter;
            };
            GridOptionsWrapper.prototype.isEnableOldSetFilterModel = function() {
                return isTrue(this.gridOptions.enableOldSetFilterModel);
            };
            GridOptionsWrapper.prototype.getDefaultColDef = function() {
                return this.gridOptions.defaultColDef;
            };
            GridOptionsWrapper.prototype.getDefaultColGroupDef = function() {
                return this.gridOptions.defaultColGroupDef;
            };
            GridOptionsWrapper.prototype.getDefaultExportParams = function() {
                return this.gridOptions.defaultExportParams;
            };
            GridOptionsWrapper.prototype.isSuppressCsvExport = function() {
                return isTrue(this.gridOptions.suppressCsvExport);
            };
            GridOptionsWrapper.prototype.isSuppressExcelExport = function() {
                return isTrue(this.gridOptions.suppressExcelExport);
            };
            GridOptionsWrapper.prototype.isSuppressMakeColumnVisibleAfterUnGroup = function() {
                return isTrue(this.gridOptions.suppressMakeColumnVisibleAfterUnGroup);
            };
            GridOptionsWrapper.prototype.getNodeChildDetailsFunc = function() {
                return this.gridOptions.getNodeChildDetails;
            };
            GridOptionsWrapper.prototype.getDataPathFunc = function() {
                return this.gridOptions.getDataPath;
            };
            GridOptionsWrapper.prototype.getGroupRowAggNodesFunc = function() {
                return this.gridOptions.groupRowAggNodes;
            };
            GridOptionsWrapper.prototype.getContextMenuItemsFunc = function() {
                return this.gridOptions.getContextMenuItems;
            };
            GridOptionsWrapper.prototype.getMainMenuItemsFunc = function() {
                return this.gridOptions.getMainMenuItems;
            };
            GridOptionsWrapper.prototype.getRowNodeIdFunc = function() {
                return this.gridOptions.getRowNodeId;
            };
            GridOptionsWrapper.prototype.getNavigateToNextCellFunc = function() {
                return this.gridOptions.navigateToNextCell;
            };
            GridOptionsWrapper.prototype.getTabToNextCellFunc = function() {
                return this.gridOptions.tabToNextCell;
            };
            GridOptionsWrapper.prototype.isTreeData = function() {
                return isTrue(this.gridOptions.treeData);
            };
            GridOptionsWrapper.prototype.isValueCache = function() {
                return isTrue(this.gridOptions.valueCache);
            };
            GridOptionsWrapper.prototype.isValueCacheNeverExpires = function() {
                return isTrue(this.gridOptions.valueCacheNeverExpires);
            };
            GridOptionsWrapper.prototype.isAggregateOnlyChangedColumns = function() {
                return isTrue(this.gridOptions.aggregateOnlyChangedColumns);
            };
            GridOptionsWrapper.prototype.getProcessSecondaryColDefFunc = function() {
                return this.gridOptions.processSecondaryColDef;
            };
            GridOptionsWrapper.prototype.getProcessSecondaryColGroupDefFunc = function() {
                return this.gridOptions.processSecondaryColGroupDef;
            };
            GridOptionsWrapper.prototype.getSendToClipboardFunc = function() {
                return this.gridOptions.sendToClipboard;
            };
            GridOptionsWrapper.prototype.getProcessRowPostCreateFunc = function() {
                return this.gridOptions.processRowPostCreate;
            };
            GridOptionsWrapper.prototype.getProcessCellForClipboardFunc = function() {
                return this.gridOptions.processCellForClipboard;
            };
            GridOptionsWrapper.prototype.getProcessHeaderForClipboardFunc = function() {
                return this.gridOptions.processHeaderForClipboard;
            };
            GridOptionsWrapper.prototype.getProcessCellFromClipboardFunc = function() {
                return this.gridOptions.processCellFromClipboard;
            };
            GridOptionsWrapper.prototype.getViewportRowModelPageSize = function() {
                return oneOrGreater(this.gridOptions.viewportRowModelPageSize, DEFAULT_VIEWPORT_ROW_MODEL_PAGE_SIZE);
            };
            GridOptionsWrapper.prototype.getViewportRowModelBufferSize = function() {
                return zeroOrGreater(this.gridOptions.viewportRowModelBufferSize, DEFAULT_VIEWPORT_ROW_MODEL_BUFFER_SIZE);
            };
            GridOptionsWrapper.prototype.getPostSortFunc = function() {
                return this.gridOptions.postSort;
            };
            GridOptionsWrapper.prototype.getClipboardDeliminator = function() {
                return utils_1.Utils.exists(this.gridOptions.clipboardDeliminator) ? this.gridOptions.clipboardDeliminator : "\t";
            };
            GridOptionsWrapper.prototype.setProperty = function(key, value) {
                var gridOptionsNoType = this.gridOptions;
                var previousValue = gridOptionsNoType[key];
                if (previousValue !== value) {
                    gridOptionsNoType[key] = value;
                    var event_1 = {
                        type: key,
                        currentValue: value,
                        previousValue: previousValue
                    };
                    this.propertyEventService.dispatchEvent(event_1);
                }
            };
            GridOptionsWrapper.prototype.addEventListener = function(key, listener) {
                GridOptionsWrapper_1.checkEventDeprecation(key);
                this.propertyEventService.addEventListener(key, listener);
            };
            GridOptionsWrapper.checkEventDeprecation = function(eventName) {
                if (eventName === eventKeys_1.Events.DEPRECATED_EVENT_GRID_SIZE_CHANGED) {
                    console.warn("ag-Grid: Since ag-Grid v18 event " + eventKeys_1.Events.DEPRECATED_EVENT_GRID_SIZE_CHANGED + " no longer exists.");
                }
                if (eventName === "floatingRowDataChanged") {
                    console.warn("ag-Grid: floatingRowDataChanged is now called pinnedRowDataChanged");
                }
            };
            GridOptionsWrapper.prototype.removeEventListener = function(key, listener) {
                this.propertyEventService.removeEventListener(key, listener);
            };
            GridOptionsWrapper.prototype.getAutoSizePadding = function() {
                return this.gridOptions.autoSizePadding > 0 ? this.gridOptions.autoSizePadding : 20;
            };
            GridOptionsWrapper.prototype.getHeaderHeight = function() {
                if (typeof this.gridOptions.headerHeight === "number") {
                    return this.gridOptions.headerHeight;
                } else {
                    return this.specialForNewMaterial(25, "headerHeight");
                }
            };
            GridOptionsWrapper.prototype.getFloatingFiltersHeight = function() {
                if (typeof this.gridOptions.floatingFiltersHeight === "number") {
                    return this.gridOptions.floatingFiltersHeight;
                } else {
                    return this.specialForNewMaterial(25, "headerHeight");
                }
            };
            GridOptionsWrapper.prototype.getGroupHeaderHeight = function() {
                if (typeof this.gridOptions.groupHeaderHeight === "number") {
                    return this.gridOptions.groupHeaderHeight;
                } else {
                    return this.getHeaderHeight();
                }
            };
            GridOptionsWrapper.prototype.getPivotHeaderHeight = function() {
                if (typeof this.gridOptions.pivotHeaderHeight === "number") {
                    return this.gridOptions.pivotHeaderHeight;
                } else {
                    return this.getHeaderHeight();
                }
            };
            GridOptionsWrapper.prototype.getPivotGroupHeaderHeight = function() {
                if (typeof this.gridOptions.pivotGroupHeaderHeight === "number") {
                    return this.gridOptions.pivotGroupHeaderHeight;
                } else {
                    return this.getGroupHeaderHeight();
                }
            };
            GridOptionsWrapper.prototype.isExternalFilterPresent = function() {
                if (typeof this.gridOptions.isExternalFilterPresent === "function") {
                    return this.gridOptions.isExternalFilterPresent();
                } else {
                    return false;
                }
            };
            GridOptionsWrapper.prototype.doesExternalFilterPass = function(node) {
                if (typeof this.gridOptions.doesExternalFilterPass === "function") {
                    return this.gridOptions.doesExternalFilterPass(node);
                } else {
                    return false;
                }
            };
            GridOptionsWrapper.prototype.getDocument = function() {
                var result;
                if (utils_1.Utils.exists(this.gridOptions.getDocument)) {
                    result = this.gridOptions.getDocument();
                }
                if (utils_1.Utils.exists(result)) {
                    return result;
                } else {
                    return document;
                }
            };
            GridOptionsWrapper.prototype.getLayoutInterval = function() {
                if (typeof this.gridOptions.layoutInterval === "number") {
                    return this.gridOptions.layoutInterval;
                } else {
                    return constants_1.Constants.LAYOUT_INTERVAL;
                }
            };
            GridOptionsWrapper.prototype.getMinColWidth = function() {
                if (this.gridOptions.minColWidth > GridOptionsWrapper_1.MIN_COL_WIDTH) {
                    return this.gridOptions.minColWidth;
                } else {
                    return GridOptionsWrapper_1.MIN_COL_WIDTH;
                }
            };
            GridOptionsWrapper.prototype.getMaxColWidth = function() {
                if (this.gridOptions.maxColWidth > GridOptionsWrapper_1.MIN_COL_WIDTH) {
                    return this.gridOptions.maxColWidth;
                } else {
                    return null;
                }
            };
            GridOptionsWrapper.prototype.getColWidth = function() {
                if (typeof this.gridOptions.colWidth !== "number" || this.gridOptions.colWidth < GridOptionsWrapper_1.MIN_COL_WIDTH) {
                    return 200;
                } else {
                    return this.gridOptions.colWidth;
                }
            };
            GridOptionsWrapper.prototype.getRowBuffer = function() {
                if (typeof this.gridOptions.rowBuffer === "number") {
                    if (this.gridOptions.rowBuffer < 0) {
                        console.warn("ag-Grid: rowBuffer should not be negative");
                    }
                    return this.gridOptions.rowBuffer;
                } else {
                    return constants_1.Constants.ROW_BUFFER_SIZE;
                }
            };
            GridOptionsWrapper.prototype.getScrollbarWidth = function() {
                var scrollbarWidth = this.gridOptions.scrollbarWidth;
                if (typeof scrollbarWidth !== "number" || scrollbarWidth < 0) {
                    scrollbarWidth = utils_1.Utils.getScrollbarWidth();
                }
                return scrollbarWidth;
            };
            GridOptionsWrapper.prototype.checkForDeprecated = function() {
                var options = this.gridOptions;
                if (options.suppressUnSort) {
                    console.warn("ag-grid: as of v1.12.4 suppressUnSort is not used. Please use sortingOrder instead.");
                }
                if (options.suppressDescSort) {
                    console.warn("ag-grid: as of v1.12.4 suppressDescSort is not used. Please use sortingOrder instead.");
                }
                if (options.groupAggFields) {
                    console.warn("ag-grid: as of v3 groupAggFields is not used. Please add appropriate agg fields to your columns.");
                }
                if (options.groupHidePivotColumns) {
                    console.warn("ag-grid: as of v3 groupHidePivotColumns is not used as pivot columns are now called rowGroup columns. Please refer to the documentation");
                }
                if (options.groupKeys) {
                    console.warn("ag-grid: as of v3 groupKeys is not used. You need to set rowGroupIndex on the columns to group. Please refer to the documentation");
                }
                if (typeof options.groupDefaultExpanded === "boolean") {
                    console.warn("ag-grid: groupDefaultExpanded can no longer be boolean. for groupDefaultExpanded=true, use groupDefaultExpanded=9999 instead, to expand all the groups");
                }
                if (options.onRowDeselected || options.rowDeselected) {
                    console.warn("ag-grid: since version 3.4 event rowDeselected no longer exists, please check the docs");
                }
                if (options.rowsAlreadyGrouped) {
                    console.warn("ag-grid: since version 3.4 rowsAlreadyGrouped no longer exists, please use getNodeChildDetails() instead");
                }
                if (options.groupAggFunction) {
                    console.warn("ag-grid: since version 4.3.x groupAggFunction is now called groupRowAggNodes");
                }
                if (options.checkboxSelection) {
                    console.warn("ag-grid: since version 8.0.x checkboxSelection is not supported as a grid option. " + "If you want this on all columns, use defaultColDef instead and set it there");
                }
                if (options.paginationInitialRowCount) {
                    console.warn("ag-grid: since version 9.0.x paginationInitialRowCount is now called infiniteInitialRowCount");
                }
                if (options.infinitePageSize) {
                    console.warn("ag-grid: since version 9.0.x infinitePageSize is now called cacheBlockSize");
                }
                if (options.infiniteBlockSize) {
                    console.warn("ag-grid: since version 10.0.x infiniteBlockSize is now called cacheBlockSize");
                }
                if (options.maxPagesInCache) {
                    console.warn("ag-grid: since version 10.0.x maxPagesInCache is now called maxBlocksInCache");
                }
                if (options.paginationOverflowSize) {
                    console.warn("ag-grid: since version 10.0.x paginationOverflowSize is now called cacheOverflowSize");
                }
                if (options.forPrint) {
                    console.warn('ag-grid: since version 10.1.x, use property domLayout="forPrint" instead of forPrint=true');
                }
                if (options.suppressMenuFilterPanel) {
                    console.warn("ag-grid: since version 11.0.x, use property colDef.menuTabs=['generalMenuTab','columnsMenuTab'] instead of suppressMenuFilterPanel=true");
                }
                if (options.suppressMenuMainPanel) {
                    console.warn("ag-grid: since version 11.0.x, use property colDef.menuTabs=['filterMenuTab','columnsMenuTab'] instead of suppressMenuMainPanel=true");
                }
                if (options.suppressMenuColumnPanel) {
                    console.warn("ag-grid: since version 11.0.x, use property colDef.menuTabs=['generalMenuTab','filterMenuTab'] instead of suppressMenuColumnPanel=true");
                }
                if (options.suppressUseColIdForGroups) {
                    console.warn("ag-grid: since version 11.0.x, this is not in use anymore. You should be able to remove it from your definition");
                }
                if (options.groupColumnDef) {
                    console.warn("ag-grid: since version 11.0.x, groupColumnDef has been renamed, this property is now called autoGroupColumnDef. Please change your configuration accordingly");
                }
                if (options.slaveGrids) {
                    console.warn("ag-grid: since version 12.x, slaveGrids has been renamed, this property is now called alignedGrids. Please change your configuration accordingly");
                }
                if (options.floatingTopRowData) {
                    console.warn("ag-grid: since version 12.x, floatingTopRowData is now called pinnedTopRowData");
                }
                if (options.floatingBottomRowData) {
                    console.warn("ag-grid: since version 12.x, floatingBottomRowData is now called pinnedBottomRowData");
                }
                if (options.paginationStartPage) {
                    console.warn("ag-grid: since version 12.x, paginationStartPage is gone, please call api.paginationGoToPage(" + options.paginationStartPage + ") instead.");
                }
                if (options.getHeaderCellTemplate) {
                    console.warn("ag-grid: since version 15.x, getHeaderCellTemplate is gone, please check the header documentation on how to set header templates.");
                }
                if (options.headerCellTemplate) {
                    console.warn("ag-grid: since version 15.x, headerCellTemplate is gone, please check the header documentation on how to set header templates.");
                }
                if (options.headerCellRenderer) {
                    console.warn("ag-grid: since version 15.x, headerCellRenderer is gone, please check the header documentation on how to set header templates.");
                }
                if (options.angularCompileHeaders) {
                    console.warn("ag-grid: since version 15.x, angularCompileHeaders is gone, please see the getting started for Angular 1 docs to see how to do headers in Angular 1.x.");
                }
                if (options.domLayout === "forPrint") {
                    console.warn("ag-grid: since version 18.x, forPrint is no longer supported, as same can be achieved using autoHeight (and set the grid width accordingly). please use autoHeight instead.");
                }
                if (options.domLayout === "autoHeight") {
                    console.warn("ag-grid: since version 18.x, domLayout is gone, instead if doing auto-height, set gridAutoHeight=true.");
                    options.gridAutoHeight = true;
                }
                if (options.pivotTotals) {
                    console.warn("ag-grid: since version 18.x, pivotTotals has been removed, instead if using pivotTotals, set pivotColumnGroupTotals='before'|'after'.");
                    options.pivotColumnGroupTotals = "before";
                }
                if (options.rowModelType === "inMemory") {
                    console.warn("ag-grid: since version 18.x, The In Memory Row Model has been renamed to the Client Side Row Model, set rowModelType='clientSide' instead.");
                    options.rowModelType = "clientSide";
                }
                if (options.rowModelType === "enterprise") {
                    console.warn("ag-grid: since version 18.x, The Enterprise Row Model has been renamed to the Server Side Row Model, set rowModelType='serverSide' instead.");
                    options.rowModelType = "serverSide";
                }
            };
            GridOptionsWrapper.prototype.getLocaleTextFunc = function() {
                if (this.gridOptions.localeTextFunc) {
                    return this.gridOptions.localeTextFunc;
                }
                var that = this;
                return function(key, defaultValue) {
                    var localeText = that.gridOptions.localeText;
                    if (localeText && localeText[key]) {
                        return localeText[key];
                    } else {
                        return defaultValue;
                    }
                };
            };
            GridOptionsWrapper.prototype.globalEventHandler = function(eventName, event) {
                var callbackMethodName = componentUtil_1.ComponentUtil.getCallbackForEvent(eventName);
                if (typeof this.gridOptions[callbackMethodName] === "function") {
                    this.gridOptions[callbackMethodName](event);
                }
            };
            GridOptionsWrapper.prototype.getRowHeightAsNumber = function() {
                var rowHeight = this.gridOptions.rowHeight;
                if (utils_1.Utils.missing(rowHeight)) {
                    return this.getDefaultRowHeight();
                } else if (this.isNumeric(this.gridOptions.rowHeight)) {
                    return this.gridOptions.rowHeight;
                } else {
                    console.warn("ag-Grid row height must be a number if not using standard row model");
                    return this.getDefaultRowHeight();
                }
            };
            GridOptionsWrapper.prototype.getRowHeightForNode = function(rowNode) {
                if (typeof this.gridOptions.getRowHeight === "function") {
                    var params = {
                        node: rowNode,
                        data: rowNode.data,
                        api: this.gridOptions.api,
                        context: this.gridOptions.context
                    };
                    return this.gridOptions.getRowHeight(params);
                } else if (rowNode.detail && this.isMasterDetail()) {
                    if (this.isNumeric(this.gridOptions.detailRowHeight)) {
                        return this.gridOptions.detailRowHeight;
                    } else {
                        return DEFAULT_DETAIL_ROW_HEIGHT;
                    }
                } else {
                    var defaultHeight = this.isNumeric(this.gridOptions.rowHeight) ? this.gridOptions.rowHeight : this.getDefaultRowHeight();
                    if (this.columnController.isAutoRowHeightActive()) {
                        var autoHeight = this.autoHeightCalculator.getPreferredHeightForRow(rowNode);
                        if (autoHeight > defaultHeight) {
                            return autoHeight;
                        } else {
                            return defaultHeight;
                        }
                    } else {
                        return defaultHeight;
                    }
                }
            };
            GridOptionsWrapper.prototype.isDynamicRowHeight = function() {
                return typeof this.gridOptions.getRowHeight === "function";
            };
            GridOptionsWrapper.prototype.getVirtualItemHeight = function() {
                return this.specialForNewMaterial(20, "virtualItemHeight");
            };
            GridOptionsWrapper.prototype.isNumeric = function(value) {
                return !isNaN(value) && typeof value === "number";
            };
            GridOptionsWrapper.prototype.specialForNewMaterial = function(defaultValue, sassVariableName) {
                var theme = this.environment.getTheme();
                if (theme.indexOf("ag-theme") === 0) {
                    return this.environment.getSassVariable(theme, sassVariableName);
                } else {
                    return defaultValue;
                }
            };
            GridOptionsWrapper.prototype.getDefaultRowHeight = function() {
                return this.specialForNewMaterial(DEFAULT_ROW_HEIGHT, "rowHeight");
            };
            GridOptionsWrapper.MIN_COL_WIDTH = 10;
            GridOptionsWrapper.PROP_HEADER_HEIGHT = "headerHeight";
            GridOptionsWrapper.PROP_GROUP_REMOVE_SINGLE_CHILDREN = "groupRemoveSingleChildren";
            GridOptionsWrapper.PROP_GROUP_REMOVE_LOWEST_SINGLE_CHILDREN = "groupRemoveLowestSingleChildren";
            GridOptionsWrapper.PROP_PIVOT_HEADER_HEIGHT = "pivotHeaderHeight";
            GridOptionsWrapper.PROP_SUPPRESS_CLIPBOARD_PASTE = "suppressClipboardPaste";
            GridOptionsWrapper.PROP_GROUP_HEADER_HEIGHT = "groupHeaderHeight";
            GridOptionsWrapper.PROP_PIVOT_GROUP_HEADER_HEIGHT = "pivotGroupHeaderHeight";
            GridOptionsWrapper.PROP_FLOATING_FILTERS_HEIGHT = "floatingFiltersHeight";
            GridOptionsWrapper.PROP_SUPPRESS_ROW_DRAG = "suppressRowDrag";
            GridOptionsWrapper.PROP_POPUP_PARENT = "popupParent";
            GridOptionsWrapper.PROP_GRID_AUTO_HEIGHT = "gridAutoHeight";
            __decorate([ context_1.Autowired("gridOptions"), __metadata("design:type", Object) ], GridOptionsWrapper.prototype, "gridOptions", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], GridOptionsWrapper.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], GridOptionsWrapper.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("enterprise"), __metadata("design:type", Boolean) ], GridOptionsWrapper.prototype, "enterprise", void 0);
            __decorate([ context_1.Autowired("frameworkFactory"), __metadata("design:type", Object) ], GridOptionsWrapper.prototype, "frameworkFactory", void 0);
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], GridOptionsWrapper.prototype, "gridApi", void 0);
            __decorate([ context_1.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], GridOptionsWrapper.prototype, "columnApi", void 0);
            __decorate([ context_1.Autowired("environment"), __metadata("design:type", environment_1.Environment) ], GridOptionsWrapper.prototype, "environment", void 0);
            __decorate([ context_1.Autowired("autoHeightCalculator"), __metadata("design:type", autoHeightCalculator_1.AutoHeightCalculator) ], GridOptionsWrapper.prototype, "autoHeightCalculator", void 0);
            __decorate([ __param(0, context_1.Qualifier("gridApi")), __param(1, context_1.Qualifier("columnApi")), __metadata("design:type", Function), __metadata("design:paramtypes", [ gridApi_1.GridApi, columnApi_1.ColumnApi ]), __metadata("design:returntype", void 0) ], GridOptionsWrapper.prototype, "agWire", null);
            __decorate([ context_1.PreDestroy, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], GridOptionsWrapper.prototype, "destroy", null);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], GridOptionsWrapper.prototype, "init", null);
            GridOptionsWrapper = GridOptionsWrapper_1 = __decorate([ context_1.Bean("gridOptionsWrapper") ], GridOptionsWrapper);
            return GridOptionsWrapper;
            var GridOptionsWrapper_1;
        }();
        exports.GridOptionsWrapper = GridOptionsWrapper;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        var __param = this && this.__param || function(paramIndex, decorator) {
            return function(target, key) {
                decorator(target, key, paramIndex);
            };
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var logger_1 = __webpack_require__(12);
        var utils_1 = __webpack_require__(1);
        var context_1 = __webpack_require__(0);
        var context_2 = __webpack_require__(0);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var EventService = function() {
            function EventService() {
                this.allSyncListeners = {};
                this.allAsyncListeners = {};
                this.globalSyncListeners = [];
                this.globalAsyncListeners = [];
                this.asyncFunctionsQueue = [];
                this.scheduled = false;
            }
            EventService_1 = EventService;
            EventService.prototype.setBeans = function(loggerFactory, gridOptionsWrapper, globalEventListener) {
                if (globalEventListener === void 0) {
                    globalEventListener = null;
                }
                this.logger = loggerFactory.create("EventService");
                if (globalEventListener) {
                    var async = gridOptionsWrapper.useAsyncEvents();
                    this.addGlobalListener(globalEventListener, async);
                }
            };
            EventService.prototype.getListenerList = function(eventType, async) {
                var listenerMap = async ? this.allAsyncListeners : this.allSyncListeners;
                var listenerList = listenerMap[eventType];
                if (!listenerList) {
                    listenerList = [];
                    listenerMap[eventType] = listenerList;
                }
                return listenerList;
            };
            EventService.prototype.addEventListener = function(eventType, listener, async) {
                if (async === void 0) {
                    async = false;
                }
                var listenerList = this.getListenerList(eventType, async);
                if (listenerList.indexOf(listener) < 0) {
                    listenerList.push(listener);
                }
            };
            EventService.prototype.addModalPriorityEventListener = function(eventType, listener, async) {
                if (async === void 0) {
                    async = false;
                }
                this.addEventListener(eventType + EventService_1.PRIORITY, listener, async);
            };
            EventService.prototype.addGlobalListener = function(listener, async) {
                if (async === void 0) {
                    async = false;
                }
                if (async) {
                    this.globalAsyncListeners.push(listener);
                } else {
                    this.globalSyncListeners.push(listener);
                }
            };
            EventService.prototype.removeEventListener = function(eventType, listener, async) {
                if (async === void 0) {
                    async = false;
                }
                var listenerList = this.getListenerList(eventType, async);
                utils_1.Utils.removeFromArray(listenerList, listener);
            };
            EventService.prototype.removeGlobalListener = function(listener, async) {
                if (async === void 0) {
                    async = false;
                }
                if (async) {
                    utils_1.Utils.removeFromArray(this.globalAsyncListeners, listener);
                } else {
                    utils_1.Utils.removeFromArray(this.globalSyncListeners, listener);
                }
            };
            EventService.prototype.dispatchEvent = function(event) {
                this.dispatchToListeners(event, true);
                this.dispatchToListeners(event, false);
            };
            EventService.prototype.dispatchToListeners = function(event, async) {
                var _this = this;
                var globalListeners = async ? this.globalAsyncListeners : this.globalSyncListeners;
                var eventType = event.type;
                var p1ListenerList = this.getListenerList(eventType + EventService_1.PRIORITY, async);
                utils_1.Utils.forEachSnapshotFirst(p1ListenerList, function(listener) {
                    if (async) {
                        _this.dispatchAsync(function() {
                            return listener(event);
                        });
                    } else {
                        listener(event);
                    }
                });
                var listenerList = this.getListenerList(eventType, async);
                utils_1.Utils.forEachSnapshotFirst(listenerList, function(listener) {
                    if (async) {
                        _this.dispatchAsync(function() {
                            return listener(event);
                        });
                    } else {
                        listener(event);
                    }
                });
                utils_1.Utils.forEachSnapshotFirst(globalListeners, function(listener) {
                    if (async) {
                        _this.dispatchAsync(function() {
                            return listener(eventType, event);
                        });
                    } else {
                        listener(eventType, event);
                    }
                });
            };
            EventService.prototype.dispatchAsync = function(func) {
                this.asyncFunctionsQueue.push(func);
                if (!this.scheduled) {
                    setTimeout(this.flushAsyncQueue.bind(this), 0);
                    this.scheduled = true;
                }
            };
            EventService.prototype.flushAsyncQueue = function() {
                this.scheduled = false;
                var queueCopy = this.asyncFunctionsQueue.slice();
                this.asyncFunctionsQueue = [];
                queueCopy.forEach(function(func) {
                    return func();
                });
            };
            EventService.PRIORITY = "-P1";
            __decorate([ __param(0, context_2.Qualifier("loggerFactory")), __param(1, context_2.Qualifier("gridOptionsWrapper")), __param(2, context_2.Qualifier("globalEventListener")), __metadata("design:type", Function), __metadata("design:paramtypes", [ logger_1.LoggerFactory, gridOptionsWrapper_1.GridOptionsWrapper, Function ]), __metadata("design:returntype", void 0) ], EventService.prototype, "setBeans", null);
            EventService = EventService_1 = __decorate([ context_1.Bean("eventService") ], EventService);
            return EventService;
            var EventService_1;
        }();
        exports.EventService = EventService;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        var __param = this && this.__param || function(paramIndex, decorator) {
            return function(target, key) {
                decorator(target, key, paramIndex);
            };
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var columnGroup_1 = __webpack_require__(26);
        var column_1 = __webpack_require__(10);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var expressionService_1 = __webpack_require__(19);
        var balancedColumnTreeBuilder_1 = __webpack_require__(38);
        var displayedGroupCreator_1 = __webpack_require__(48);
        var autoWidthCalculator_1 = __webpack_require__(39);
        var eventService_1 = __webpack_require__(3);
        var columnUtils_1 = __webpack_require__(31);
        var logger_1 = __webpack_require__(12);
        var events_1 = __webpack_require__(5);
        var originalColumnGroup_1 = __webpack_require__(32);
        var groupInstanceIdCreator_1 = __webpack_require__(83);
        var context_1 = __webpack_require__(0);
        var columnAnimationService_1 = __webpack_require__(53);
        var autoGroupColService_1 = __webpack_require__(104);
        var valueCache_1 = __webpack_require__(33);
        var gridApi_1 = __webpack_require__(6);
        var columnApi_1 = __webpack_require__(7);
        var ColumnController = function() {
            function ColumnController() {
                this.primaryHeaderRowCount = 0;
                this.secondaryHeaderRowCount = 0;
                this.secondaryColumnsPresent = false;
                this.gridHeaderRowCount = 0;
                this.displayedLeftColumns = [];
                this.displayedRightColumns = [];
                this.displayedCenterColumns = [];
                this.allDisplayedColumns = [];
                this.allDisplayedVirtualColumns = [];
                this.allDisplayedCenterVirtualColumns = [];
                this.rowGroupColumns = [];
                this.valueColumns = [];
                this.pivotColumns = [];
                this.ready = false;
                this.autoGroupsNeedBuilding = false;
                this.pivotMode = false;
                this.bodyWidth = 0;
                this.leftWidth = 0;
                this.rightWidth = 0;
                this.bodyWidthDirty = true;
            }
            ColumnController.prototype.init = function() {
                var pivotMode = this.gridOptionsWrapper.isPivotMode();
                this.suppressColumnVirtualisation = this.gridOptionsWrapper.isSuppressColumnVirtualisation();
                if (this.isPivotSettingAllowed(pivotMode)) {
                    this.pivotMode = pivotMode;
                }
                this.usingTreeData = this.gridOptionsWrapper.isTreeData();
            };
            ColumnController.prototype.isAutoRowHeightActive = function() {
                return this.autoRowHeightColumns && this.autoRowHeightColumns.length > 0;
            };
            ColumnController.prototype.getAllAutoRowHeightCols = function() {
                return this.autoRowHeightColumns;
            };
            ColumnController.prototype.setVirtualViewportLeftAndRight = function() {
                if (this.gridOptionsWrapper.isEnableRtl()) {
                    this.viewportLeft = this.bodyWidth - this.scrollPosition - this.scrollWidth;
                    this.viewportRight = this.bodyWidth - this.scrollPosition;
                } else {
                    this.viewportLeft = this.scrollPosition;
                    this.viewportRight = this.scrollWidth + this.scrollPosition;
                }
            };
            ColumnController.prototype.getDisplayedColumnsStartingAt = function(column) {
                var currentColumn = column;
                var result = [];
                while (utils_1.Utils.exists(currentColumn)) {
                    result.push(currentColumn);
                    currentColumn = this.getDisplayedColAfter(currentColumn);
                }
                return result;
            };
            ColumnController.prototype.checkDisplayedVirtualColumns = function() {
                if (utils_1.Utils.exists(this.displayedCenterColumns)) {
                    var hashBefore = this.allDisplayedVirtualColumns.map(function(column) {
                        return column.getId();
                    }).join("#");
                    this.updateVirtualSets();
                    var hashAfter = this.allDisplayedVirtualColumns.map(function(column) {
                        return column.getId();
                    }).join("#");
                    if (hashBefore !== hashAfter) {
                        var event_1 = {
                            type: events_1.Events.EVENT_VIRTUAL_COLUMNS_CHANGED,
                            api: this.gridApi,
                            columnApi: this.columnApi
                        };
                        this.eventService.dispatchEvent(event_1);
                    }
                }
            };
            ColumnController.prototype.setVirtualViewportPosition = function(scrollWidth, scrollPosition) {
                if (scrollWidth !== this.scrollWidth || scrollPosition !== this.scrollPosition || this.bodyWidthDirty) {
                    this.scrollWidth = scrollWidth;
                    this.scrollPosition = scrollPosition;
                    this.bodyWidthDirty = true;
                    this.setVirtualViewportLeftAndRight();
                    if (this.ready) {
                        this.checkDisplayedVirtualColumns();
                    }
                }
            };
            ColumnController.prototype.isPivotMode = function() {
                return this.pivotMode;
            };
            ColumnController.prototype.isPivotSettingAllowed = function(pivot) {
                if (pivot) {
                    if (this.gridOptionsWrapper.isTreeData()) {
                        console.warn("ag-Grid: Pivot mode not available in conjunction Tree Data i.e. 'gridOptions.treeData: true'");
                        return false;
                    } else {
                        return true;
                    }
                } else {
                    return true;
                }
            };
            ColumnController.prototype.setPivotMode = function(pivotMode, source) {
                if (source === void 0) {
                    source = "api";
                }
                if (pivotMode === this.pivotMode) {
                    return;
                }
                if (!this.isPivotSettingAllowed(this.pivotMode)) {
                    return;
                }
                this.pivotMode = pivotMode;
                this.updateDisplayedColumns(source);
                var event = {
                    type: events_1.Events.EVENT_COLUMN_PIVOT_MODE_CHANGED,
                    api: this.gridApi,
                    columnApi: this.columnApi
                };
                this.eventService.dispatchEvent(event);
            };
            ColumnController.prototype.getSecondaryPivotColumn = function(pivotKeys, valueColKey) {
                if (!this.secondaryColumnsPresent) {
                    return null;
                }
                var valueColumnToFind = this.getPrimaryColumn(valueColKey);
                var foundColumn = null;
                this.secondaryColumns.forEach(function(column) {
                    var thisPivotKeys = column.getColDef().pivotKeys;
                    var pivotValueColumn = column.getColDef().pivotValueColumn;
                    var pivotKeyMatches = utils_1.Utils.compareArrays(thisPivotKeys, pivotKeys);
                    var pivotValueMatches = pivotValueColumn === valueColumnToFind;
                    if (pivotKeyMatches && pivotValueMatches) {
                        foundColumn = column;
                    }
                });
                return foundColumn;
            };
            ColumnController.prototype.setBeans = function(loggerFactory) {
                this.logger = loggerFactory.create("ColumnController");
            };
            ColumnController.prototype.setFirstRightAndLastLeftPinned = function(source) {
                var lastLeft;
                var firstRight;
                if (this.gridOptionsWrapper.isEnableRtl()) {
                    lastLeft = this.displayedLeftColumns ? this.displayedLeftColumns[0] : null;
                    firstRight = this.displayedRightColumns ? this.displayedRightColumns[this.displayedRightColumns.length - 1] : null;
                } else {
                    lastLeft = this.displayedLeftColumns ? this.displayedLeftColumns[this.displayedLeftColumns.length - 1] : null;
                    firstRight = this.displayedRightColumns ? this.displayedRightColumns[0] : null;
                }
                this.gridColumns.forEach(function(column) {
                    column.setLastLeftPinned(column === lastLeft, source);
                    column.setFirstRightPinned(column === firstRight, source);
                });
            };
            ColumnController.prototype.autoSizeColumns = function(keys, source) {
                var _this = this;
                if (source === void 0) {
                    source = "api";
                }
                var columnsAutosized = [];
                var changesThisTimeAround = -1;
                while (changesThisTimeAround !== 0) {
                    changesThisTimeAround = 0;
                    this.actionOnGridColumns(keys, function(column) {
                        if (columnsAutosized.indexOf(column) >= 0) {
                            return;
                        }
                        var preferredWidth = _this.autoWidthCalculator.getPreferredWidthForColumn(column);
                        if (preferredWidth > 0) {
                            var newWidth = _this.normaliseColumnWidth(column, preferredWidth);
                            column.setActualWidth(newWidth, source);
                            columnsAutosized.push(column);
                            changesThisTimeAround++;
                        }
                        return true;
                    }, source);
                }
                if (columnsAutosized.length > 0) {
                    var event_2 = {
                        type: events_1.Events.EVENT_COLUMN_RESIZED,
                        columns: columnsAutosized,
                        column: columnsAutosized.length === 1 ? columnsAutosized[0] : null,
                        finished: true,
                        api: this.gridApi,
                        columnApi: this.columnApi,
                        source: "autosizeColumns"
                    };
                    this.eventService.dispatchEvent(event_2);
                }
            };
            ColumnController.prototype.autoSizeColumn = function(key, source) {
                if (source === void 0) {
                    source = "api";
                }
                this.autoSizeColumns([ key ], source);
            };
            ColumnController.prototype.autoSizeAllColumns = function(source) {
                if (source === void 0) {
                    source = "api";
                }
                var allDisplayedColumns = this.getAllDisplayedColumns();
                this.autoSizeColumns(allDisplayedColumns, source);
            };
            ColumnController.prototype.getColumnsFromTree = function(rootColumns) {
                var result = [];
                recursiveFindColumns(rootColumns);
                return result;
                function recursiveFindColumns(childColumns) {
                    for (var i = 0; i < childColumns.length; i++) {
                        var child = childColumns[i];
                        if (child instanceof column_1.Column) {
                            result.push(child);
                        } else if (child instanceof originalColumnGroup_1.OriginalColumnGroup) {
                            recursiveFindColumns(child.getChildren());
                        }
                    }
                }
            };
            ColumnController.prototype.getAllDisplayedColumnGroups = function() {
                if (this.displayedLeftColumnTree && this.displayedRightColumnTree && this.displayedCentreColumnTree) {
                    return this.displayedLeftColumnTree.concat(this.displayedCentreColumnTree).concat(this.displayedRightColumnTree);
                } else {
                    return null;
                }
            };
            ColumnController.prototype.getPrimaryColumnTree = function() {
                return this.primaryBalancedTree;
            };
            ColumnController.prototype.getHeaderRowCount = function() {
                return this.gridHeaderRowCount;
            };
            ColumnController.prototype.getLeftDisplayedColumnGroups = function() {
                return this.displayedLeftColumnTree;
            };
            ColumnController.prototype.getRightDisplayedColumnGroups = function() {
                return this.displayedRightColumnTree;
            };
            ColumnController.prototype.getCenterDisplayedColumnGroups = function() {
                return this.displayedCentreColumnTree;
            };
            ColumnController.prototype.getDisplayedColumnGroups = function(type) {
                switch (type) {
                  case column_1.Column.PINNED_LEFT:
                    return this.getLeftDisplayedColumnGroups();

                  case column_1.Column.PINNED_RIGHT:
                    return this.getRightDisplayedColumnGroups();

                  default:
                    return this.getCenterDisplayedColumnGroups();
                }
            };
            ColumnController.prototype.isColumnDisplayed = function(column) {
                return this.getAllDisplayedColumns().indexOf(column) >= 0;
            };
            ColumnController.prototype.getAllDisplayedColumns = function() {
                return this.allDisplayedColumns;
            };
            ColumnController.prototype.getAllDisplayedVirtualColumns = function() {
                return this.allDisplayedVirtualColumns;
            };
            ColumnController.prototype.getDisplayedLeftColumnsForRow = function(rowNode) {
                if (!this.colSpanActive) {
                    return this.displayedLeftColumns;
                } else {
                    return this.getDisplayedColumnsForRow(rowNode, this.displayedLeftColumns);
                }
            };
            ColumnController.prototype.getDisplayedRightColumnsForRow = function(rowNode) {
                if (!this.colSpanActive) {
                    return this.displayedRightColumns;
                } else {
                    return this.getDisplayedColumnsForRow(rowNode, this.displayedRightColumns);
                }
            };
            ColumnController.prototype.getDisplayedColumnsForRow = function(rowNode, displayedColumns, filterCallback, emptySpaceBeforeColumn) {
                var result = [];
                var lastConsideredCol = null;
                var _loop_1 = function(i) {
                    var col = displayedColumns[i];
                    var colSpan = col.getColSpan(rowNode);
                    var columnsToCheckFilter = [ col ];
                    if (colSpan > 1) {
                        var colsToRemove = colSpan - 1;
                        for (var j = 1; j <= colsToRemove; j++) {
                            columnsToCheckFilter.push(displayedColumns[i + j]);
                        }
                        i += colsToRemove;
                    }
                    var filterPasses;
                    if (filterCallback) {
                        filterPasses = false;
                        columnsToCheckFilter.forEach(function(colForFilter) {
                            if (filterCallback(colForFilter)) filterPasses = true;
                        });
                    } else {
                        filterPasses = true;
                    }
                    if (filterPasses) {
                        if (result.length === 0 && lastConsideredCol) {
                            var gapBeforeColumn = emptySpaceBeforeColumn ? emptySpaceBeforeColumn(col) : false;
                            if (gapBeforeColumn) {
                                result.push(lastConsideredCol);
                            }
                        }
                        result.push(col);
                    }
                    lastConsideredCol = col;
                    out_i_1 = i;
                };
                var out_i_1;
                for (var i = 0; i < displayedColumns.length; i++) {
                    _loop_1(i);
                    i = out_i_1;
                }
                return result;
            };
            ColumnController.prototype.getAllDisplayedCenterVirtualColumnsForRow = function(rowNode) {
                var _this = this;
                if (!this.colSpanActive) {
                    return this.allDisplayedCenterVirtualColumns;
                }
                var emptySpaceBeforeColumn = function(col) {
                    return col.getLeft() > _this.viewportLeft;
                };
                var filterCallback = this.suppressColumnVirtualisation ? null : this.isColumnInViewport.bind(this);
                return this.getDisplayedColumnsForRow(rowNode, this.displayedCenterColumns, filterCallback, emptySpaceBeforeColumn);
            };
            ColumnController.prototype.isColumnInViewport = function(col) {
                var columnLeft = col.getLeft();
                var columnRight = col.getLeft() + col.getActualWidth();
                var columnToMuchLeft = columnLeft < this.viewportLeft && columnRight < this.viewportLeft;
                var columnToMuchRight = columnLeft > this.viewportRight && columnRight > this.viewportRight;
                return !columnToMuchLeft && !columnToMuchRight;
            };
            ColumnController.prototype.getPinnedLeftContainerWidth = function() {
                return this.getWidthOfColsInList(this.displayedLeftColumns);
            };
            ColumnController.prototype.getPinnedRightContainerWidth = function() {
                return this.getWidthOfColsInList(this.displayedRightColumns);
            };
            ColumnController.prototype.updatePrimaryColumnList = function(keys, masterList, actionIsAdd, columnCallback, eventType, source) {
                var _this = this;
                if (source === void 0) {
                    source = "api";
                }
                if (utils_1.Utils.missingOrEmpty(keys)) {
                    return;
                }
                var atLeastOne = false;
                keys.forEach(function(key) {
                    var columnToAdd = _this.getPrimaryColumn(key);
                    if (!columnToAdd) {
                        return;
                    }
                    if (actionIsAdd) {
                        if (masterList.indexOf(columnToAdd) >= 0) {
                            return;
                        }
                        masterList.push(columnToAdd);
                    } else {
                        if (masterList.indexOf(columnToAdd) < 0) {
                            return;
                        }
                        utils_1.Utils.removeFromArray(masterList, columnToAdd);
                    }
                    columnCallback(columnToAdd);
                    atLeastOne = true;
                });
                if (!atLeastOne) {
                    return;
                }
                if (this.autoGroupsNeedBuilding) {
                    this.updateGridColumns();
                }
                this.updateDisplayedColumns(source);
                var event = {
                    type: eventType,
                    columns: masterList,
                    column: masterList.length === 1 ? masterList[0] : null,
                    api: this.gridApi,
                    columnApi: this.columnApi,
                    source: source
                };
                this.eventService.dispatchEvent(event);
            };
            ColumnController.prototype.setRowGroupColumns = function(colKeys, source) {
                if (source === void 0) {
                    source = "api";
                }
                this.autoGroupsNeedBuilding = true;
                this.setPrimaryColumnList(colKeys, this.rowGroupColumns, events_1.Events.EVENT_COLUMN_ROW_GROUP_CHANGED, this.setRowGroupActive.bind(this), source);
            };
            ColumnController.prototype.setRowGroupActive = function(active, column, source) {
                if (active === column.isRowGroupActive()) {
                    return;
                }
                column.setRowGroupActive(active, source);
                if (!active && !this.gridOptionsWrapper.isSuppressMakeColumnVisibleAfterUnGroup()) {
                    column.setVisible(true, source);
                }
            };
            ColumnController.prototype.addRowGroupColumn = function(key, source) {
                if (source === void 0) {
                    source = "api";
                }
                this.addRowGroupColumns([ key ], source);
            };
            ColumnController.prototype.addRowGroupColumns = function(keys, source) {
                if (source === void 0) {
                    source = "api";
                }
                this.autoGroupsNeedBuilding = true;
                this.updatePrimaryColumnList(keys, this.rowGroupColumns, true, this.setRowGroupActive.bind(this, true), events_1.Events.EVENT_COLUMN_ROW_GROUP_CHANGED, source);
            };
            ColumnController.prototype.removeRowGroupColumns = function(keys, source) {
                if (source === void 0) {
                    source = "api";
                }
                this.autoGroupsNeedBuilding = true;
                this.updatePrimaryColumnList(keys, this.rowGroupColumns, false, this.setRowGroupActive.bind(this, false), events_1.Events.EVENT_COLUMN_ROW_GROUP_CHANGED, source);
            };
            ColumnController.prototype.removeRowGroupColumn = function(key, source) {
                if (source === void 0) {
                    source = "api";
                }
                this.removeRowGroupColumns([ key ], source);
            };
            ColumnController.prototype.addPivotColumns = function(keys, source) {
                if (source === void 0) {
                    source = "api";
                }
                this.updatePrimaryColumnList(keys, this.pivotColumns, true, function(column) {
                    return column.setPivotActive(true, source);
                }, events_1.Events.EVENT_COLUMN_PIVOT_CHANGED, source);
            };
            ColumnController.prototype.setPivotColumns = function(colKeys, source) {
                if (source === void 0) {
                    source = "api";
                }
                this.setPrimaryColumnList(colKeys, this.pivotColumns, events_1.Events.EVENT_COLUMN_PIVOT_CHANGED, function(added, column) {
                    column.setPivotActive(added, source);
                }, source);
            };
            ColumnController.prototype.addPivotColumn = function(key, source) {
                if (source === void 0) {
                    source = "api";
                }
                this.addPivotColumns([ key ], source);
            };
            ColumnController.prototype.removePivotColumns = function(keys, source) {
                if (source === void 0) {
                    source = "api";
                }
                this.updatePrimaryColumnList(keys, this.pivotColumns, false, function(column) {
                    return column.setPivotActive(false, source);
                }, events_1.Events.EVENT_COLUMN_PIVOT_CHANGED, source);
            };
            ColumnController.prototype.removePivotColumn = function(key, source) {
                if (source === void 0) {
                    source = "api";
                }
                this.removePivotColumns([ key ], source);
            };
            ColumnController.prototype.setPrimaryColumnList = function(colKeys, masterList, eventName, columnCallback, source) {
                var _this = this;
                masterList.length = 0;
                if (utils_1.Utils.exists(colKeys)) {
                    colKeys.forEach(function(key) {
                        var column = _this.getPrimaryColumn(key);
                        masterList.push(column);
                    });
                }
                this.primaryColumns.forEach(function(column) {
                    var added = masterList.indexOf(column) >= 0;
                    columnCallback(added, column);
                });
                if (this.autoGroupsNeedBuilding) {
                    this.updateGridColumns();
                }
                this.updateDisplayedColumns(source);
                var event = {
                    type: eventName,
                    columns: masterList,
                    column: masterList.length === 1 ? masterList[0] : null,
                    api: this.gridApi,
                    columnApi: this.columnApi,
                    source: source
                };
                this.eventService.dispatchEvent(event);
            };
            ColumnController.prototype.setValueColumns = function(colKeys, source) {
                if (source === void 0) {
                    source = "api";
                }
                this.setPrimaryColumnList(colKeys, this.valueColumns, events_1.Events.EVENT_COLUMN_VALUE_CHANGED, this.setValueActive.bind(this), source);
            };
            ColumnController.prototype.setValueActive = function(active, column, source) {
                if (active === column.isValueActive()) {
                    return;
                }
                column.setValueActive(active, source);
                if (active && !column.getAggFunc()) {
                    var defaultAggFunc = this.aggFuncService.getDefaultAggFunc(column);
                    column.setAggFunc(defaultAggFunc);
                }
            };
            ColumnController.prototype.addValueColumns = function(keys, source) {
                if (source === void 0) {
                    source = "api";
                }
                this.updatePrimaryColumnList(keys, this.valueColumns, true, this.setValueActive.bind(this, true), events_1.Events.EVENT_COLUMN_VALUE_CHANGED, source);
            };
            ColumnController.prototype.addValueColumn = function(colKey, source) {
                if (source === void 0) {
                    source = "api";
                }
                this.addValueColumns([ colKey ], source);
            };
            ColumnController.prototype.removeValueColumn = function(colKey, source) {
                if (source === void 0) {
                    source = "api";
                }
                this.removeValueColumns([ colKey ], source);
            };
            ColumnController.prototype.removeValueColumns = function(keys, source) {
                if (source === void 0) {
                    source = "api";
                }
                this.updatePrimaryColumnList(keys, this.valueColumns, false, this.setValueActive.bind(this, false), events_1.Events.EVENT_COLUMN_VALUE_CHANGED, source);
            };
            ColumnController.prototype.normaliseColumnWidth = function(column, newWidth) {
                if (newWidth < column.getMinWidth()) {
                    newWidth = column.getMinWidth();
                }
                if (column.isGreaterThanMax(newWidth)) {
                    newWidth = column.getMaxWidth();
                }
                return newWidth;
            };
            ColumnController.prototype.getPrimaryOrGridColumn = function(key) {
                var column = this.getPrimaryColumn(key);
                if (column) {
                    return column;
                } else {
                    return this.getGridColumn(key);
                }
            };
            ColumnController.prototype.setColumnWidth = function(key, newWidth, takeFromAdjacent, finished, source) {
                if (source === void 0) {
                    source = "api";
                }
                var col = this.getPrimaryOrGridColumn(key);
                if (!col) {
                    return;
                }
                var sets = [];
                sets.push({
                    width: newWidth,
                    ratios: [ 1 ],
                    columns: [ col ]
                });
                if (takeFromAdjacent) {
                    var otherCol = this.getDisplayedColAfter(col);
                    if (!otherCol) {
                        return;
                    }
                    var widthDiff = col.getActualWidth() - newWidth;
                    var otherColWidth = otherCol.getActualWidth() + widthDiff;
                    sets.push({
                        width: otherColWidth,
                        ratios: [ 1 ],
                        columns: [ otherCol ]
                    });
                }
                this.resizeColumnSets(sets, finished, source);
            };
            ColumnController.prototype.checkMinAndMaxWidthsForSet = function(columnResizeSet) {
                var columns = columnResizeSet.columns, width = columnResizeSet.width;
                var minWidthAccumulated = 0;
                var maxWidthAccumulated = 0;
                var maxWidthActive = true;
                columns.forEach(function(col) {
                    minWidthAccumulated += col.getMinWidth();
                    if (col.getMaxWidth() > 0) {
                        maxWidthAccumulated += col.getMaxWidth();
                    } else {
                        maxWidthActive = false;
                    }
                });
                var minWidthPasses = width >= minWidthAccumulated;
                var maxWidthPasses = !maxWidthActive || width <= maxWidthAccumulated;
                return minWidthPasses && maxWidthPasses;
            };
            ColumnController.prototype.resizeColumnSets = function(resizeSets, finished, source) {
                var passMinMaxCheck = utils_1.Utils.every(resizeSets, this.checkMinAndMaxWidthsForSet.bind(this));
                if (!passMinMaxCheck) {
                    return;
                }
                var changedCols = [];
                var allCols = [];
                resizeSets.forEach(function(set) {
                    var width = set.width, columns = set.columns, ratios = set.ratios;
                    var newWidths = {};
                    var finishedCols = {};
                    columns.forEach(function(col) {
                        return allCols.push(col);
                    });
                    var finishedColsGrew = true;
                    var loopCount = 0;
                    var _loop_2 = function() {
                        loopCount++;
                        if (loopCount > 1e3) {
                            console.error("ag-Grid: infinite loop in resizeColumnSets");
                            return "break";
                        }
                        finishedColsGrew = false;
                        var subsetCols = [];
                        var subsetRatios = [];
                        var subsetRatioTotal = 0;
                        var pixelsToDistribute = width;
                        columns.forEach(function(col, index) {
                            var thisColFinished = finishedCols[col.getId()];
                            if (thisColFinished) {
                                pixelsToDistribute -= newWidths[col.getId()];
                            } else {
                                subsetCols.push(col);
                                var ratioThisCol = ratios[index];
                                subsetRatioTotal += ratioThisCol;
                                subsetRatios.push(ratioThisCol);
                            }
                        });
                        var ratioScale = 1 / subsetRatioTotal;
                        subsetCols.forEach(function(col, index) {
                            var lastCol = index === subsetCols.length - 1;
                            var colNewWidth;
                            if (lastCol) {
                                colNewWidth = pixelsToDistribute;
                            } else {
                                colNewWidth = Math.round(ratios[index] * width * ratioScale);
                                pixelsToDistribute -= colNewWidth;
                            }
                            if (colNewWidth < col.getMinWidth()) {
                                colNewWidth = col.getMinWidth();
                                finishedCols[col.getId()] = true;
                                finishedColsGrew = true;
                            } else if (col.getMaxWidth() > 0 && colNewWidth > col.getMaxWidth()) {
                                colNewWidth = col.getMaxWidth();
                                finishedCols[col.getId()] = true;
                                finishedColsGrew = true;
                            }
                            newWidths[col.getId()] = colNewWidth;
                        });
                    };
                    while (finishedColsGrew) {
                        var state_1 = _loop_2();
                        if (state_1 === "break") break;
                    }
                    columns.forEach(function(col) {
                        var newWidth = newWidths[col.getId()];
                        if (col.getActualWidth() !== newWidth) {
                            col.setActualWidth(newWidth);
                            changedCols.push(col);
                        }
                    });
                });
                var atLeastOneColChanged = changedCols.length > 0;
                if (atLeastOneColChanged) {
                    this.setLeftValues(source);
                    this.updateBodyWidths();
                    this.checkDisplayedVirtualColumns();
                }
                if (atLeastOneColChanged || finished) {
                    var event_3 = {
                        type: events_1.Events.EVENT_COLUMN_RESIZED,
                        columns: allCols,
                        column: allCols.length === 1 ? allCols[0] : null,
                        finished: finished,
                        api: this.gridApi,
                        columnApi: this.columnApi,
                        source: source
                    };
                    this.eventService.dispatchEvent(event_3);
                }
            };
            ColumnController.prototype.setColumnAggFunc = function(column, aggFunc, source) {
                if (source === void 0) {
                    source = "api";
                }
                column.setAggFunc(aggFunc);
                var event = {
                    type: events_1.Events.EVENT_COLUMN_VALUE_CHANGED,
                    columns: [ column ],
                    column: column,
                    api: this.gridApi,
                    columnApi: this.columnApi,
                    source: source
                };
                this.eventService.dispatchEvent(event);
            };
            ColumnController.prototype.moveRowGroupColumn = function(fromIndex, toIndex, source) {
                if (source === void 0) {
                    source = "api";
                }
                var column = this.rowGroupColumns[fromIndex];
                this.rowGroupColumns.splice(fromIndex, 1);
                this.rowGroupColumns.splice(toIndex, 0, column);
                var event = {
                    type: events_1.Events.EVENT_COLUMN_ROW_GROUP_CHANGED,
                    columns: this.rowGroupColumns,
                    column: this.rowGroupColumns.length === 1 ? this.rowGroupColumns[0] : null,
                    api: this.gridApi,
                    columnApi: this.columnApi,
                    source: source
                };
                this.eventService.dispatchEvent(event);
            };
            ColumnController.prototype.moveColumns = function(columnsToMoveKeys, toIndex, source) {
                if (source === void 0) {
                    source = "api";
                }
                this.columnAnimationService.start();
                if (toIndex > this.gridColumns.length - columnsToMoveKeys.length) {
                    console.warn("ag-Grid: tried to insert columns in invalid location, toIndex = " + toIndex);
                    console.warn("ag-Grid: remember that you should not count the moving columns when calculating the new index");
                    return;
                }
                var columnsToMove = this.getGridColumns(columnsToMoveKeys);
                var failedRules = !this.doesMovePassRules(columnsToMove, toIndex);
                if (failedRules) {
                    return;
                }
                utils_1.Utils.moveInArray(this.gridColumns, columnsToMove, toIndex);
                this.updateDisplayedColumns(source);
                var event = {
                    type: events_1.Events.EVENT_COLUMN_MOVED,
                    columns: columnsToMove,
                    column: columnsToMove.length === 1 ? columnsToMove[0] : null,
                    toIndex: toIndex,
                    api: this.gridApi,
                    columnApi: this.columnApi,
                    source: source
                };
                this.eventService.dispatchEvent(event);
                this.columnAnimationService.finish();
            };
            ColumnController.prototype.doesMovePassRules = function(columnsToMove, toIndex) {
                var proposedColumnOrder = this.gridColumns.slice();
                utils_1.Utils.moveInArray(proposedColumnOrder, columnsToMove, toIndex);
                if (!this.doesMovePassMarryChildren(proposedColumnOrder)) {
                    return false;
                }
                if (!this.doesMovePassLockedPositions(proposedColumnOrder)) {
                    return false;
                }
                return true;
            };
            ColumnController.prototype.doesMovePassLockedPositions = function(proposedColumnOrder) {
                var foundNonLocked = false;
                var rulePassed = true;
                proposedColumnOrder.forEach(function(col) {
                    if (col.isLockPosition()) {
                        if (foundNonLocked) {
                            rulePassed = false;
                        }
                    } else {
                        foundNonLocked = true;
                    }
                });
                return rulePassed;
            };
            ColumnController.prototype.doesMovePassMarryChildren = function(allColumnsCopy) {
                var rulePassed = true;
                this.columnUtils.depthFirstOriginalTreeSearch(this.gridBalancedTree, function(child) {
                    if (!(child instanceof originalColumnGroup_1.OriginalColumnGroup)) {
                        return;
                    }
                    var columnGroup = child;
                    var marryChildren = columnGroup.getColGroupDef() && columnGroup.getColGroupDef().marryChildren;
                    if (!marryChildren) {
                        return;
                    }
                    var newIndexes = [];
                    columnGroup.getLeafColumns().forEach(function(col) {
                        var newColIndex = allColumnsCopy.indexOf(col);
                        newIndexes.push(newColIndex);
                    });
                    var maxIndex = Math.max.apply(Math, newIndexes);
                    var minIndex = Math.min.apply(Math, newIndexes);
                    var spread = maxIndex - minIndex;
                    var maxSpread = columnGroup.getLeafColumns().length - 1;
                    if (spread > maxSpread) {
                        rulePassed = false;
                    }
                });
                return rulePassed;
            };
            ColumnController.prototype.moveColumn = function(key, toIndex, source) {
                if (source === void 0) {
                    source = "api";
                }
                this.moveColumns([ key ], toIndex, source);
            };
            ColumnController.prototype.moveColumnByIndex = function(fromIndex, toIndex, source) {
                if (source === void 0) {
                    source = "api";
                }
                var column = this.gridColumns[fromIndex];
                this.moveColumn(column, toIndex, source);
            };
            ColumnController.prototype.getBodyContainerWidth = function() {
                return this.bodyWidth;
            };
            ColumnController.prototype.getContainerWidth = function(pinned) {
                switch (pinned) {
                  case column_1.Column.PINNED_LEFT:
                    return this.leftWidth;

                  case column_1.Column.PINNED_RIGHT:
                    return this.rightWidth;

                  default:
                    return this.bodyWidth;
                }
            };
            ColumnController.prototype.updateBodyWidths = function() {
                var newBodyWidth = this.getWidthOfColsInList(this.displayedCenterColumns);
                var newLeftWidth = this.getWidthOfColsInList(this.displayedLeftColumns);
                var newRightWidth = this.getWidthOfColsInList(this.displayedRightColumns);
                this.bodyWidthDirty = this.bodyWidth !== newBodyWidth;
                var atLeastOneChanged = this.bodyWidth !== newBodyWidth || this.leftWidth !== newLeftWidth || this.rightWidth !== newRightWidth;
                if (atLeastOneChanged) {
                    this.bodyWidth = newBodyWidth;
                    this.leftWidth = newLeftWidth;
                    this.rightWidth = newRightWidth;
                    var event_4 = {
                        type: events_1.Events.EVENT_DISPLAYED_COLUMNS_WIDTH_CHANGED,
                        api: this.gridApi,
                        columnApi: this.columnApi
                    };
                    this.eventService.dispatchEvent(event_4);
                }
            };
            ColumnController.prototype.getValueColumns = function() {
                return this.valueColumns ? this.valueColumns : [];
            };
            ColumnController.prototype.getPivotColumns = function() {
                return this.pivotColumns ? this.pivotColumns : [];
            };
            ColumnController.prototype.isPivotActive = function() {
                return this.pivotColumns && this.pivotColumns.length > 0 && this.pivotMode;
            };
            ColumnController.prototype.getRowGroupColumns = function() {
                return this.rowGroupColumns ? this.rowGroupColumns : [];
            };
            ColumnController.prototype.getDisplayedCenterColumns = function() {
                return this.displayedCenterColumns;
            };
            ColumnController.prototype.getDisplayedLeftColumns = function() {
                return this.displayedLeftColumns;
            };
            ColumnController.prototype.getDisplayedRightColumns = function() {
                return this.displayedRightColumns;
            };
            ColumnController.prototype.getDisplayedColumns = function(type) {
                switch (type) {
                  case column_1.Column.PINNED_LEFT:
                    return this.getDisplayedLeftColumns();

                  case column_1.Column.PINNED_RIGHT:
                    return this.getDisplayedRightColumns();

                  default:
                    return this.getDisplayedCenterColumns();
                }
            };
            ColumnController.prototype.getAllPrimaryColumns = function() {
                return this.primaryColumns;
            };
            ColumnController.prototype.getAllColumnsForQuickFilter = function() {
                return this.columnsForQuickFilter;
            };
            ColumnController.prototype.getAllGridColumns = function() {
                return this.gridColumns;
            };
            ColumnController.prototype.isEmpty = function() {
                return utils_1.Utils.missingOrEmpty(this.gridColumns);
            };
            ColumnController.prototype.isRowGroupEmpty = function() {
                return utils_1.Utils.missingOrEmpty(this.rowGroupColumns);
            };
            ColumnController.prototype.setColumnVisible = function(key, visible, source) {
                if (source === void 0) {
                    source = "api";
                }
                this.setColumnsVisible([ key ], visible, source);
            };
            ColumnController.prototype.setColumnsVisible = function(keys, visible, source) {
                var _this = this;
                if (source === void 0) {
                    source = "api";
                }
                this.columnAnimationService.start();
                this.actionOnGridColumns(keys, function(column) {
                    if (column.isVisible() !== visible) {
                        column.setVisible(visible, source);
                        return true;
                    } else {
                        return false;
                    }
                }, source, function() {
                    var event = {
                        type: events_1.Events.EVENT_COLUMN_VISIBLE,
                        visible: visible,
                        column: null,
                        columns: null,
                        api: _this.gridApi,
                        columnApi: _this.columnApi,
                        source: source
                    };
                    return event;
                });
                this.columnAnimationService.finish();
            };
            ColumnController.prototype.setColumnPinned = function(key, pinned, source) {
                if (source === void 0) {
                    source = "api";
                }
                this.setColumnsPinned([ key ], pinned, source);
            };
            ColumnController.prototype.setColumnsPinned = function(keys, pinned, source) {
                var _this = this;
                if (source === void 0) {
                    source = "api";
                }
                this.columnAnimationService.start();
                var actualPinned;
                if (pinned === true || pinned === column_1.Column.PINNED_LEFT) {
                    actualPinned = column_1.Column.PINNED_LEFT;
                } else if (pinned === column_1.Column.PINNED_RIGHT) {
                    actualPinned = column_1.Column.PINNED_RIGHT;
                } else {
                    actualPinned = null;
                }
                this.actionOnGridColumns(keys, function(col) {
                    if (col.getPinned() !== actualPinned) {
                        col.setPinned(actualPinned);
                        return true;
                    } else {
                        return false;
                    }
                }, source, function() {
                    var event = {
                        type: events_1.Events.EVENT_COLUMN_PINNED,
                        pinned: actualPinned,
                        column: null,
                        columns: null,
                        api: _this.gridApi,
                        columnApi: _this.columnApi,
                        source: source
                    };
                    return event;
                });
                this.columnAnimationService.finish();
            };
            ColumnController.prototype.actionOnGridColumns = function(keys, action, source, createEvent) {
                var _this = this;
                if (utils_1.Utils.missingOrEmpty(keys)) {
                    return;
                }
                var updatedColumns = [];
                keys.forEach(function(key) {
                    var column = _this.getGridColumn(key);
                    if (!column) {
                        return;
                    }
                    var resultOfAction = action(column);
                    if (resultOfAction !== false) {
                        updatedColumns.push(column);
                    }
                });
                if (updatedColumns.length === 0) {
                    return;
                }
                this.updateDisplayedColumns(source);
                if (utils_1.Utils.exists(createEvent)) {
                    var event_5 = createEvent();
                    event_5.columns = updatedColumns;
                    event_5.column = updatedColumns.length === 1 ? updatedColumns[0] : null;
                    this.eventService.dispatchEvent(event_5);
                }
            };
            ColumnController.prototype.getDisplayedColBefore = function(col) {
                var allDisplayedColumns = this.getAllDisplayedColumns();
                var oldIndex = allDisplayedColumns.indexOf(col);
                if (oldIndex > 0) {
                    return allDisplayedColumns[oldIndex - 1];
                } else {
                    return null;
                }
            };
            ColumnController.prototype.getDisplayedColAfter = function(col) {
                var allDisplayedColumns = this.getAllDisplayedColumns();
                var oldIndex = allDisplayedColumns.indexOf(col);
                if (oldIndex < allDisplayedColumns.length - 1) {
                    return allDisplayedColumns[oldIndex + 1];
                } else {
                    return null;
                }
            };
            ColumnController.prototype.getDisplayedGroupAfter = function(columnGroup) {
                var col = columnGroup.getDisplayedLeafColumns()[0];
                var requiredLevel = columnGroup.getOriginalColumnGroup().getLevel();
                while (true) {
                    col = this.getDisplayedColAfter(col);
                    if (!col) {
                        return null;
                    }
                    var groupPointer = col.getParent();
                    while (groupPointer.getOriginalColumnGroup().getLevel() !== requiredLevel) {
                        groupPointer = groupPointer.getParent();
                    }
                    if (groupPointer !== columnGroup) {
                        return groupPointer;
                    }
                }
            };
            ColumnController.prototype.isPinningLeft = function() {
                return this.displayedLeftColumns.length > 0;
            };
            ColumnController.prototype.isPinningRight = function() {
                return this.displayedRightColumns.length > 0;
            };
            ColumnController.prototype.getPrimaryAndSecondaryAndAutoColumns = function() {
                var result = this.primaryColumns ? this.primaryColumns.slice(0) : [];
                if (utils_1.Utils.exists(this.groupAutoColumns)) {
                    this.groupAutoColumns.forEach(function(col) {
                        return result.push(col);
                    });
                }
                if (this.secondaryColumnsPresent) {
                    this.secondaryColumns.forEach(function(column) {
                        return result.push(column);
                    });
                }
                return result;
            };
            ColumnController.prototype.createStateItemFromColumn = function(column) {
                var rowGroupIndex = column.isRowGroupActive() ? this.rowGroupColumns.indexOf(column) : null;
                var pivotIndex = column.isPivotActive() ? this.pivotColumns.indexOf(column) : null;
                var aggFunc = column.isValueActive() ? column.getAggFunc() : null;
                return {
                    colId: column.getColId(),
                    hide: !column.isVisible(),
                    aggFunc: aggFunc,
                    width: column.getActualWidth(),
                    pivotIndex: pivotIndex,
                    pinned: column.getPinned(),
                    rowGroupIndex: rowGroupIndex
                };
            };
            ColumnController.prototype.getColumnState = function() {
                if (utils_1.Utils.missing(this.primaryColumns)) {
                    return [];
                }
                var columnStateList = this.primaryColumns.map(this.createStateItemFromColumn.bind(this));
                if (!this.pivotMode) {
                    this.orderColumnStateList(columnStateList);
                }
                return columnStateList;
            };
            ColumnController.prototype.orderColumnStateList = function(columnStateList) {
                var gridColumnIds = this.gridColumns.map(function(column) {
                    return column.getColId();
                });
                columnStateList.sort(function(itemA, itemB) {
                    var posA = gridColumnIds.indexOf(itemA.colId);
                    var posB = gridColumnIds.indexOf(itemB.colId);
                    return posA - posB;
                });
            };
            ColumnController.prototype.resetColumnState = function(source) {
                if (source === void 0) {
                    source = "api";
                }
                var primaryColumns = this.getColumnsFromTree(this.primaryBalancedTree);
                var state = [];
                if (primaryColumns) {
                    primaryColumns.forEach(function(column) {
                        state.push({
                            colId: column.getColId(),
                            aggFunc: column.getColDef().aggFunc,
                            hide: column.getColDef().hide,
                            pinned: column.getColDef().pinned,
                            rowGroupIndex: column.getColDef().rowGroupIndex,
                            pivotIndex: column.getColDef().pivotIndex,
                            width: column.getColDef().width
                        });
                    });
                }
                this.setColumnState(state, source);
            };
            ColumnController.prototype.setColumnState = function(columnState, source) {
                var _this = this;
                if (source === void 0) {
                    source = "api";
                }
                if (utils_1.Utils.missingOrEmpty(this.primaryColumns)) {
                    return false;
                }
                this.autoGroupsNeedBuilding = true;
                var columnsWithNoState = this.primaryColumns.slice();
                this.rowGroupColumns = [];
                this.valueColumns = [];
                this.pivotColumns = [];
                var success = true;
                var rowGroupIndexes = {};
                var pivotIndexes = {};
                if (columnState) {
                    columnState.forEach(function(stateItem) {
                        var column = _this.getPrimaryColumn(stateItem.colId);
                        if (!column) {
                            console.warn("ag-grid: column " + stateItem.colId + " not found");
                            success = false;
                        } else {
                            _this.syncColumnWithStateItem(column, stateItem, rowGroupIndexes, pivotIndexes, source);
                            utils_1.Utils.removeFromArray(columnsWithNoState, column);
                        }
                    });
                }
                columnsWithNoState.forEach(this.syncColumnWithNoState.bind(this));
                this.rowGroupColumns.sort(this.sortColumnListUsingIndexes.bind(this, rowGroupIndexes));
                this.pivotColumns.sort(this.sortColumnListUsingIndexes.bind(this, pivotIndexes));
                this.updateGridColumns();
                if (columnState) {
                    var orderOfColIds_1 = columnState.map(function(stateItem) {
                        return stateItem.colId;
                    });
                    this.gridColumns.sort(function(colA, colB) {
                        var indexA = orderOfColIds_1.indexOf(colA.getId());
                        var indexB = orderOfColIds_1.indexOf(colB.getId());
                        return indexA - indexB;
                    });
                }
                this.updateDisplayedColumns(source);
                var event = {
                    type: events_1.Events.EVENT_COLUMN_EVERYTHING_CHANGED,
                    api: this.gridApi,
                    columnApi: this.columnApi,
                    source: source
                };
                this.eventService.dispatchEvent(event);
                return success;
            };
            ColumnController.prototype.sortColumnListUsingIndexes = function(indexes, colA, colB) {
                var indexA = indexes[colA.getId()];
                var indexB = indexes[colB.getId()];
                return indexA - indexB;
            };
            ColumnController.prototype.syncColumnWithNoState = function(column, source) {
                column.setVisible(false, source);
                column.setAggFunc(null);
                column.setPinned(null);
                column.setRowGroupActive(false, source);
                column.setPivotActive(false, source);
                column.setValueActive(false, source);
            };
            ColumnController.prototype.syncColumnWithStateItem = function(column, stateItem, rowGroupIndexes, pivotIndexes, source) {
                column.setVisible(!stateItem.hide, source);
                column.setPinned(stateItem.pinned);
                if (stateItem.width >= this.gridOptionsWrapper.getMinColWidth()) {
                    column.setActualWidth(stateItem.width, source);
                }
                if (typeof stateItem.aggFunc === "string") {
                    column.setAggFunc(stateItem.aggFunc);
                    column.setValueActive(true, source);
                    this.valueColumns.push(column);
                } else {
                    if (utils_1.Utils.exists(stateItem.aggFunc)) {
                        console.warn("ag-Grid: stateItem.aggFunc must be a string. if using your own aggregation " + "functions, register the functions first before using them in get/set state. This is because it is" + "intended for the column state to be stored and retrieved as simple JSON.");
                    }
                    column.setAggFunc(null);
                    column.setValueActive(false, source);
                }
                if (typeof stateItem.rowGroupIndex === "number") {
                    this.rowGroupColumns.push(column);
                    column.setRowGroupActive(true, source);
                    rowGroupIndexes[column.getId()] = stateItem.rowGroupIndex;
                } else {
                    column.setRowGroupActive(false, source);
                }
                if (typeof stateItem.pivotIndex === "number") {
                    this.pivotColumns.push(column);
                    column.setPivotActive(true, source);
                    pivotIndexes[column.getId()] = stateItem.pivotIndex;
                } else {
                    column.setPivotActive(false, source);
                }
            };
            ColumnController.prototype.getGridColumns = function(keys) {
                return this.getColumns(keys, this.getGridColumn.bind(this));
            };
            ColumnController.prototype.getColumns = function(keys, columnLookupCallback) {
                var foundColumns = [];
                if (keys) {
                    keys.forEach(function(key) {
                        var column = columnLookupCallback(key);
                        if (column) {
                            foundColumns.push(column);
                        }
                    });
                }
                return foundColumns;
            };
            ColumnController.prototype.getColumnWithValidation = function(key) {
                var column = this.getPrimaryColumn(key);
                if (!column) {
                    console.warn("ag-Grid: could not find column " + column);
                }
                return column;
            };
            ColumnController.prototype.getPrimaryColumn = function(key) {
                return this.getColumn(key, this.primaryColumns);
            };
            ColumnController.prototype.getGridColumn = function(key) {
                return this.getColumn(key, this.gridColumns);
            };
            ColumnController.prototype.getColumn = function(key, columnList) {
                if (!key) {
                    return null;
                }
                for (var i = 0; i < columnList.length; i++) {
                    if (this.columnsMatch(columnList[i], key)) {
                        return columnList[i];
                    }
                }
                return this.getAutoColumn(key);
            };
            ColumnController.prototype.getAutoColumn = function(key) {
                var _this = this;
                if (!utils_1.Utils.exists(this.groupAutoColumns) || utils_1.Utils.missing(this.groupAutoColumns)) {
                    return null;
                }
                return utils_1.Utils.find(this.groupAutoColumns, function(groupCol) {
                    return _this.columnsMatch(groupCol, key);
                });
            };
            ColumnController.prototype.columnsMatch = function(column, key) {
                var columnMatches = column === key;
                var colDefMatches = column.getColDef() === key;
                var idMatches = column.getColId() == key;
                return columnMatches || colDefMatches || idMatches;
            };
            ColumnController.prototype.getDisplayNameForColumn = function(column, location, includeAggFunc) {
                if (includeAggFunc === void 0) {
                    includeAggFunc = false;
                }
                var headerName = this.getHeaderName(column.getColDef(), column, null, null, location);
                if (includeAggFunc) {
                    return this.wrapHeaderNameWithAggFunc(column, headerName);
                } else {
                    return headerName;
                }
            };
            ColumnController.prototype.getDisplayNameForOriginalColumnGroup = function(columnGroup, originalColumnGroup, location) {
                var colGroupDef = originalColumnGroup.getColGroupDef();
                if (colGroupDef) {
                    return this.getHeaderName(colGroupDef, null, columnGroup, originalColumnGroup, location);
                } else {
                    return null;
                }
            };
            ColumnController.prototype.getDisplayNameForColumnGroup = function(columnGroup, location) {
                return this.getDisplayNameForOriginalColumnGroup(columnGroup, columnGroup.getOriginalColumnGroup(), location);
            };
            ColumnController.prototype.getHeaderName = function(colDef, column, columnGroup, originalColumnGroup, location) {
                var headerValueGetter = colDef.headerValueGetter;
                if (headerValueGetter) {
                    var params = {
                        colDef: colDef,
                        column: column,
                        columnGroup: columnGroup,
                        originalColumnGroup: originalColumnGroup,
                        location: location,
                        api: this.gridOptionsWrapper.getApi(),
                        context: this.gridOptionsWrapper.getContext()
                    };
                    if (typeof headerValueGetter === "function") {
                        return headerValueGetter(params);
                    } else if (typeof headerValueGetter === "string") {
                        return this.expressionService.evaluate(headerValueGetter, params);
                    } else {
                        console.warn("ag-grid: headerValueGetter must be a function or a string");
                        return "";
                    }
                } else if (colDef.headerName != null) {
                    return colDef.headerName;
                } else if (colDef.field) {
                    return utils_1.Utils.camelCaseToHumanText(colDef.field);
                } else {
                    return "";
                }
            };
            ColumnController.prototype.wrapHeaderNameWithAggFunc = function(column, headerName) {
                if (this.gridOptionsWrapper.isSuppressAggFuncInHeader()) {
                    return headerName;
                }
                var pivotValueColumn = column.getColDef().pivotValueColumn;
                var pivotActiveOnThisColumn = utils_1.Utils.exists(pivotValueColumn);
                var aggFunc = null;
                var aggFuncFound;
                if (pivotActiveOnThisColumn) {
                    aggFunc = pivotValueColumn.getAggFunc();
                    aggFuncFound = true;
                } else {
                    var measureActive = column.isValueActive();
                    var aggregationPresent = this.pivotMode || !this.isRowGroupEmpty();
                    if (measureActive && aggregationPresent) {
                        aggFunc = column.getAggFunc();
                        aggFuncFound = true;
                    } else {
                        aggFuncFound = false;
                    }
                }
                if (aggFuncFound) {
                    var aggFuncString = typeof aggFunc === "string" ? aggFunc : "func";
                    var localeTextFunc = this.gridOptionsWrapper.getLocaleTextFunc();
                    var aggFuncStringTranslated = localeTextFunc(aggFuncString, aggFuncString);
                    return aggFuncStringTranslated + "(" + headerName + ")";
                } else {
                    return headerName;
                }
            };
            ColumnController.prototype.getColumnGroup = function(colId, instanceId) {
                if (!colId) {
                    return null;
                }
                if (colId instanceof columnGroup_1.ColumnGroup) {
                    return colId;
                }
                var allColumnGroups = this.getAllDisplayedColumnGroups();
                var checkInstanceId = typeof instanceId === "number";
                var result = null;
                this.columnUtils.depthFirstAllColumnTreeSearch(allColumnGroups, function(child) {
                    if (child instanceof columnGroup_1.ColumnGroup) {
                        var columnGroup = child;
                        var matched = void 0;
                        if (checkInstanceId) {
                            matched = colId === columnGroup.getGroupId() && instanceId === columnGroup.getInstanceId();
                        } else {
                            matched = colId === columnGroup.getGroupId();
                        }
                        if (matched) {
                            result = columnGroup;
                        }
                    }
                });
                return result;
            };
            ColumnController.prototype.setColumnDefs = function(columnDefs, source) {
                if (source === void 0) {
                    source = "api";
                }
                this.valueCache.expire();
                this.autoGroupsNeedBuilding = true;
                var balancedTreeResult = this.balancedColumnTreeBuilder.createBalancedColumnGroups(columnDefs, true);
                this.primaryBalancedTree = balancedTreeResult.balancedTree;
                this.primaryHeaderRowCount = balancedTreeResult.treeDept + 1;
                this.primaryColumns = this.getColumnsFromTree(this.primaryBalancedTree);
                this.autoRowHeightColumns = this.primaryColumns.filter(function(col) {
                    return col.getColDef().autoHeight;
                });
                this.extractRowGroupColumns(source);
                this.extractPivotColumns(source);
                this.createValueColumns(source);
                this.updateGridColumns();
                this.updateDisplayedColumns(source);
                this.checkDisplayedVirtualColumns();
                this.ready = true;
                var eventEverythingChanged = {
                    type: events_1.Events.EVENT_COLUMN_EVERYTHING_CHANGED,
                    api: this.gridApi,
                    columnApi: this.columnApi,
                    source: source
                };
                this.eventService.dispatchEvent(eventEverythingChanged);
                var newColumnsLoadedEvent = {
                    type: events_1.Events.EVENT_NEW_COLUMNS_LOADED,
                    api: this.gridApi,
                    columnApi: this.columnApi
                };
                this.eventService.dispatchEvent(newColumnsLoadedEvent);
            };
            ColumnController.prototype.isReady = function() {
                return this.ready;
            };
            ColumnController.prototype.extractRowGroupColumns = function(source) {
                var _this = this;
                this.rowGroupColumns.forEach(function(column) {
                    return column.setRowGroupActive(false, source);
                });
                this.rowGroupColumns = [];
                this.primaryColumns.forEach(function(column) {
                    if (typeof column.getColDef().rowGroupIndex === "number") {
                        _this.rowGroupColumns.push(column);
                        column.setRowGroupActive(true, source);
                    }
                });
                this.rowGroupColumns.sort(function(colA, colB) {
                    return colA.getColDef().rowGroupIndex - colB.getColDef().rowGroupIndex;
                });
                this.primaryColumns.forEach(function(column) {
                    if (column.getColDef().rowGroup) {
                        if (_this.rowGroupColumns.indexOf(column) >= 0) {
                            return;
                        }
                        _this.rowGroupColumns.push(column);
                        column.setRowGroupActive(true, source);
                    }
                });
            };
            ColumnController.prototype.extractPivotColumns = function(source) {
                var _this = this;
                this.pivotColumns.forEach(function(column) {
                    return column.setPivotActive(false, source);
                });
                this.pivotColumns = [];
                this.primaryColumns.forEach(function(column) {
                    if (typeof column.getColDef().pivotIndex === "number") {
                        _this.pivotColumns.push(column);
                        column.setPivotActive(true, source);
                    }
                });
                this.pivotColumns.sort(function(colA, colB) {
                    return colA.getColDef().pivotIndex - colB.getColDef().pivotIndex;
                });
                this.primaryColumns.forEach(function(column) {
                    if (column.getColDef().pivot) {
                        if (_this.pivotColumns.indexOf(column) >= 0) {
                            return;
                        }
                        _this.pivotColumns.push(column);
                        column.setPivotActive(true, source);
                    }
                });
            };
            ColumnController.prototype.resetColumnGroupState = function(source) {
                if (source === void 0) {
                    source = "api";
                }
                var stateItems = [];
                this.columnUtils.depthFirstOriginalTreeSearch(this.primaryBalancedTree, function(child) {
                    if (child instanceof originalColumnGroup_1.OriginalColumnGroup) {
                        var groupState = {
                            groupId: child.getGroupId(),
                            open: child.getColGroupDef().openByDefault
                        };
                        stateItems.push(groupState);
                    }
                });
                this.setColumnGroupState(stateItems, source);
            };
            ColumnController.prototype.getColumnGroupState = function() {
                var columnGroupState = [];
                this.columnUtils.depthFirstOriginalTreeSearch(this.gridBalancedTree, function(node) {
                    if (node instanceof originalColumnGroup_1.OriginalColumnGroup) {
                        var originalColumnGroup = node;
                        columnGroupState.push({
                            groupId: originalColumnGroup.getGroupId(),
                            open: originalColumnGroup.isExpanded()
                        });
                    }
                });
                return columnGroupState;
            };
            ColumnController.prototype.setColumnGroupState = function(stateItems, source) {
                var _this = this;
                if (source === void 0) {
                    source = "api";
                }
                this.columnAnimationService.start();
                var impactedGroups = [];
                stateItems.forEach(function(stateItem) {
                    var groupKey = stateItem.groupId;
                    var newValue = stateItem.open;
                    var originalColumnGroup = _this.getOriginalColumnGroup(groupKey);
                    if (!originalColumnGroup) {
                        return;
                    }
                    if (originalColumnGroup.isExpanded() === newValue) {
                        return;
                    }
                    _this.logger.log("columnGroupOpened(" + originalColumnGroup.getGroupId() + "," + newValue + ")");
                    originalColumnGroup.setExpanded(newValue);
                    impactedGroups.push(originalColumnGroup);
                });
                this.updateGroupsAndDisplayedColumns(source);
                impactedGroups.forEach(function(originalColumnGroup) {
                    var event = {
                        type: events_1.Events.EVENT_COLUMN_GROUP_OPENED,
                        columnGroup: originalColumnGroup,
                        api: _this.gridApi,
                        columnApi: _this.columnApi
                    };
                    _this.eventService.dispatchEvent(event);
                });
                this.columnAnimationService.finish();
            };
            ColumnController.prototype.setColumnGroupOpened = function(key, newValue, source) {
                if (source === void 0) {
                    source = "api";
                }
                var keyAsString;
                if (key instanceof originalColumnGroup_1.OriginalColumnGroup) {
                    keyAsString = key.getId();
                } else {
                    keyAsString = key;
                }
                this.setColumnGroupState([ {
                    groupId: keyAsString,
                    open: newValue
                } ], source);
            };
            ColumnController.prototype.getOriginalColumnGroup = function(key) {
                if (key instanceof originalColumnGroup_1.OriginalColumnGroup) {
                    return key;
                }
                if (typeof key !== "string") {
                    console.error("ag-Grid: group key must be a string");
                }
                var res = null;
                this.columnUtils.depthFirstOriginalTreeSearch(this.gridBalancedTree, function(node) {
                    if (node instanceof originalColumnGroup_1.OriginalColumnGroup) {
                        var originalColumnGroup = node;
                        if (originalColumnGroup.getId() === key) {
                            res = originalColumnGroup;
                        }
                    }
                });
                return res;
            };
            ColumnController.prototype.calculateColumnsForDisplay = function() {
                var _this = this;
                var columnsForDisplay;
                if (this.pivotMode && !this.secondaryColumnsPresent) {
                    columnsForDisplay = utils_1.Utils.filter(this.gridColumns, function(column) {
                        var isAutoGroupCol = _this.groupAutoColumns && _this.groupAutoColumns.indexOf(column) >= 0;
                        var isValueCol = _this.valueColumns && _this.valueColumns.indexOf(column) >= 0;
                        return isAutoGroupCol || isValueCol;
                    });
                } else {
                    columnsForDisplay = utils_1.Utils.filter(this.gridColumns, function(column) {
                        var isAutoGroupCol = _this.groupAutoColumns && _this.groupAutoColumns.indexOf(column) >= 0;
                        return isAutoGroupCol || column.isVisible();
                    });
                }
                return columnsForDisplay;
            };
            ColumnController.prototype.checkColSpanActiveInCols = function(columns) {
                var result = false;
                columns.forEach(function(col) {
                    if (utils_1.Utils.exists(col.getColDef().colSpan)) {
                        result = true;
                    }
                });
                return result;
            };
            ColumnController.prototype.calculateColumnsForGroupDisplay = function() {
                var _this = this;
                this.groupDisplayColumns = [];
                var checkFunc = function(col) {
                    var colDef = col.getColDef();
                    if (colDef && utils_1.Utils.exists(colDef.showRowGroup)) {
                        _this.groupDisplayColumns.push(col);
                    }
                };
                this.gridColumns.forEach(checkFunc);
                if (this.groupAutoColumns) {
                    this.groupAutoColumns.forEach(checkFunc);
                }
            };
            ColumnController.prototype.getGroupDisplayColumns = function() {
                return this.groupDisplayColumns;
            };
            ColumnController.prototype.updateDisplayedColumns = function(source) {
                var columnsForDisplay = this.calculateColumnsForDisplay();
                this.buildDisplayedTrees(columnsForDisplay);
                this.calculateColumnsForGroupDisplay();
                this.updateGroupsAndDisplayedColumns(source);
                this.setFirstRightAndLastLeftPinned(source);
            };
            ColumnController.prototype.isSecondaryColumnsPresent = function() {
                return this.secondaryColumnsPresent;
            };
            ColumnController.prototype.setSecondaryColumns = function(colDefs, source) {
                if (source === void 0) {
                    source = "api";
                }
                var newColsPresent = colDefs && colDefs.length > 0;
                if (!newColsPresent && !this.secondaryColumnsPresent) {
                    return;
                }
                if (newColsPresent) {
                    this.processSecondaryColumnDefinitions(colDefs);
                    var balancedTreeResult = this.balancedColumnTreeBuilder.createBalancedColumnGroups(colDefs, false);
                    this.secondaryBalancedTree = balancedTreeResult.balancedTree;
                    this.secondaryHeaderRowCount = balancedTreeResult.treeDept + 1;
                    this.secondaryColumns = this.getColumnsFromTree(this.secondaryBalancedTree);
                    this.secondaryColumnsPresent = true;
                } else {
                    this.secondaryBalancedTree = null;
                    this.secondaryHeaderRowCount = -1;
                    this.secondaryColumns = null;
                    this.secondaryColumnsPresent = false;
                }
                this.updateGridColumns();
                this.updateDisplayedColumns(source);
            };
            ColumnController.prototype.processSecondaryColumnDefinitions = function(colDefs) {
                var columnCallback = this.gridOptionsWrapper.getProcessSecondaryColDefFunc();
                var groupCallback = this.gridOptionsWrapper.getProcessSecondaryColGroupDefFunc();
                if (!columnCallback && !groupCallback) {
                    return;
                }
                searchForColDefs(colDefs);
                function searchForColDefs(colDefs2) {
                    colDefs2.forEach(function(abstractColDef) {
                        var isGroup = utils_1.Utils.exists(abstractColDef.children);
                        if (isGroup) {
                            var colGroupDef = abstractColDef;
                            if (groupCallback) {
                                groupCallback(colGroupDef);
                            }
                            searchForColDefs(colGroupDef.children);
                        } else {
                            var colDef = abstractColDef;
                            if (columnCallback) {
                                columnCallback(colDef);
                            }
                        }
                    });
                }
            };
            ColumnController.prototype.updateGridColumns = function() {
                if (this.gridColsArePrimary) {
                    this.lastPrimaryOrder = this.gridColumns;
                }
                if (this.secondaryColumns) {
                    this.gridBalancedTree = this.secondaryBalancedTree.slice();
                    this.gridHeaderRowCount = this.secondaryHeaderRowCount;
                    this.gridColumns = this.secondaryColumns.slice();
                    this.gridColsArePrimary = false;
                } else {
                    this.gridBalancedTree = this.primaryBalancedTree.slice();
                    this.gridHeaderRowCount = this.primaryHeaderRowCount;
                    this.gridColumns = this.primaryColumns.slice();
                    this.gridColsArePrimary = true;
                    this.orderGridColsLikeLastPrimary();
                }
                this.putFixedColumnsFirst();
                this.addAutoGroupToGridColumns();
                this.setupQuickFilterColumns();
                this.clearDisplayedColumns();
                this.colSpanActive = this.checkColSpanActiveInCols(this.gridColumns);
                var event = {
                    type: events_1.Events.EVENT_GRID_COLUMNS_CHANGED,
                    api: this.gridApi,
                    columnApi: this.columnApi
                };
                this.eventService.dispatchEvent(event);
            };
            ColumnController.prototype.orderGridColsLikeLastPrimary = function() {
                var _this = this;
                if (utils_1.Utils.missing(this.lastPrimaryOrder)) {
                    return;
                }
                var oneMissing = false;
                this.gridColumns.forEach(function(col) {
                    if (_this.lastPrimaryOrder.indexOf(col) < 0) {
                        oneMissing = true;
                    }
                });
                if (oneMissing) {
                    return;
                }
                this.gridColumns.sort(function(colA, colB) {
                    var indexA = _this.lastPrimaryOrder.indexOf(colA);
                    var indexB = _this.lastPrimaryOrder.indexOf(colB);
                    return indexA - indexB;
                });
            };
            ColumnController.prototype.isPrimaryColumnGroupsPresent = function() {
                return this.primaryHeaderRowCount > 1;
            };
            ColumnController.prototype.setupQuickFilterColumns = function() {
                if (this.groupAutoColumns) {
                    this.columnsForQuickFilter = this.primaryColumns.concat(this.groupAutoColumns);
                } else {
                    this.columnsForQuickFilter = this.primaryColumns;
                }
            };
            ColumnController.prototype.putFixedColumnsFirst = function() {
                var locked = this.gridColumns.filter(function(c) {
                    return c.isLockPosition();
                });
                var unlocked = this.gridColumns.filter(function(c) {
                    return !c.isLockPosition();
                });
                this.gridColumns = locked.concat(unlocked);
            };
            ColumnController.prototype.addAutoGroupToGridColumns = function() {
                this.createGroupAutoColumnsIfNeeded();
                if (utils_1.Utils.missing(this.groupAutoColumns)) {
                    return;
                }
                this.gridColumns = this.groupAutoColumns.concat(this.gridColumns);
                var autoColBalancedTree = this.balancedColumnTreeBuilder.createForAutoGroups(this.groupAutoColumns, this.gridBalancedTree);
                this.gridBalancedTree = autoColBalancedTree.concat(this.gridBalancedTree);
            };
            ColumnController.prototype.clearDisplayedColumns = function() {
                this.displayedLeftColumnTree = [];
                this.displayedRightColumnTree = [];
                this.displayedCentreColumnTree = [];
                this.displayedLeftHeaderRows = {};
                this.displayedRightHeaderRows = {};
                this.displayedCentreHeaderRows = {};
                this.displayedLeftColumns = [];
                this.displayedRightColumns = [];
                this.displayedCenterColumns = [];
                this.allDisplayedColumns = [];
                this.allDisplayedVirtualColumns = [];
            };
            ColumnController.prototype.updateGroupsAndDisplayedColumns = function(source) {
                this.updateOpenClosedVisibilityInColumnGroups();
                this.updateDisplayedColumnsFromTrees(source);
                this.updateVirtualSets();
                this.updateBodyWidths();
                var event = {
                    type: events_1.Events.EVENT_DISPLAYED_COLUMNS_CHANGED,
                    api: this.gridApi,
                    columnApi: this.columnApi
                };
                this.eventService.dispatchEvent(event);
            };
            ColumnController.prototype.updateDisplayedColumnsFromTrees = function(source) {
                this.addToDisplayedColumns(this.displayedLeftColumnTree, this.displayedLeftColumns);
                this.addToDisplayedColumns(this.displayedCentreColumnTree, this.displayedCenterColumns);
                this.addToDisplayedColumns(this.displayedRightColumnTree, this.displayedRightColumns);
                this.setupAllDisplayedColumns();
                this.setLeftValues(source);
            };
            ColumnController.prototype.setupAllDisplayedColumns = function() {
                if (this.gridOptionsWrapper.isEnableRtl()) {
                    this.allDisplayedColumns = this.displayedRightColumns.concat(this.displayedCenterColumns).concat(this.displayedLeftColumns);
                } else {
                    this.allDisplayedColumns = this.displayedLeftColumns.concat(this.displayedCenterColumns).concat(this.displayedRightColumns);
                }
            };
            ColumnController.prototype.setLeftValues = function(source) {
                this.setLeftValuesOfColumns(source);
                this.setLeftValuesOfGroups();
            };
            ColumnController.prototype.setLeftValuesOfColumns = function(source) {
                var _this = this;
                var allColumns = this.primaryColumns.slice(0);
                var doingRtl = this.gridOptionsWrapper.isEnableRtl();
                [ this.displayedLeftColumns, this.displayedRightColumns, this.displayedCenterColumns ].forEach(function(columns) {
                    if (doingRtl) {
                        var left_1 = _this.getWidthOfColsInList(columns);
                        columns.forEach(function(column) {
                            left_1 -= column.getActualWidth();
                            column.setLeft(left_1, source);
                        });
                    } else {
                        var left_2 = 0;
                        columns.forEach(function(column) {
                            column.setLeft(left_2, source);
                            left_2 += column.getActualWidth();
                        });
                    }
                    utils_1.Utils.removeAllFromArray(allColumns, columns);
                });
                allColumns.forEach(function(column) {
                    column.setLeft(null, source);
                });
            };
            ColumnController.prototype.setLeftValuesOfGroups = function() {
                [ this.displayedLeftColumnTree, this.displayedRightColumnTree, this.displayedCentreColumnTree ].forEach(function(columns) {
                    columns.forEach(function(column) {
                        if (column instanceof columnGroup_1.ColumnGroup) {
                            var columnGroup = column;
                            columnGroup.checkLeft();
                        }
                    });
                });
            };
            ColumnController.prototype.addToDisplayedColumns = function(displayedColumnTree, displayedColumns) {
                displayedColumns.length = 0;
                this.columnUtils.depthFirstDisplayedColumnTreeSearch(displayedColumnTree, function(child) {
                    if (child instanceof column_1.Column) {
                        displayedColumns.push(child);
                    }
                });
            };
            ColumnController.prototype.updateDisplayedCenterVirtualColumns = function() {
                if (this.suppressColumnVirtualisation) {
                    this.allDisplayedCenterVirtualColumns = this.displayedCenterColumns;
                } else {
                    this.allDisplayedCenterVirtualColumns = this.filterOutColumnsWithinViewport();
                }
                this.allDisplayedVirtualColumns = this.allDisplayedCenterVirtualColumns.concat(this.displayedLeftColumns).concat(this.displayedRightColumns);
                var result = {};
                this.allDisplayedVirtualColumns.forEach(function(col) {
                    result[col.getId()] = true;
                });
                return result;
            };
            ColumnController.prototype.getVirtualHeaderGroupRow = function(type, dept) {
                var result;
                switch (type) {
                  case column_1.Column.PINNED_LEFT:
                    result = this.displayedLeftHeaderRows[dept];
                    break;

                  case column_1.Column.PINNED_RIGHT:
                    result = this.displayedRightHeaderRows[dept];
                    break;

                  default:
                    result = this.displayedCentreHeaderRows[dept];
                    break;
                }
                if (utils_1.Utils.missing(result)) {
                    result = [];
                }
                return result;
            };
            ColumnController.prototype.updateDisplayedVirtualGroups = function(virtualColIds) {
                this.displayedLeftHeaderRows = {};
                this.displayedRightHeaderRows = {};
                this.displayedCentreHeaderRows = {};
                testGroup(this.displayedLeftColumnTree, this.displayedLeftHeaderRows, 0);
                testGroup(this.displayedRightColumnTree, this.displayedRightHeaderRows, 0);
                testGroup(this.displayedCentreColumnTree, this.displayedCentreHeaderRows, 0);
                function testGroup(children, result, dept) {
                    var returnValue = false;
                    for (var i = 0; i < children.length; i++) {
                        var child = children[i];
                        var addThisItem = void 0;
                        if (child instanceof column_1.Column) {
                            addThisItem = virtualColIds[child.getId()] === true;
                        } else {
                            var columnGroup = child;
                            addThisItem = testGroup(columnGroup.getDisplayedChildren(), result, dept + 1);
                        }
                        if (addThisItem) {
                            returnValue = true;
                            if (!result[dept]) {
                                result[dept] = [];
                            }
                            result[dept].push(child);
                        }
                    }
                    return returnValue;
                }
            };
            ColumnController.prototype.updateVirtualSets = function() {
                var virtualColIds = this.updateDisplayedCenterVirtualColumns();
                this.updateDisplayedVirtualGroups(virtualColIds);
            };
            ColumnController.prototype.filterOutColumnsWithinViewport = function() {
                return utils_1.Utils.filter(this.displayedCenterColumns, this.isColumnInViewport.bind(this));
            };
            ColumnController.prototype.sizeColumnsToFit = function(gridWidth, source) {
                var _this = this;
                if (source === void 0) {
                    source = "api";
                }
                var allDisplayedColumns = this.getAllDisplayedColumns();
                if (gridWidth <= 0 || allDisplayedColumns.length === 0) {
                    return;
                }
                var colsToNotSpread = utils_1.Utils.filter(allDisplayedColumns, function(column) {
                    return column.getColDef().suppressSizeToFit === true;
                });
                var colsToSpread = utils_1.Utils.filter(allDisplayedColumns, function(column) {
                    return column.getColDef().suppressSizeToFit !== true;
                });
                var colsToFireEventFor = colsToSpread.slice(0);
                var finishedResizing = false;
                while (!finishedResizing) {
                    finishedResizing = true;
                    var availablePixels = gridWidth - this.getWidthOfColsInList(colsToNotSpread);
                    if (availablePixels <= 0) {
                        colsToSpread.forEach(function(column) {
                            column.setMinimum(source);
                        });
                    } else {
                        var scale = availablePixels / this.getWidthOfColsInList(colsToSpread);
                        var pixelsForLastCol = availablePixels;
                        for (var i = colsToSpread.length - 1; i >= 0; i--) {
                            var column = colsToSpread[i];
                            var newWidth = Math.round(column.getActualWidth() * scale);
                            if (newWidth < column.getMinWidth()) {
                                column.setMinimum(source);
                                moveToNotSpread(column);
                                finishedResizing = false;
                            } else if (column.isGreaterThanMax(newWidth)) {
                                column.setActualWidth(column.getMaxWidth(), source);
                                moveToNotSpread(column);
                                finishedResizing = false;
                            } else {
                                var onLastCol = i === 0;
                                if (onLastCol) {
                                    column.setActualWidth(pixelsForLastCol, source);
                                } else {
                                    column.setActualWidth(newWidth, source);
                                }
                            }
                            pixelsForLastCol -= newWidth;
                        }
                    }
                }
                this.setLeftValues(source);
                this.updateBodyWidths();
                colsToFireEventFor.forEach(function(column) {
                    var event = {
                        type: events_1.Events.EVENT_COLUMN_RESIZED,
                        column: column,
                        columns: [ column ],
                        finished: true,
                        api: _this.gridApi,
                        columnApi: _this.columnApi,
                        source: "sizeColumnsToFit"
                    };
                    _this.eventService.dispatchEvent(event);
                });
                function moveToNotSpread(column) {
                    utils_1.Utils.removeFromArray(colsToSpread, column);
                    colsToNotSpread.push(column);
                }
            };
            ColumnController.prototype.buildDisplayedTrees = function(visibleColumns) {
                var leftVisibleColumns = utils_1.Utils.filter(visibleColumns, function(column) {
                    return column.getPinned() === "left";
                });
                var rightVisibleColumns = utils_1.Utils.filter(visibleColumns, function(column) {
                    return column.getPinned() === "right";
                });
                var centerVisibleColumns = utils_1.Utils.filter(visibleColumns, function(column) {
                    return column.getPinned() !== "left" && column.getPinned() !== "right";
                });
                var groupInstanceIdCreator = new groupInstanceIdCreator_1.GroupInstanceIdCreator();
                this.displayedLeftColumnTree = this.displayedGroupCreator.createDisplayedGroups(leftVisibleColumns, this.gridBalancedTree, groupInstanceIdCreator, this.displayedLeftColumnTree);
                this.displayedRightColumnTree = this.displayedGroupCreator.createDisplayedGroups(rightVisibleColumns, this.gridBalancedTree, groupInstanceIdCreator, this.displayedRightColumnTree);
                this.displayedCentreColumnTree = this.displayedGroupCreator.createDisplayedGroups(centerVisibleColumns, this.gridBalancedTree, groupInstanceIdCreator, this.displayedCentreColumnTree);
            };
            ColumnController.prototype.updateOpenClosedVisibilityInColumnGroups = function() {
                var allColumnGroups = this.getAllDisplayedColumnGroups();
                this.columnUtils.depthFirstAllColumnTreeSearch(allColumnGroups, function(child) {
                    if (child instanceof columnGroup_1.ColumnGroup) {
                        var columnGroup = child;
                        columnGroup.calculateDisplayedColumns();
                    }
                });
            };
            ColumnController.prototype.getGroupAutoColumns = function() {
                return this.groupAutoColumns;
            };
            ColumnController.prototype.createGroupAutoColumnsIfNeeded = function() {
                if (!this.autoGroupsNeedBuilding) {
                    return;
                }
                this.autoGroupsNeedBuilding = false;
                var needAutoColumns = (this.rowGroupColumns.length > 0 || this.usingTreeData) && !this.gridOptionsWrapper.isGroupSuppressAutoColumn() && !this.gridOptionsWrapper.isGroupUseEntireRow() && !this.gridOptionsWrapper.isGroupSuppressRow();
                if (needAutoColumns) {
                    this.groupAutoColumns = this.autoGroupColService.createAutoGroupColumns(this.rowGroupColumns);
                } else {
                    this.groupAutoColumns = null;
                }
            };
            ColumnController.prototype.createValueColumns = function(source) {
                this.valueColumns.forEach(function(column) {
                    return column.setValueActive(false, source);
                });
                this.valueColumns = [];
                for (var i = 0; i < this.primaryColumns.length; i++) {
                    var column = this.primaryColumns[i];
                    if (column.getColDef().aggFunc) {
                        column.setAggFunc(column.getColDef().aggFunc);
                        this.valueColumns.push(column);
                        column.setValueActive(true, source);
                    }
                }
            };
            ColumnController.prototype.getWidthOfColsInList = function(columnList) {
                var result = 0;
                for (var i = 0; i < columnList.length; i++) {
                    result += columnList[i].getActualWidth();
                }
                return result;
            };
            ColumnController.prototype.getGridBalancedTree = function() {
                return this.gridBalancedTree;
            };
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], ColumnController.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("expressionService"), __metadata("design:type", expressionService_1.ExpressionService) ], ColumnController.prototype, "expressionService", void 0);
            __decorate([ context_1.Autowired("balancedColumnTreeBuilder"), __metadata("design:type", balancedColumnTreeBuilder_1.BalancedColumnTreeBuilder) ], ColumnController.prototype, "balancedColumnTreeBuilder", void 0);
            __decorate([ context_1.Autowired("displayedGroupCreator"), __metadata("design:type", displayedGroupCreator_1.DisplayedGroupCreator) ], ColumnController.prototype, "displayedGroupCreator", void 0);
            __decorate([ context_1.Autowired("autoWidthCalculator"), __metadata("design:type", autoWidthCalculator_1.AutoWidthCalculator) ], ColumnController.prototype, "autoWidthCalculator", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], ColumnController.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("columnUtils"), __metadata("design:type", columnUtils_1.ColumnUtils) ], ColumnController.prototype, "columnUtils", void 0);
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], ColumnController.prototype, "context", void 0);
            __decorate([ context_1.Autowired("columnAnimationService"), __metadata("design:type", columnAnimationService_1.ColumnAnimationService) ], ColumnController.prototype, "columnAnimationService", void 0);
            __decorate([ context_1.Autowired("autoGroupColService"), __metadata("design:type", autoGroupColService_1.AutoGroupColService) ], ColumnController.prototype, "autoGroupColService", void 0);
            __decorate([ context_1.Optional("aggFuncService"), __metadata("design:type", Object) ], ColumnController.prototype, "aggFuncService", void 0);
            __decorate([ context_1.Optional("valueCache"), __metadata("design:type", valueCache_1.ValueCache) ], ColumnController.prototype, "valueCache", void 0);
            __decorate([ context_1.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], ColumnController.prototype, "columnApi", void 0);
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], ColumnController.prototype, "gridApi", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], ColumnController.prototype, "init", null);
            __decorate([ __param(0, context_1.Qualifier("loggerFactory")), __metadata("design:type", Function), __metadata("design:paramtypes", [ logger_1.LoggerFactory ]), __metadata("design:returntype", void 0) ], ColumnController.prototype, "setBeans", null);
            ColumnController = __decorate([ context_1.Bean("columnController") ], ColumnController);
            return ColumnController;
        }();
        exports.ColumnController = ColumnController;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var eventKeys_1 = __webpack_require__(25);
        exports.Events = eventKeys_1.Events;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var csvCreator_1 = __webpack_require__(47);
        var rowRenderer_1 = __webpack_require__(20);
        var filterManager_1 = __webpack_require__(18);
        var columnController_1 = __webpack_require__(4);
        var selectionController_1 = __webpack_require__(17);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var valueService_1 = __webpack_require__(16);
        var eventService_1 = __webpack_require__(3);
        var constants_1 = __webpack_require__(9);
        var context_1 = __webpack_require__(0);
        var gridCore_1 = __webpack_require__(42);
        var sortController_1 = __webpack_require__(24);
        var focusedCellController_1 = __webpack_require__(22);
        var gridCell_1 = __webpack_require__(23);
        var utils_1 = __webpack_require__(1);
        var cellRendererFactory_1 = __webpack_require__(55);
        var cellEditorFactory_1 = __webpack_require__(54);
        var paginationProxy_1 = __webpack_require__(29);
        var immutableService_1 = __webpack_require__(105);
        var valueCache_1 = __webpack_require__(33);
        var alignedGridsService_1 = __webpack_require__(58);
        var pinnedRowModel_1 = __webpack_require__(30);
        var animationFrameService_1 = __webpack_require__(37);
        var GridApi = function() {
            function GridApi() {
                this.detailGridInfoMap = {};
            }
            GridApi.prototype.registerGridComp = function(gridPanel) {
                this.gridPanel = gridPanel;
            };
            GridApi.prototype.registerHeaderRootComp = function(headerRootComp) {
                this.headerRootComp = headerRootComp;
            };
            GridApi.prototype.init = function() {
                switch (this.rowModel.getType()) {
                  case constants_1.Constants.ROW_MODEL_TYPE_CLIENT_SIDE:
                    this.clientSideRowModel = this.rowModel;
                    break;

                  case constants_1.Constants.ROW_MODEL_TYPE_INFINITE:
                    this.infinitePageRowModel = this.rowModel;
                    break;

                  case constants_1.Constants.ROW_MODEL_TYPE_SERVER_SIDE:
                    this.serverSideRowModel = this.rowModel;
                    break;
                }
            };
            GridApi.prototype.__getAlignedGridService = function() {
                return this.alignedGridsService;
            };
            GridApi.prototype.addDetailGridInfo = function(id, gridInfo) {
                this.detailGridInfoMap[id] = gridInfo;
            };
            GridApi.prototype.removeDetailGridInfo = function(id) {
                this.detailGridInfoMap[id] = undefined;
            };
            GridApi.prototype.getDetailGridInfo = function(id) {
                return this.detailGridInfoMap[id];
            };
            GridApi.prototype.forEachDetailGridInfo = function(callback) {
                var index = 0;
                utils_1.Utils.iterateObject(this.detailGridInfoMap, function(id, gridInfo) {
                    if (utils_1.Utils.exists(gridInfo)) {
                        callback(gridInfo, index);
                        index++;
                    }
                });
            };
            GridApi.prototype.getDataAsCsv = function(params) {
                return this.csvCreator.getDataAsCsv(params);
            };
            GridApi.prototype.exportDataAsCsv = function(params) {
                this.csvCreator.exportDataAsCsv(params);
            };
            GridApi.prototype.getDataAsExcel = function(params) {
                if (!this.excelCreator) {
                    console.warn("ag-Grid: Excel export is only available in ag-Grid Enterprise");
                }
                return this.excelCreator.getDataAsExcelXml(params);
            };
            GridApi.prototype.exportDataAsExcel = function(params) {
                if (!this.excelCreator) {
                    console.warn("ag-Grid: Excel export is only available in ag-Grid Enterprise");
                }
                this.excelCreator.exportDataAsExcel(params);
            };
            GridApi.prototype.setEnterpriseDatasource = function(datasource) {
                console.warn("ag-grid: since version 18.x, api.setEnterpriseDatasource() should be replaced with api.setServerSideDatasource()");
                this.setServerSideDatasource(datasource);
            };
            GridApi.prototype.setServerSideDatasource = function(datasource) {
                if (this.gridOptionsWrapper.isRowModelServerSide()) {
                    this.rowModel.setDatasource(datasource);
                } else {
                    console.warn("ag-Grid: you can only use an enterprise datasource when gridOptions.rowModelType is '" + constants_1.Constants.ROW_MODEL_TYPE_SERVER_SIDE + "'");
                }
            };
            GridApi.prototype.setDatasource = function(datasource) {
                if (this.gridOptionsWrapper.isRowModelInfinite()) {
                    this.rowModel.setDatasource(datasource);
                } else {
                    console.warn("ag-Grid: you can only use a datasource when gridOptions.rowModelType is '" + constants_1.Constants.ROW_MODEL_TYPE_INFINITE + "'");
                }
            };
            GridApi.prototype.setViewportDatasource = function(viewportDatasource) {
                if (this.gridOptionsWrapper.isRowModelViewport()) {
                    this.rowModel.setViewportDatasource(viewportDatasource);
                } else {
                    console.warn("ag-Grid: you can only use a viewport datasource when gridOptions.rowModelType is '" + constants_1.Constants.ROW_MODEL_TYPE_VIEWPORT + "'");
                }
            };
            GridApi.prototype.setRowData = function(rowData) {
                if (this.gridOptionsWrapper.isRowModelDefault()) {
                    if (this.gridOptionsWrapper.isDeltaRowDataMode()) {
                        var _a = this.immutableService.createTransactionForRowData(rowData), transaction = _a[0], orderIdMap = _a[1];
                        this.clientSideRowModel.updateRowData(transaction, orderIdMap);
                    } else {
                        this.selectionController.reset();
                        this.clientSideRowModel.setRowData(rowData);
                    }
                } else {
                    console.log("cannot call setRowData unless using normal row model");
                }
            };
            GridApi.prototype.setFloatingTopRowData = function(rows) {
                console.warn("ag-Grid: since v12, api.setFloatingTopRowData() is now api.setPinnedTopRowData()");
                this.setPinnedTopRowData(rows);
            };
            GridApi.prototype.setFloatingBottomRowData = function(rows) {
                console.warn("ag-Grid: since v12, api.setFloatingBottomRowData() is now api.setPinnedBottomRowData()");
                this.setPinnedBottomRowData(rows);
            };
            GridApi.prototype.getFloatingTopRowCount = function() {
                console.warn("ag-Grid: since v12, api.getFloatingTopRowCount() is now api.getPinnedTopRowCount()");
                return this.getPinnedTopRowCount();
            };
            GridApi.prototype.getFloatingBottomRowCount = function() {
                console.warn("ag-Grid: since v12, api.getFloatingBottomRowCount() is now api.getPinnedBottomRowCount()");
                return this.getPinnedBottomRowCount();
            };
            GridApi.prototype.getFloatingTopRow = function(index) {
                console.warn("ag-Grid: since v12, api.getFloatingTopRow() is now api.getPinnedTopRow()");
                return this.getPinnedTopRow(index);
            };
            GridApi.prototype.getFloatingBottomRow = function(index) {
                console.warn("ag-Grid: since v12, api.getFloatingBottomRow() is now api.getPinnedBottomRow()");
                return this.getPinnedBottomRow(index);
            };
            GridApi.prototype.setPinnedTopRowData = function(rows) {
                this.pinnedRowModel.setPinnedTopRowData(rows);
            };
            GridApi.prototype.setPinnedBottomRowData = function(rows) {
                this.pinnedRowModel.setPinnedBottomRowData(rows);
            };
            GridApi.prototype.getPinnedTopRowCount = function() {
                return this.pinnedRowModel.getPinnedTopRowCount();
            };
            GridApi.prototype.getPinnedBottomRowCount = function() {
                return this.pinnedRowModel.getPinnedBottomRowCount();
            };
            GridApi.prototype.getPinnedTopRow = function(index) {
                return this.pinnedRowModel.getPinnedTopRow(index);
            };
            GridApi.prototype.getPinnedBottomRow = function(index) {
                return this.pinnedRowModel.getPinnedBottomRow(index);
            };
            GridApi.prototype.setColumnDefs = function(colDefs, source) {
                if (source === void 0) {
                    source = "api";
                }
                this.columnController.setColumnDefs(colDefs, source);
            };
            GridApi.prototype.expireValueCache = function() {
                this.valueCache.expire();
            };
            GridApi.prototype.getVerticalPixelRange = function() {
                return this.gridPanel.getVScrollPosition();
            };
            GridApi.prototype.refreshToolPanel = function() {
                if (this.toolPanelComp) {
                    this.toolPanelComp.refresh();
                }
            };
            GridApi.prototype.refreshCells = function(params) {
                if (params === void 0) {
                    params = {};
                }
                if (Array.isArray(params)) {
                    console.warn("since ag-Grid v11.1, refreshCells() now takes parameters, please see the documentation.");
                    return;
                }
                this.rowRenderer.refreshCells(params);
            };
            GridApi.prototype.flashCells = function(params) {
                if (params === void 0) {
                    params = {};
                }
                this.rowRenderer.flashCells(params);
            };
            GridApi.prototype.redrawRows = function(params) {
                if (params === void 0) {
                    params = {};
                }
                if (params && params.rowNodes) {
                    this.rowRenderer.redrawRows(params.rowNodes);
                } else {
                    this.rowRenderer.redrawAfterModelUpdate();
                }
            };
            GridApi.prototype.timeFullRedraw = function(count) {
                if (count === void 0) {
                    count = 1;
                }
                var iterationCount = 0;
                var totalProcessing = 0;
                var totalReflow = 0;
                var that = this;
                doOneIteration();
                function doOneIteration() {
                    var start = new Date().getTime();
                    that.rowRenderer.redrawAfterModelUpdate();
                    var endProcessing = new Date().getTime();
                    setTimeout(function() {
                        var endReflow = new Date().getTime();
                        var durationProcessing = endProcessing - start;
                        var durationReflow = endReflow - endProcessing;
                        console.log("duration:  processing = " + durationProcessing + "ms, reflow = " + durationReflow + "ms");
                        iterationCount++;
                        totalProcessing += durationProcessing;
                        totalReflow += durationReflow;
                        if (iterationCount < count) {
                            setTimeout(doOneIteration, 1e3);
                        } else {
                            finish();
                        }
                    }, 0);
                }
                function finish() {
                    console.log("tests complete. iteration count = " + iterationCount);
                    console.log("average processing = " + totalProcessing / iterationCount + "ms");
                    console.log("average reflow = " + totalReflow / iterationCount + "ms");
                }
            };
            GridApi.prototype.refreshView = function() {
                console.warn("ag-Grid: since v11.1, refreshView() is deprecated, please call refreshCells() or redrawRows() instead");
                this.redrawRows();
            };
            GridApi.prototype.refreshRows = function(rowNodes) {
                console.warn("since ag-Grid v11.1, refreshRows() is deprecated, please use refreshCells({rowNodes: rows}) or redrawRows({rowNodes: rows}) instead");
                this.refreshCells({
                    rowNodes: rowNodes
                });
            };
            GridApi.prototype.rowDataChanged = function(rows) {
                console.log("ag-Grid: rowDataChanged is deprecated, either call refreshView() to refresh everything, or call rowNode.setRowData(newData) to set value on a particular node");
                this.redrawRows();
            };
            GridApi.prototype.softRefreshView = function() {
                console.error("ag-Grid: since v16, softRefreshView() is no longer supported. Please check the documentation on how to refresh.");
            };
            GridApi.prototype.refreshGroupRows = function() {
                console.warn("ag-Grid: since v11.1, refreshGroupRows() is no longer supported, call refreshCells() instead. " + "Because refreshCells() now does dirty checking, it will only refresh cells that have changed, so it should " + "not be necessary to only refresh the group rows.");
                this.refreshCells();
            };
            GridApi.prototype.setFunctionsReadOnly = function(readOnly) {
                this.gridOptionsWrapper.setProperty("functionsReadOnly", readOnly);
            };
            GridApi.prototype.refreshHeader = function() {
                this.headerRootComp.refreshHeader();
                this.gridPanel.setBodyAndHeaderHeights();
            };
            GridApi.prototype.isAnyFilterPresent = function() {
                return this.filterManager.isAnyFilterPresent();
            };
            GridApi.prototype.isAdvancedFilterPresent = function() {
                return this.filterManager.isAdvancedFilterPresent();
            };
            GridApi.prototype.isQuickFilterPresent = function() {
                return this.filterManager.isQuickFilterPresent();
            };
            GridApi.prototype.getModel = function() {
                return this.rowModel;
            };
            GridApi.prototype.onGroupExpandedOrCollapsed = function(deprecated_refreshFromIndex) {
                if (utils_1.Utils.missing(this.clientSideRowModel)) {
                    console.log("ag-Grid: cannot call onGroupExpandedOrCollapsed unless using normal row model");
                }
                if (utils_1.Utils.exists(deprecated_refreshFromIndex)) {
                    console.log("ag-Grid: api.onGroupExpandedOrCollapsed - refreshFromIndex parameter is no longer used, the grid will refresh all rows");
                }
                this.clientSideRowModel.refreshModel({
                    step: constants_1.Constants.STEP_MAP
                });
            };
            GridApi.prototype.refreshInMemoryRowModel = function(step) {
                console.warn("ag-grid: since version 18.x, api.refreshInMemoryRowModel() should be replaced with api.refreshClientSideRowModel()");
                this.refreshClientSideRowModel(step);
            };
            GridApi.prototype.refreshClientSideRowModel = function(step) {
                if (utils_1.Utils.missing(this.clientSideRowModel)) {
                    console.log("cannot call refreshClientSideRowModel unless using normal row model");
                }
                var paramsStep = constants_1.Constants.STEP_EVERYTHING;
                var stepsMapped = {
                    group: constants_1.Constants.STEP_EVERYTHING,
                    filter: constants_1.Constants.STEP_FILTER,
                    map: constants_1.Constants.STEP_MAP,
                    aggregate: constants_1.Constants.STEP_AGGREGATE,
                    sort: constants_1.Constants.STEP_SORT,
                    pivot: constants_1.Constants.STEP_PIVOT
                };
                if (utils_1.Utils.exists(step)) {
                    paramsStep = stepsMapped[step];
                }
                if (utils_1.Utils.missing(paramsStep)) {
                    console.error("ag-Grid: invalid step " + step + ", available steps are " + Object.keys(stepsMapped).join(", "));
                    return;
                }
                var modelParams = {
                    step: paramsStep,
                    keepRenderedRows: true,
                    animate: true,
                    keepEditingRows: true
                };
                this.clientSideRowModel.refreshModel(modelParams);
            };
            GridApi.prototype.isAnimationFrameQueueEmpty = function() {
                return this.animationFrameService.isQueueEmpty();
            };
            GridApi.prototype.getRowNode = function(id) {
                return this.rowModel.getRowNode(id);
            };
            GridApi.prototype.expandAll = function() {
                if (utils_1.Utils.missing(this.clientSideRowModel)) {
                    console.warn("ag-Grid: cannot call expandAll unless using normal row model");
                    return;
                }
                this.clientSideRowModel.expandOrCollapseAll(true);
            };
            GridApi.prototype.collapseAll = function() {
                if (utils_1.Utils.missing(this.clientSideRowModel)) {
                    console.warn("ag-Grid: cannot call collapseAll unless using normal row model");
                    return;
                }
                this.clientSideRowModel.expandOrCollapseAll(false);
            };
            GridApi.prototype.addVirtualRowListener = function(eventName, rowIndex, callback) {
                if (typeof eventName !== "string") {
                    console.log("ag-Grid: addVirtualRowListener is deprecated, please use addRenderedRowListener.");
                }
                this.addRenderedRowListener(eventName, rowIndex, callback);
            };
            GridApi.prototype.addRenderedRowListener = function(eventName, rowIndex, callback) {
                if (eventName === "virtualRowSelected") {
                    console.log("ag-Grid: event virtualRowSelected is deprecated, to register for individual row " + "selection events, add a listener directly to the row node.");
                }
                this.rowRenderer.addRenderedRowListener(eventName, rowIndex, callback);
            };
            GridApi.prototype.setQuickFilter = function(newFilter) {
                this.filterManager.setQuickFilter(newFilter);
            };
            GridApi.prototype.selectIndex = function(index, tryMulti, suppressEvents) {
                console.log("ag-Grid: do not use api for selection, call node.setSelected(value) instead");
                if (suppressEvents) {
                    console.log("ag-Grid: suppressEvents is no longer supported, stop listening for the event if you no longer want it");
                }
                this.selectionController.selectIndex(index, tryMulti);
            };
            GridApi.prototype.deselectIndex = function(index, suppressEvents) {
                if (suppressEvents === void 0) {
                    suppressEvents = false;
                }
                console.log("ag-Grid: do not use api for selection, call node.setSelected(value) instead");
                if (suppressEvents) {
                    console.log("ag-Grid: suppressEvents is no longer supported, stop listening for the event if you no longer want it");
                }
                this.selectionController.deselectIndex(index);
            };
            GridApi.prototype.selectNode = function(node, tryMulti, suppressEvents) {
                if (tryMulti === void 0) {
                    tryMulti = false;
                }
                if (suppressEvents === void 0) {
                    suppressEvents = false;
                }
                console.log("ag-Grid: API for selection is deprecated, call node.setSelected(value) instead");
                if (suppressEvents) {
                    console.log("ag-Grid: suppressEvents is no longer supported, stop listening for the event if you no longer want it");
                }
                node.setSelectedParams({
                    newValue: true,
                    clearSelection: !tryMulti
                });
            };
            GridApi.prototype.deselectNode = function(node, suppressEvents) {
                if (suppressEvents === void 0) {
                    suppressEvents = false;
                }
                console.log("ag-Grid: API for selection is deprecated, call node.setSelected(value) instead");
                if (suppressEvents) {
                    console.log("ag-Grid: suppressEvents is no longer supported, stop listening for the event if you no longer want it");
                }
                node.setSelectedParams({
                    newValue: false
                });
            };
            GridApi.prototype.selectAll = function() {
                this.selectionController.selectAllRowNodes();
            };
            GridApi.prototype.deselectAll = function() {
                this.selectionController.deselectAllRowNodes();
            };
            GridApi.prototype.selectAllFiltered = function() {
                this.selectionController.selectAllRowNodes(true);
            };
            GridApi.prototype.deselectAllFiltered = function() {
                this.selectionController.deselectAllRowNodes(true);
            };
            GridApi.prototype.recomputeAggregates = function() {
                if (utils_1.Utils.missing(this.clientSideRowModel)) {
                    console.warn("cannot call recomputeAggregates unless using normal row model");
                }
                console.warn("recomputeAggregates is deprecated, please call api.refreshClientSideRowModel('aggregate') instead");
                this.clientSideRowModel.refreshModel({
                    step: constants_1.Constants.STEP_AGGREGATE
                });
            };
            GridApi.prototype.sizeColumnsToFit = function() {
                this.gridPanel.sizeColumnsToFit();
            };
            GridApi.prototype.showLoadingOverlay = function() {
                this.gridPanel.showLoadingOverlay();
            };
            GridApi.prototype.showNoRowsOverlay = function() {
                this.gridPanel.showNoRowsOverlay();
            };
            GridApi.prototype.hideOverlay = function() {
                this.gridPanel.hideOverlay();
            };
            GridApi.prototype.isNodeSelected = function(node) {
                console.log("ag-Grid: no need to call api.isNodeSelected(), just call node.isSelected() instead");
                return node.isSelected();
            };
            GridApi.prototype.getSelectedNodesById = function() {
                console.error("ag-Grid: since version 3.4, getSelectedNodesById no longer exists, use getSelectedNodes() instead");
                return null;
            };
            GridApi.prototype.getSelectedNodes = function() {
                return this.selectionController.getSelectedNodes();
            };
            GridApi.prototype.getSelectedRows = function() {
                return this.selectionController.getSelectedRows();
            };
            GridApi.prototype.getBestCostNodeSelection = function() {
                return this.selectionController.getBestCostNodeSelection();
            };
            GridApi.prototype.getRenderedNodes = function() {
                return this.rowRenderer.getRenderedNodes();
            };
            GridApi.prototype.ensureColIndexVisible = function(index) {
                console.warn("ag-Grid: ensureColIndexVisible(index) no longer supported, use ensureColumnVisible(colKey) instead.");
            };
            GridApi.prototype.ensureColumnVisible = function(key) {
                this.gridPanel.ensureColumnVisible(key);
            };
            GridApi.prototype.ensureIndexVisible = function(index, position) {
                this.gridPanel.ensureIndexVisible(index, position);
            };
            GridApi.prototype.ensureNodeVisible = function(comparator, position) {
                this.gridCore.ensureNodeVisible(comparator, position);
            };
            GridApi.prototype.forEachLeafNode = function(callback) {
                if (utils_1.Utils.missing(this.clientSideRowModel)) {
                    console.log("cannot call forEachNode unless using normal row model");
                }
                this.clientSideRowModel.forEachLeafNode(callback);
            };
            GridApi.prototype.forEachNode = function(callback) {
                this.rowModel.forEachNode(callback);
            };
            GridApi.prototype.forEachNodeAfterFilter = function(callback) {
                if (utils_1.Utils.missing(this.clientSideRowModel)) {
                    console.log("cannot call forEachNodeAfterFilter unless using normal row model");
                }
                this.clientSideRowModel.forEachNodeAfterFilter(callback);
            };
            GridApi.prototype.forEachNodeAfterFilterAndSort = function(callback) {
                if (utils_1.Utils.missing(this.clientSideRowModel)) {
                    console.log("cannot call forEachNodeAfterFilterAndSort unless using normal row model");
                }
                this.clientSideRowModel.forEachNodeAfterFilterAndSort(callback);
            };
            GridApi.prototype.getFilterApiForColDef = function(colDef) {
                console.warn("ag-grid API method getFilterApiForColDef deprecated, use getFilterApi instead");
                return this.getFilterInstance(colDef);
            };
            GridApi.prototype.getFilterInstance = function(key) {
                var column = this.columnController.getPrimaryColumn(key);
                if (column) {
                    return this.filterManager.getFilterComponent(column).resolveNow(null, function(filterComp) {
                        return filterComp;
                    });
                }
            };
            GridApi.prototype.getFilterApi = function(key) {
                console.warn("ag-Grid: getFilterApi is deprecated, use getFilterInstance instead");
                return this.getFilterInstance(key);
            };
            GridApi.prototype.destroyFilter = function(key) {
                var column = this.columnController.getPrimaryColumn(key);
                if (column) {
                    return this.filterManager.destroyFilter(column, "filterDestroyed");
                }
            };
            GridApi.prototype.getColumnDef = function(key) {
                var column = this.columnController.getPrimaryColumn(key);
                if (column) {
                    return column.getColDef();
                } else {
                    return null;
                }
            };
            GridApi.prototype.onFilterChanged = function() {
                this.filterManager.onFilterChanged();
            };
            GridApi.prototype.onSortChanged = function() {
                this.sortController.onSortChanged();
            };
            GridApi.prototype.setSortModel = function(sortModel, source) {
                if (source === void 0) {
                    source = "api";
                }
                this.sortController.setSortModel(sortModel, source);
            };
            GridApi.prototype.getSortModel = function() {
                return this.sortController.getSortModel();
            };
            GridApi.prototype.setFilterModel = function(model) {
                this.filterManager.setFilterModel(model);
            };
            GridApi.prototype.getFilterModel = function() {
                return this.filterManager.getFilterModel();
            };
            GridApi.prototype.getFocusedCell = function() {
                return this.focusedCellController.getFocusedCell();
            };
            GridApi.prototype.clearFocusedCell = function() {
                return this.focusedCellController.clearFocusedCell();
            };
            GridApi.prototype.setFocusedCell = function(rowIndex, colKey, floating) {
                this.focusedCellController.setFocusedCell(rowIndex, colKey, floating, true);
            };
            GridApi.prototype.setSuppressRowDrag = function(value) {
                this.gridOptionsWrapper.setProperty(gridOptionsWrapper_1.GridOptionsWrapper.PROP_SUPPRESS_ROW_DRAG, value);
            };
            GridApi.prototype.setHeaderHeight = function(headerHeight) {
                this.gridOptionsWrapper.setProperty(gridOptionsWrapper_1.GridOptionsWrapper.PROP_HEADER_HEIGHT, headerHeight);
                this.doLayout();
            };
            GridApi.prototype.setGridAutoHeight = function(gridAutoHeight) {
                this.gridOptionsWrapper.setProperty(gridOptionsWrapper_1.GridOptionsWrapper.PROP_GRID_AUTO_HEIGHT, gridAutoHeight);
            };
            GridApi.prototype.getPreferredWidth = function() {
                return this.gridCore.getPreferredWidth();
            };
            GridApi.prototype.setGroupHeaderHeight = function(headerHeight) {
                this.gridOptionsWrapper.setProperty(gridOptionsWrapper_1.GridOptionsWrapper.PROP_GROUP_HEADER_HEIGHT, headerHeight);
                this.doLayout();
            };
            GridApi.prototype.setFloatingFiltersHeight = function(headerHeight) {
                this.gridOptionsWrapper.setProperty(gridOptionsWrapper_1.GridOptionsWrapper.PROP_FLOATING_FILTERS_HEIGHT, headerHeight);
                this.doLayout();
            };
            GridApi.prototype.setPivotGroupHeaderHeight = function(headerHeight) {
                this.gridOptionsWrapper.setProperty(gridOptionsWrapper_1.GridOptionsWrapper.PROP_PIVOT_GROUP_HEADER_HEIGHT, headerHeight);
                this.doLayout();
            };
            GridApi.prototype.setPivotHeaderHeight = function(headerHeight) {
                this.gridOptionsWrapper.setProperty(gridOptionsWrapper_1.GridOptionsWrapper.PROP_PIVOT_HEADER_HEIGHT, headerHeight);
                this.doLayout();
            };
            GridApi.prototype.showToolPanel = function(show) {
                this.gridCore.showToolPanel(show);
            };
            GridApi.prototype.setSuppressClipboardPaste = function(value) {
                this.gridOptionsWrapper.setProperty(gridOptionsWrapper_1.GridOptionsWrapper.PROP_SUPPRESS_CLIPBOARD_PASTE, value);
            };
            GridApi.prototype.isToolPanelShowing = function() {
                return this.gridCore.isToolPanelShowing();
            };
            GridApi.prototype.doLayout = function() {
                this.gridPanel.checkViewportAndScrolls();
            };
            GridApi.prototype.resetRowHeights = function() {
                if (utils_1.Utils.exists(this.clientSideRowModel)) {
                    this.clientSideRowModel.resetRowHeights();
                }
            };
            GridApi.prototype.setGroupRemoveSingleChildren = function(value) {
                this.gridOptionsWrapper.setProperty(gridOptionsWrapper_1.GridOptionsWrapper.PROP_GROUP_REMOVE_SINGLE_CHILDREN, value);
            };
            GridApi.prototype.setGroupRemoveLowestSingleChildren = function(value) {
                this.gridOptionsWrapper.setProperty(gridOptionsWrapper_1.GridOptionsWrapper.PROP_GROUP_REMOVE_LOWEST_SINGLE_CHILDREN, value);
            };
            GridApi.prototype.onRowHeightChanged = function() {
                if (utils_1.Utils.exists(this.clientSideRowModel)) {
                    this.clientSideRowModel.onRowHeightChanged();
                }
            };
            GridApi.prototype.getValue = function(colKey, rowNode) {
                var column = this.columnController.getPrimaryColumn(colKey);
                if (utils_1.Utils.missing(column)) {
                    column = this.columnController.getGridColumn(colKey);
                }
                if (utils_1.Utils.missing(column)) {
                    return null;
                } else {
                    return this.valueService.getValue(column, rowNode);
                }
            };
            GridApi.prototype.addEventListener = function(eventType, listener) {
                var async = this.gridOptionsWrapper.useAsyncEvents();
                this.eventService.addEventListener(eventType, listener, async);
            };
            GridApi.prototype.addGlobalListener = function(listener) {
                var async = this.gridOptionsWrapper.useAsyncEvents();
                this.eventService.addGlobalListener(listener, async);
            };
            GridApi.prototype.removeEventListener = function(eventType, listener) {
                var async = this.gridOptionsWrapper.useAsyncEvents();
                this.eventService.removeEventListener(eventType, listener, async);
            };
            GridApi.prototype.removeGlobalListener = function(listener) {
                var async = this.gridOptionsWrapper.useAsyncEvents();
                this.eventService.removeGlobalListener(listener, async);
            };
            GridApi.prototype.dispatchEvent = function(event) {
                this.eventService.dispatchEvent(event);
            };
            GridApi.prototype.destroy = function() {
                this.context.destroy();
            };
            GridApi.prototype.resetQuickFilter = function() {
                this.rowModel.forEachNode(function(node) {
                    return node.quickFilterAggregateText = null;
                });
            };
            GridApi.prototype.getRangeSelections = function() {
                if (this.rangeController) {
                    return this.rangeController.getCellRanges();
                } else {
                    console.warn("ag-Grid: cell range selection is only available in ag-Grid Enterprise");
                    return null;
                }
            };
            GridApi.prototype.camelCaseToHumanReadable = function(camelCase) {
                return utils_1.Utils.camelCaseToHumanText(camelCase);
            };
            GridApi.prototype.addRangeSelection = function(rangeSelection) {
                if (!this.rangeController) {
                    console.warn("ag-Grid: cell range selection is only available in ag-Grid Enterprise");
                }
                this.rangeController.addRange(rangeSelection);
            };
            GridApi.prototype.clearRangeSelection = function() {
                if (!this.rangeController) {
                    console.warn("ag-Grid: cell range selection is only available in ag-Grid Enterprise");
                }
                this.rangeController.clearSelection();
            };
            GridApi.prototype.copySelectedRowsToClipboard = function(includeHeader, columnKeys) {
                if (!this.clipboardService) {
                    console.warn("ag-Grid: clipboard is only available in ag-Grid Enterprise");
                }
                this.clipboardService.copySelectedRowsToClipboard(includeHeader, columnKeys);
            };
            GridApi.prototype.copySelectedRangeToClipboard = function(includeHeader) {
                if (!this.clipboardService) {
                    console.warn("ag-Grid: clipboard is only available in ag-Grid Enterprise");
                }
                this.clipboardService.copySelectedRangeToClipboard(includeHeader);
            };
            GridApi.prototype.copySelectedRangeDown = function() {
                if (!this.clipboardService) {
                    console.warn("ag-Grid: clipboard is only available in ag-Grid Enterprise");
                }
                this.clipboardService.copyRangeDown();
            };
            GridApi.prototype.showColumnMenuAfterButtonClick = function(colKey, buttonElement) {
                var column = this.columnController.getPrimaryColumn(colKey);
                this.menuFactory.showMenuAfterButtonClick(column, buttonElement);
            };
            GridApi.prototype.showColumnMenuAfterMouseClick = function(colKey, mouseEvent) {
                var column = this.columnController.getPrimaryColumn(colKey);
                this.menuFactory.showMenuAfterMouseEvent(column, mouseEvent);
            };
            GridApi.prototype.hidePopupMenu = function() {
                if (this.contextMenuFactory) {
                    this.contextMenuFactory.hideActiveMenu();
                }
                this.menuFactory.hideActiveMenu();
            };
            GridApi.prototype.setPopupParent = function(ePopupParent) {
                this.gridOptionsWrapper.setProperty(gridOptionsWrapper_1.GridOptionsWrapper.PROP_POPUP_PARENT, ePopupParent);
            };
            GridApi.prototype.tabToNextCell = function() {
                return this.rowRenderer.tabToNextCell(false);
            };
            GridApi.prototype.tabToPreviousCell = function() {
                return this.rowRenderer.tabToNextCell(true);
            };
            GridApi.prototype.getCellRendererInstances = function(params) {
                if (params === void 0) {
                    params = {};
                }
                return this.rowRenderer.getCellRendererInstances(params);
            };
            GridApi.prototype.getCellEditorInstances = function(params) {
                if (params === void 0) {
                    params = {};
                }
                return this.rowRenderer.getCellEditorInstances(params);
            };
            GridApi.prototype.getEditingCells = function() {
                return this.rowRenderer.getEditingCells();
            };
            GridApi.prototype.stopEditing = function(cancel) {
                if (cancel === void 0) {
                    cancel = false;
                }
                this.rowRenderer.stopEditing(cancel);
            };
            GridApi.prototype.startEditingCell = function(params) {
                var column = this.columnController.getGridColumn(params.colKey);
                if (!column) {
                    console.warn("ag-Grid: no column found for " + params.colKey);
                    return;
                }
                var gridCellDef = {
                    rowIndex: params.rowIndex,
                    floating: params.rowPinned,
                    column: column
                };
                var gridCell = new gridCell_1.GridCell(gridCellDef);
                var notPinned = utils_1.Utils.missing(params.rowPinned);
                if (notPinned) {
                    this.gridPanel.ensureIndexVisible(params.rowIndex);
                }
                this.rowRenderer.startEditingCell(gridCell, params.keyPress, params.charPress);
            };
            GridApi.prototype.addAggFunc = function(key, aggFunc) {
                if (this.aggFuncService) {
                    this.aggFuncService.addAggFunc(key, aggFunc);
                }
            };
            GridApi.prototype.addAggFuncs = function(aggFuncs) {
                if (this.aggFuncService) {
                    this.aggFuncService.addAggFuncs(aggFuncs);
                }
            };
            GridApi.prototype.clearAggFuncs = function() {
                if (this.aggFuncService) {
                    this.aggFuncService.clear();
                }
            };
            GridApi.prototype.updateRowData = function(rowDataTransaction) {
                var res = null;
                if (this.clientSideRowModel) {
                    res = this.clientSideRowModel.updateRowData(rowDataTransaction);
                } else if (this.infinitePageRowModel) {
                    this.infinitePageRowModel.updateRowData(rowDataTransaction);
                } else {
                    console.error("ag-Grid: updateRowData() only works with ClientSideRowModel and InfiniteRowModel.");
                }
                if (!this.gridOptionsWrapper.isSuppressChangeDetection()) {
                    this.rowRenderer.refreshCells();
                }
                return res;
            };
            GridApi.prototype.batchUpdateRowData = function(rowDataTransaction, callback) {
                if (!this.clientSideRowModel) {
                    console.error("ag-Grid: api.batchUpdateRowData() only works with ClientSideRowModel.");
                    return;
                }
                this.clientSideRowModel.batchUpdateRowData(rowDataTransaction, callback);
            };
            GridApi.prototype.insertItemsAtIndex = function(index, items, skipRefresh) {
                if (skipRefresh === void 0) {
                    skipRefresh = false;
                }
                console.warn("ag-Grid: insertItemsAtIndex() is deprecated, use updateRowData(transaction) instead.");
                this.updateRowData({
                    add: items,
                    addIndex: index,
                    update: null,
                    remove: null
                });
            };
            GridApi.prototype.removeItems = function(rowNodes, skipRefresh) {
                if (skipRefresh === void 0) {
                    skipRefresh = false;
                }
                console.warn("ag-Grid: removeItems() is deprecated, use updateRowData(transaction) instead.");
                var dataToRemove = rowNodes.map(function(rowNode) {
                    return rowNode.data;
                });
                this.updateRowData({
                    add: null,
                    addIndex: null,
                    update: null,
                    remove: dataToRemove
                });
            };
            GridApi.prototype.addItems = function(items, skipRefresh) {
                if (skipRefresh === void 0) {
                    skipRefresh = false;
                }
                console.warn("ag-Grid: addItems() is deprecated, use updateRowData(transaction) instead.");
                this.updateRowData({
                    add: items,
                    addIndex: null,
                    update: null,
                    remove: null
                });
            };
            GridApi.prototype.refreshVirtualPageCache = function() {
                console.warn("ag-Grid: refreshVirtualPageCache() is now called refreshInfiniteCache(), please call refreshInfiniteCache() instead");
                this.refreshInfiniteCache();
            };
            GridApi.prototype.refreshInfinitePageCache = function() {
                console.warn("ag-Grid: refreshInfinitePageCache() is now called refreshInfiniteCache(), please call refreshInfiniteCache() instead");
                this.refreshInfiniteCache();
            };
            GridApi.prototype.refreshInfiniteCache = function() {
                if (this.infinitePageRowModel) {
                    this.infinitePageRowModel.refreshCache();
                } else {
                    console.warn("ag-Grid: api.refreshInfiniteCache is only available when rowModelType='infinite'.");
                }
            };
            GridApi.prototype.purgeVirtualPageCache = function() {
                console.warn("ag-Grid: purgeVirtualPageCache() is now called purgeInfiniteCache(), please call purgeInfiniteCache() instead");
                this.purgeInfinitePageCache();
            };
            GridApi.prototype.purgeInfinitePageCache = function() {
                console.warn("ag-Grid: purgeInfinitePageCache() is now called purgeInfiniteCache(), please call purgeInfiniteCache() instead");
                this.purgeInfiniteCache();
            };
            GridApi.prototype.purgeInfiniteCache = function() {
                if (this.infinitePageRowModel) {
                    this.infinitePageRowModel.purgeCache();
                } else {
                    console.warn("ag-Grid: api.purgeInfiniteCache is only available when rowModelType='infinite'.");
                }
            };
            GridApi.prototype.purgeEnterpriseCache = function(route) {
                console.warn("ag-grid: since version 18.x, api.purgeEnterpriseCache() should be replaced with api.purgeServerSideCache()");
                this.purgeServerSideCache(route);
            };
            GridApi.prototype.purgeServerSideCache = function(route) {
                if (this.serverSideRowModel) {
                    this.serverSideRowModel.purgeCache(route);
                } else {
                    console.warn("ag-Grid: api.purgeServerSideCache is only available when rowModelType='enterprise'.");
                }
            };
            GridApi.prototype.getVirtualRowCount = function() {
                console.warn("ag-Grid: getVirtualRowCount() is now called getInfiniteRowCount(), please call getInfiniteRowCount() instead");
                return this.getInfiniteRowCount();
            };
            GridApi.prototype.getInfiniteRowCount = function() {
                if (this.infinitePageRowModel) {
                    return this.infinitePageRowModel.getVirtualRowCount();
                } else {
                    console.warn("ag-Grid: api.getVirtualRowCount is only available when rowModelType='virtual'.");
                }
            };
            GridApi.prototype.isMaxRowFound = function() {
                if (this.infinitePageRowModel) {
                    return this.infinitePageRowModel.isMaxRowFound();
                } else {
                    console.warn("ag-Grid: api.isMaxRowFound is only available when rowModelType='virtual'.");
                }
            };
            GridApi.prototype.setVirtualRowCount = function(rowCount, maxRowFound) {
                console.warn("ag-Grid: setVirtualRowCount() is now called setInfiniteRowCount(), please call setInfiniteRowCount() instead");
                this.setInfiniteRowCount(rowCount, maxRowFound);
            };
            GridApi.prototype.setInfiniteRowCount = function(rowCount, maxRowFound) {
                if (this.infinitePageRowModel) {
                    this.infinitePageRowModel.setVirtualRowCount(rowCount, maxRowFound);
                } else {
                    console.warn("ag-Grid: api.setVirtualRowCount is only available when rowModelType='virtual'.");
                }
            };
            GridApi.prototype.getVirtualPageState = function() {
                console.warn("ag-Grid: getVirtualPageState() is now called getCacheBlockState(), please call getCacheBlockState() instead");
                return this.getCacheBlockState();
            };
            GridApi.prototype.getInfinitePageState = function() {
                console.warn("ag-Grid: getInfinitePageState() is now called getCacheBlockState(), please call getCacheBlockState() instead");
                return this.getCacheBlockState();
            };
            GridApi.prototype.getCacheBlockState = function() {
                if (this.infinitePageRowModel) {
                    return this.infinitePageRowModel.getBlockState();
                } else if (this.serverSideRowModel) {
                    return this.serverSideRowModel.getBlockState();
                } else {
                    console.warn("ag-Grid: api.getCacheBlockState() is only available when rowModelType='infinite' or rowModelType='serverSide'.");
                }
            };
            GridApi.prototype.checkGridSize = function() {
                this.gridPanel.setBodyAndHeaderHeights();
            };
            GridApi.prototype.getFirstRenderedRow = function() {
                console.log("in ag-Grid v12, getFirstRenderedRow() was renamed to getFirstDisplayedRow()");
                return this.getFirstDisplayedRow();
            };
            GridApi.prototype.getFirstDisplayedRow = function() {
                return this.rowRenderer.getFirstVirtualRenderedRow();
            };
            GridApi.prototype.getLastRenderedRow = function() {
                console.log("in ag-Grid v12, getLastRenderedRow() was renamed to getLastDisplayedRow()");
                return this.getLastDisplayedRow();
            };
            GridApi.prototype.getLastDisplayedRow = function() {
                return this.rowRenderer.getLastVirtualRenderedRow();
            };
            GridApi.prototype.getDisplayedRowAtIndex = function(index) {
                return this.rowModel.getRow(index);
            };
            GridApi.prototype.getDisplayedRowCount = function() {
                return this.rowModel.getRowCount();
            };
            GridApi.prototype.paginationIsLastPageFound = function() {
                return this.paginationProxy.isLastPageFound();
            };
            GridApi.prototype.paginationGetPageSize = function() {
                return this.paginationProxy.getPageSize();
            };
            GridApi.prototype.paginationSetPageSize = function(size) {
                this.gridOptionsWrapper.setProperty("paginationPageSize", size);
            };
            GridApi.prototype.paginationGetCurrentPage = function() {
                return this.paginationProxy.getCurrentPage();
            };
            GridApi.prototype.paginationGetTotalPages = function() {
                return this.paginationProxy.getTotalPages();
            };
            GridApi.prototype.paginationGetRowCount = function() {
                return this.paginationProxy.getTotalRowCount();
            };
            GridApi.prototype.paginationGoToNextPage = function() {
                this.paginationProxy.goToNextPage();
            };
            GridApi.prototype.paginationGoToPreviousPage = function() {
                this.paginationProxy.goToPreviousPage();
            };
            GridApi.prototype.paginationGoToFirstPage = function() {
                this.paginationProxy.goToFirstPage();
            };
            GridApi.prototype.paginationGoToLastPage = function() {
                this.paginationProxy.goToLastPage();
            };
            GridApi.prototype.paginationGoToPage = function(page) {
                this.paginationProxy.goToPage(page);
            };
            __decorate([ context_1.Autowired("immutableService"), __metadata("design:type", immutableService_1.ImmutableService) ], GridApi.prototype, "immutableService", void 0);
            __decorate([ context_1.Autowired("csvCreator"), __metadata("design:type", csvCreator_1.CsvCreator) ], GridApi.prototype, "csvCreator", void 0);
            __decorate([ context_1.Optional("excelCreator"), __metadata("design:type", Object) ], GridApi.prototype, "excelCreator", void 0);
            __decorate([ context_1.Autowired("gridCore"), __metadata("design:type", gridCore_1.GridCore) ], GridApi.prototype, "gridCore", void 0);
            __decorate([ context_1.Autowired("rowRenderer"), __metadata("design:type", rowRenderer_1.RowRenderer) ], GridApi.prototype, "rowRenderer", void 0);
            __decorate([ context_1.Autowired("filterManager"), __metadata("design:type", filterManager_1.FilterManager) ], GridApi.prototype, "filterManager", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], GridApi.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("selectionController"), __metadata("design:type", selectionController_1.SelectionController) ], GridApi.prototype, "selectionController", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], GridApi.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("valueService"), __metadata("design:type", valueService_1.ValueService) ], GridApi.prototype, "valueService", void 0);
            __decorate([ context_1.Autowired("alignedGridsService"), __metadata("design:type", alignedGridsService_1.AlignedGridsService) ], GridApi.prototype, "alignedGridsService", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], GridApi.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("pinnedRowModel"), __metadata("design:type", pinnedRowModel_1.PinnedRowModel) ], GridApi.prototype, "pinnedRowModel", void 0);
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], GridApi.prototype, "context", void 0);
            __decorate([ context_1.Autowired("rowModel"), __metadata("design:type", Object) ], GridApi.prototype, "rowModel", void 0);
            __decorate([ context_1.Autowired("sortController"), __metadata("design:type", sortController_1.SortController) ], GridApi.prototype, "sortController", void 0);
            __decorate([ context_1.Autowired("paginationProxy"), __metadata("design:type", paginationProxy_1.PaginationProxy) ], GridApi.prototype, "paginationProxy", void 0);
            __decorate([ context_1.Autowired("focusedCellController"), __metadata("design:type", focusedCellController_1.FocusedCellController) ], GridApi.prototype, "focusedCellController", void 0);
            __decorate([ context_1.Optional("rangeController"), __metadata("design:type", Object) ], GridApi.prototype, "rangeController", void 0);
            __decorate([ context_1.Optional("clipboardService"), __metadata("design:type", Object) ], GridApi.prototype, "clipboardService", void 0);
            __decorate([ context_1.Optional("aggFuncService"), __metadata("design:type", Object) ], GridApi.prototype, "aggFuncService", void 0);
            __decorate([ context_1.Autowired("menuFactory"), __metadata("design:type", Object) ], GridApi.prototype, "menuFactory", void 0);
            __decorate([ context_1.Optional("contextMenuFactory"), __metadata("design:type", Object) ], GridApi.prototype, "contextMenuFactory", void 0);
            __decorate([ context_1.Autowired("cellRendererFactory"), __metadata("design:type", cellRendererFactory_1.CellRendererFactory) ], GridApi.prototype, "cellRendererFactory", void 0);
            __decorate([ context_1.Autowired("cellEditorFactory"), __metadata("design:type", cellEditorFactory_1.CellEditorFactory) ], GridApi.prototype, "cellEditorFactory", void 0);
            __decorate([ context_1.Autowired("valueCache"), __metadata("design:type", valueCache_1.ValueCache) ], GridApi.prototype, "valueCache", void 0);
            __decorate([ context_1.Optional("toolPanelComp"), __metadata("design:type", Object) ], GridApi.prototype, "toolPanelComp", void 0);
            __decorate([ context_1.Autowired("animationFrameService"), __metadata("design:type", animationFrameService_1.AnimationFrameService) ], GridApi.prototype, "animationFrameService", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], GridApi.prototype, "init", null);
            GridApi = __decorate([ context_1.Bean("gridApi") ], GridApi);
            return GridApi;
        }();
        exports.GridApi = GridApi;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var columnController_1 = __webpack_require__(4);
        var context_1 = __webpack_require__(0);
        var ColumnApi = function() {
            function ColumnApi() {}
            ColumnApi.prototype.sizeColumnsToFit = function(gridWidth) {
                this.columnController.sizeColumnsToFit(gridWidth, "api");
            };
            ColumnApi.prototype.setColumnGroupOpened = function(group, newValue) {
                this.columnController.setColumnGroupOpened(group, newValue, "api");
            };
            ColumnApi.prototype.getColumnGroup = function(name, instanceId) {
                return this.columnController.getColumnGroup(name, instanceId);
            };
            ColumnApi.prototype.getOriginalColumnGroup = function(name) {
                return this.columnController.getOriginalColumnGroup(name);
            };
            ColumnApi.prototype.getDisplayNameForColumn = function(column, location) {
                return this.columnController.getDisplayNameForColumn(column, location);
            };
            ColumnApi.prototype.getDisplayNameForColumnGroup = function(columnGroup, location) {
                return this.columnController.getDisplayNameForColumnGroup(columnGroup, location);
            };
            ColumnApi.prototype.getColumn = function(key) {
                return this.columnController.getPrimaryColumn(key);
            };
            ColumnApi.prototype.setColumnState = function(columnState) {
                return this.columnController.setColumnState(columnState, "api");
            };
            ColumnApi.prototype.getColumnState = function() {
                return this.columnController.getColumnState();
            };
            ColumnApi.prototype.resetColumnState = function() {
                this.columnController.resetColumnState("api");
            };
            ColumnApi.prototype.getColumnGroupState = function() {
                return this.columnController.getColumnGroupState();
            };
            ColumnApi.prototype.setColumnGroupState = function(stateItems) {
                this.columnController.setColumnGroupState(stateItems, "api");
            };
            ColumnApi.prototype.resetColumnGroupState = function() {
                this.columnController.resetColumnGroupState("api");
            };
            ColumnApi.prototype.isPinning = function() {
                return this.columnController.isPinningLeft() || this.columnController.isPinningRight();
            };
            ColumnApi.prototype.isPinningLeft = function() {
                return this.columnController.isPinningLeft();
            };
            ColumnApi.prototype.isPinningRight = function() {
                return this.columnController.isPinningRight();
            };
            ColumnApi.prototype.getDisplayedColAfter = function(col) {
                return this.columnController.getDisplayedColAfter(col);
            };
            ColumnApi.prototype.getDisplayedColBefore = function(col) {
                return this.columnController.getDisplayedColBefore(col);
            };
            ColumnApi.prototype.setColumnVisible = function(key, visible) {
                this.columnController.setColumnVisible(key, visible, "api");
            };
            ColumnApi.prototype.setColumnsVisible = function(keys, visible) {
                this.columnController.setColumnsVisible(keys, visible, "api");
            };
            ColumnApi.prototype.setColumnPinned = function(key, pinned) {
                this.columnController.setColumnPinned(key, pinned, "api");
            };
            ColumnApi.prototype.setColumnsPinned = function(keys, pinned) {
                this.columnController.setColumnsPinned(keys, pinned, "api");
            };
            ColumnApi.prototype.getAllColumns = function() {
                return this.columnController.getAllPrimaryColumns();
            };
            ColumnApi.prototype.getAllGridColumns = function() {
                return this.columnController.getAllGridColumns();
            };
            ColumnApi.prototype.getDisplayedLeftColumns = function() {
                return this.columnController.getDisplayedLeftColumns();
            };
            ColumnApi.prototype.getDisplayedCenterColumns = function() {
                return this.columnController.getDisplayedCenterColumns();
            };
            ColumnApi.prototype.getDisplayedRightColumns = function() {
                return this.columnController.getDisplayedRightColumns();
            };
            ColumnApi.prototype.getAllDisplayedColumns = function() {
                return this.columnController.getAllDisplayedColumns();
            };
            ColumnApi.prototype.getAllDisplayedVirtualColumns = function() {
                return this.columnController.getAllDisplayedVirtualColumns();
            };
            ColumnApi.prototype.moveColumn = function(key, toIndex) {
                if (typeof key === "number") {
                    console.log("ag-Grid: you are using moveColumn(fromIndex, toIndex) - moveColumn takes a column key and a destination index, not two indexes, to move with indexes use moveColumnByIndex(from,to) instead");
                    this.columnController.moveColumnByIndex(key, toIndex, "api");
                } else {
                    this.columnController.moveColumn(key, toIndex, "api");
                }
            };
            ColumnApi.prototype.moveColumnByIndex = function(fromIndex, toIndex) {
                this.columnController.moveColumnByIndex(fromIndex, toIndex, "api");
            };
            ColumnApi.prototype.moveColumns = function(columnsToMoveKeys, toIndex) {
                this.columnController.moveColumns(columnsToMoveKeys, toIndex, "api");
            };
            ColumnApi.prototype.moveRowGroupColumn = function(fromIndex, toIndex) {
                this.columnController.moveRowGroupColumn(fromIndex, toIndex);
            };
            ColumnApi.prototype.setColumnAggFunc = function(column, aggFunc) {
                this.columnController.setColumnAggFunc(column, aggFunc);
            };
            ColumnApi.prototype.setColumnWidth = function(key, newWidth, finished) {
                if (finished === void 0) {
                    finished = true;
                }
                this.columnController.setColumnWidth(key, newWidth, false, finished);
            };
            ColumnApi.prototype.setPivotMode = function(pivotMode) {
                this.columnController.setPivotMode(pivotMode);
            };
            ColumnApi.prototype.isPivotMode = function() {
                return this.columnController.isPivotMode();
            };
            ColumnApi.prototype.getSecondaryPivotColumn = function(pivotKeys, valueColKey) {
                return this.columnController.getSecondaryPivotColumn(pivotKeys, valueColKey);
            };
            ColumnApi.prototype.setValueColumns = function(colKeys) {
                this.columnController.setValueColumns(colKeys, "api");
            };
            ColumnApi.prototype.getValueColumns = function() {
                return this.columnController.getValueColumns();
            };
            ColumnApi.prototype.removeValueColumn = function(colKey) {
                this.columnController.removeValueColumn(colKey, "api");
            };
            ColumnApi.prototype.removeValueColumns = function(colKeys) {
                this.columnController.removeValueColumns(colKeys, "api");
            };
            ColumnApi.prototype.addValueColumn = function(colKey) {
                this.columnController.addValueColumn(colKey, "api");
            };
            ColumnApi.prototype.addValueColumns = function(colKeys) {
                this.columnController.addValueColumns(colKeys, "api");
            };
            ColumnApi.prototype.setRowGroupColumns = function(colKeys) {
                this.columnController.setRowGroupColumns(colKeys, "api");
            };
            ColumnApi.prototype.removeRowGroupColumn = function(colKey) {
                this.columnController.removeRowGroupColumn(colKey, "api");
            };
            ColumnApi.prototype.removeRowGroupColumns = function(colKeys) {
                this.columnController.removeRowGroupColumns(colKeys, "api");
            };
            ColumnApi.prototype.addRowGroupColumn = function(colKey) {
                this.columnController.addRowGroupColumn(colKey, "api");
            };
            ColumnApi.prototype.addRowGroupColumns = function(colKeys) {
                this.columnController.addRowGroupColumns(colKeys, "api");
            };
            ColumnApi.prototype.getRowGroupColumns = function() {
                return this.columnController.getRowGroupColumns();
            };
            ColumnApi.prototype.setPivotColumns = function(colKeys) {
                this.columnController.setPivotColumns(colKeys, "api");
            };
            ColumnApi.prototype.removePivotColumn = function(colKey) {
                this.columnController.removePivotColumn(colKey, "api");
            };
            ColumnApi.prototype.removePivotColumns = function(colKeys) {
                this.columnController.removePivotColumns(colKeys, "api");
            };
            ColumnApi.prototype.addPivotColumn = function(colKey) {
                this.columnController.addPivotColumn(colKey, "api");
            };
            ColumnApi.prototype.addPivotColumns = function(colKeys) {
                this.columnController.addPivotColumns(colKeys, "api");
            };
            ColumnApi.prototype.getPivotColumns = function() {
                return this.columnController.getPivotColumns();
            };
            ColumnApi.prototype.getLeftDisplayedColumnGroups = function() {
                return this.columnController.getLeftDisplayedColumnGroups();
            };
            ColumnApi.prototype.getCenterDisplayedColumnGroups = function() {
                return this.columnController.getCenterDisplayedColumnGroups();
            };
            ColumnApi.prototype.getRightDisplayedColumnGroups = function() {
                return this.columnController.getRightDisplayedColumnGroups();
            };
            ColumnApi.prototype.getAllDisplayedColumnGroups = function() {
                return this.columnController.getAllDisplayedColumnGroups();
            };
            ColumnApi.prototype.autoSizeColumn = function(key) {
                return this.columnController.autoSizeColumn(key, "api");
            };
            ColumnApi.prototype.autoSizeColumns = function(keys) {
                return this.columnController.autoSizeColumns(keys, "api");
            };
            ColumnApi.prototype.autoSizeAllColumns = function() {
                this.columnController.autoSizeAllColumns("api");
            };
            ColumnApi.prototype.setSecondaryColumns = function(colDefs) {
                this.columnController.setSecondaryColumns(colDefs, "api");
            };
            ColumnApi.prototype.columnGroupOpened = function(group, newValue) {
                console.error("ag-Grid: columnGroupOpened no longer exists, use setColumnGroupOpened");
                this.setColumnGroupOpened(group, newValue);
            };
            ColumnApi.prototype.hideColumns = function(colIds, hide) {
                console.error("ag-Grid: hideColumns is deprecated, use setColumnsVisible");
                this.columnController.setColumnsVisible(colIds, !hide, "api");
            };
            ColumnApi.prototype.hideColumn = function(colId, hide) {
                console.error("ag-Grid: hideColumn is deprecated, use setColumnVisible");
                this.columnController.setColumnVisible(colId, !hide, "api");
            };
            ColumnApi.prototype.setState = function(columnState) {
                console.error("ag-Grid: setState is deprecated, use setColumnState");
                return this.setColumnState(columnState);
            };
            ColumnApi.prototype.getState = function() {
                console.error("ag-Grid: getState is deprecated, use getColumnState");
                return this.getColumnState();
            };
            ColumnApi.prototype.resetState = function() {
                console.error("ag-Grid: resetState is deprecated, use resetColumnState");
                this.resetColumnState();
            };
            ColumnApi.prototype.getAggregationColumns = function() {
                console.error("ag-Grid: getAggregationColumns is deprecated, use getValueColumns");
                return this.columnController.getValueColumns();
            };
            ColumnApi.prototype.removeAggregationColumn = function(colKey) {
                console.error("ag-Grid: removeAggregationColumn is deprecated, use removeValueColumn");
                this.columnController.removeValueColumn(colKey, "api");
            };
            ColumnApi.prototype.removeAggregationColumns = function(colKeys) {
                console.error("ag-Grid: removeAggregationColumns is deprecated, use removeValueColumns");
                this.columnController.removeValueColumns(colKeys, "api");
            };
            ColumnApi.prototype.addAggregationColumn = function(colKey) {
                console.error("ag-Grid: addAggregationColumn is deprecated, use addValueColumn");
                this.columnController.addValueColumn(colKey, "api");
            };
            ColumnApi.prototype.addAggregationColumns = function(colKeys) {
                console.error("ag-Grid: addAggregationColumns is deprecated, use addValueColumns");
                this.columnController.addValueColumns(colKeys, "api");
            };
            ColumnApi.prototype.setColumnAggFunction = function(column, aggFunc) {
                console.error("ag-Grid: setColumnAggFunction is deprecated, use setColumnAggFunc");
                this.columnController.setColumnAggFunc(column, aggFunc, "api");
            };
            ColumnApi.prototype.getDisplayNameForCol = function(column) {
                console.error("ag-Grid: getDisplayNameForCol is deprecated, use getDisplayNameForColumn");
                return this.getDisplayNameForColumn(column, null);
            };
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], ColumnApi.prototype, "columnController", void 0);
            ColumnApi = __decorate([ context_1.Bean("columnApi") ], ColumnApi);
            return ColumnApi;
        }();
        exports.ColumnApi = ColumnApi;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var beanStub_1 = __webpack_require__(13);
        var compIdSequence = new utils_1.NumberSequence();
        var Component = function(_super) {
            __extends(Component, _super);
            function Component(template) {
                var _this = _super.call(this) || this;
                _this.childComponents = [];
                _this.annotatedEventListeners = [];
                _this.visible = true;
                _this.compId = compIdSequence.next();
                if (template) {
                    _this.setTemplate(template);
                }
                return _this;
            }
            Component.prototype.getCompId = function() {
                return this.compId;
            };
            Component.prototype.instantiate = function(context) {
                this.instantiateRecurse(this.getGui(), context);
            };
            Component.prototype.instantiateRecurse = function(parentNode, context) {
                var _this = this;
                var childNodeList = utils_1.Utils.copyNodeList(parentNode.childNodes);
                childNodeList.forEach(function(childNode) {
                    var childComp = context.createComponent(childNode, function(childComp) {
                        var attrList = _this.getAttrLists(childNode);
                        _this.copyAttributesFromNode(attrList, childComp.getGui());
                        _this.createChildAttributes(attrList, childComp);
                        _this.addEventListenersToComponent(attrList, childComp);
                    });
                    if (childComp) {
                        _this.swapComponentForNode(childComp, parentNode, childNode);
                    } else {
                        if (childNode.childNodes) {
                            _this.instantiateRecurse(childNode, context);
                        }
                        if (childNode instanceof HTMLElement) {
                            var attrList = _this.getAttrLists(childNode);
                            _this.addEventListenersToElement(attrList, childNode);
                        }
                    }
                });
            };
            Component.prototype.getAttrLists = function(child) {
                var res = {
                    bindings: [],
                    events: [],
                    normal: []
                };
                utils_1.Utils.iterateNamedNodeMap(child.attributes, function(name, value) {
                    var firstCharacter = name.substr(0, 1);
                    if (firstCharacter === "(") {
                        var eventName = name.replace("(", "").replace(")", "");
                        res.events.push({
                            name: eventName,
                            value: value
                        });
                    } else if (firstCharacter === "[") {
                        var bindingName = name.replace("[", "").replace("]", "");
                        res.bindings.push({
                            name: bindingName,
                            value: value
                        });
                    } else {
                        res.normal.push({
                            name: name,
                            value: value
                        });
                    }
                });
                return res;
            };
            Component.prototype.addEventListenersToElement = function(attrLists, element) {
                var _this = this;
                this.addEventListenerCommon(attrLists, function(eventName, listener) {
                    _this.addDestroyableEventListener(element, eventName, listener);
                });
            };
            Component.prototype.addEventListenersToComponent = function(attrLists, component) {
                var _this = this;
                this.addEventListenerCommon(attrLists, function(eventName, listener) {
                    _this.addDestroyableEventListener(component, eventName, listener);
                });
            };
            Component.prototype.addEventListenerCommon = function(attrLists, callback) {
                var _this = this;
                var methodAliases = this.getAgComponentMetaData("methods");
                attrLists.events.forEach(function(nameValue) {
                    var methodName = nameValue.value;
                    var methodAlias = utils_1.Utils.find(methodAliases, "alias", methodName);
                    var methodNameToUse = utils_1.Utils.exists(methodAlias) ? methodAlias.methodName : methodName;
                    var listener = _this[methodNameToUse];
                    if (typeof listener !== "function") {
                        console.warn("ag-Grid: count not find callback " + methodName);
                        return;
                    }
                    var eventCamelCase = utils_1.Utils.hyphenToCamelCase(nameValue.name);
                    callback(eventCamelCase, listener.bind(_this));
                });
            };
            Component.prototype.createChildAttributes = function(attrLists, child) {
                var _this = this;
                var childAttributes = {};
                attrLists.normal.forEach(function(nameValue) {
                    var nameCamelCase = utils_1.Utils.hyphenToCamelCase(nameValue.name);
                    childAttributes[nameCamelCase] = nameValue.value;
                });
                attrLists.bindings.forEach(function(nameValue) {
                    var nameCamelCase = utils_1.Utils.hyphenToCamelCase(nameValue.name);
                    childAttributes[nameCamelCase] = _this[nameValue.value];
                });
                child.props = childAttributes;
            };
            Component.prototype.copyAttributesFromNode = function(attrLists, childNode) {
                attrLists.normal.forEach(function(nameValue) {
                    childNode.setAttribute(nameValue.name, nameValue.value);
                });
            };
            Component.prototype.swapComponentForNode = function(newComponent, parentNode, childNode) {
                var eComponent = newComponent.getGui();
                parentNode.replaceChild(eComponent, childNode);
                parentNode.insertBefore(document.createComment(childNode.nodeName), eComponent);
                this.childComponents.push(newComponent);
                this.swapInComponentForQuerySelectors(newComponent, childNode);
            };
            Component.prototype.swapInComponentForQuerySelectors = function(newComponent, childNode) {
                var thisProto = Object.getPrototypeOf(this);
                var thisNoType = this;
                while (thisProto != null) {
                    var metaData = thisProto.__agComponentMetaData;
                    var currentProtoName = thisProto.constructor.name;
                    if (metaData && metaData[currentProtoName] && metaData[currentProtoName].querySelectors) {
                        metaData[currentProtoName].querySelectors.forEach(function(querySelector) {
                            if (thisNoType[querySelector.attributeName] === childNode) {
                                thisNoType[querySelector.attributeName] = newComponent;
                            }
                        });
                    }
                    thisProto = Object.getPrototypeOf(thisProto);
                }
            };
            Component.prototype.setTemplate = function(template) {
                var eGui = utils_1.Utils.loadTemplate(template);
                this.setTemplateFromElement(eGui);
            };
            Component.prototype.setTemplateFromElement = function(element) {
                this.eGui = element;
                this.eGui.__agComponent = this;
                this.addAnnotatedEventListeners();
                this.wireQuerySelectors();
            };
            Component.prototype.wireQuerySelectors = function() {
                var _this = this;
                if (!this.eGui) {
                    return;
                }
                var thisProto = Object.getPrototypeOf(this);
                var _loop_1 = function() {
                    var metaData = thisProto.__agComponentMetaData;
                    var currentProtoName = thisProto.constructor.name;
                    if (metaData && metaData[currentProtoName] && metaData[currentProtoName].querySelectors) {
                        var thisNoType_1 = this_1;
                        metaData[currentProtoName].querySelectors.forEach(function(querySelector) {
                            var resultOfQuery = _this.eGui.querySelector(querySelector.querySelector);
                            if (resultOfQuery) {
                                var backingComponent = resultOfQuery.__agComponent;
                                if (backingComponent) {
                                    thisNoType_1[querySelector.attributeName] = backingComponent;
                                } else {
                                    thisNoType_1[querySelector.attributeName] = resultOfQuery;
                                }
                            } else {}
                        });
                    }
                    thisProto = Object.getPrototypeOf(thisProto);
                };
                var this_1 = this;
                while (thisProto != null) {
                    _loop_1();
                }
            };
            Component.prototype.addAnnotatedEventListeners = function() {
                var _this = this;
                this.removeAnnotatedEventListeners();
                if (!this.eGui) {
                    return;
                }
                var listenerMethods = this.getAgComponentMetaData("listenerMethods");
                if (utils_1.Utils.missingOrEmpty(listenerMethods)) {
                    return;
                }
                if (!this.annotatedEventListeners) {
                    this.annotatedEventListeners = [];
                }
                listenerMethods.forEach(function(eventListener) {
                    var listener = _this[eventListener.methodName].bind(_this);
                    _this.eGui.addEventListener(eventListener.eventName, listener);
                    _this.annotatedEventListeners.push({
                        eventName: eventListener.eventName,
                        listener: listener
                    });
                });
            };
            Component.prototype.getAgComponentMetaData = function(key) {
                var res = [];
                var thisProto = Object.getPrototypeOf(this);
                while (thisProto != null) {
                    var metaData = thisProto.__agComponentMetaData;
                    var currentProtoName = thisProto.constructor.name;
                    if (metaData && metaData[currentProtoName] && metaData[currentProtoName][key]) {
                        res = res.concat(metaData[currentProtoName][key]);
                    }
                    thisProto = Object.getPrototypeOf(thisProto);
                }
                return res;
            };
            Component.prototype.removeAnnotatedEventListeners = function() {
                var _this = this;
                if (!this.annotatedEventListeners) {
                    return;
                }
                if (!this.eGui) {
                    return;
                }
                this.annotatedEventListeners.forEach(function(eventListener) {
                    _this.eGui.removeEventListener(eventListener.eventName, eventListener.listener);
                });
                this.annotatedEventListeners = null;
            };
            Component.prototype.getGui = function() {
                return this.eGui;
            };
            Component.prototype.setGui = function(eGui) {
                this.eGui = eGui;
            };
            Component.prototype.queryForHtmlElement = function(cssSelector) {
                return this.eGui.querySelector(cssSelector);
            };
            Component.prototype.queryForHtmlInputElement = function(cssSelector) {
                return this.eGui.querySelector(cssSelector);
            };
            Component.prototype.appendChild = function(newChild) {
                if (utils_1.Utils.isNodeOrElement(newChild)) {
                    this.eGui.appendChild(newChild);
                } else {
                    var childComponent = newChild;
                    this.eGui.appendChild(childComponent.getGui());
                    this.childComponents.push(childComponent);
                }
            };
            Component.prototype.addFeature = function(context, feature) {
                context.wireBean(feature);
                if (feature.destroy) {
                    this.addDestroyFunc(feature.destroy.bind(feature));
                }
            };
            Component.prototype.isVisible = function() {
                return this.visible;
            };
            Component.prototype.setVisible = function(visible) {
                if (visible !== this.visible) {
                    this.visible = visible;
                    utils_1.Utils.addOrRemoveCssClass(this.eGui, "ag-hidden", !visible);
                    var event_1 = {
                        type: Component.EVENT_VISIBLE_CHANGED,
                        visible: this.visible
                    };
                    this.dispatchEvent(event_1);
                }
            };
            Component.prototype.addOrRemoveCssClass = function(className, addOrRemove) {
                utils_1.Utils.addOrRemoveCssClass(this.eGui, className, addOrRemove);
            };
            Component.prototype.destroy = function() {
                _super.prototype.destroy.call(this);
                this.childComponents.forEach(function(childComponent) {
                    return childComponent.destroy();
                });
                this.childComponents.length = 0;
                this.removeAnnotatedEventListeners();
            };
            Component.prototype.addGuiEventListener = function(event, listener) {
                var _this = this;
                this.getGui().addEventListener(event, listener);
                this.addDestroyFunc(function() {
                    return _this.getGui().removeEventListener(event, listener);
                });
            };
            Component.prototype.addCssClass = function(className) {
                utils_1.Utils.addCssClass(this.getGui(), className);
            };
            Component.prototype.removeCssClass = function(className) {
                utils_1.Utils.removeCssClass(this.getGui(), className);
            };
            Component.prototype.getAttribute = function(key) {
                var eGui = this.getGui();
                if (eGui) {
                    return eGui.getAttribute(key);
                } else {
                    return null;
                }
            };
            Component.prototype.getRefElement = function(refName) {
                return this.queryForHtmlElement('[ref="' + refName + '"]');
            };
            Component.EVENT_VISIBLE_CHANGED = "visibleChanged";
            return Component;
        }(beanStub_1.BeanStub);
        exports.Component = Component;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var Constants = function() {
            function Constants() {}
            Constants.STEP_EVERYTHING = 0;
            Constants.STEP_FILTER = 1;
            Constants.STEP_SORT = 2;
            Constants.STEP_MAP = 3;
            Constants.STEP_AGGREGATE = 4;
            Constants.STEP_PIVOT = 5;
            Constants.ROW_BUFFER_SIZE = 10;
            Constants.LAYOUT_INTERVAL = 500;
            Constants.BATCH_WAIT_MILLIS = 50;
            Constants.EXPORT_TYPE_DRAG_COPY = "dragCopy";
            Constants.EXPORT_TYPE_CLIPBOARD = "clipboard";
            Constants.EXPORT_TYPE_EXCEL = "excel";
            Constants.EXPORT_TYPE_CSV = "csv";
            Constants.KEY_BACKSPACE = 8;
            Constants.KEY_TAB = 9;
            Constants.KEY_NEW_LINE = 10;
            Constants.KEY_ENTER = 13;
            Constants.KEY_SHIFT = 16;
            Constants.KEY_ESCAPE = 27;
            Constants.KEY_SPACE = 32;
            Constants.KEY_LEFT = 37;
            Constants.KEY_UP = 38;
            Constants.KEY_RIGHT = 39;
            Constants.KEY_DOWN = 40;
            Constants.KEY_DELETE = 46;
            Constants.KEY_A = 65;
            Constants.KEY_C = 67;
            Constants.KEY_V = 86;
            Constants.KEY_D = 68;
            Constants.KEY_F2 = 113;
            Constants.KEY_PAGE_UP = 33;
            Constants.KEY_PAGE_DOWN = 34;
            Constants.KEY_PAGE_HOME = 36;
            Constants.KEY_PAGE_END = 35;
            Constants.ROW_MODEL_TYPE_INFINITE = "infinite";
            Constants.ROW_MODEL_TYPE_VIEWPORT = "viewport";
            Constants.ROW_MODEL_TYPE_CLIENT_SIDE = "clientSide";
            Constants.ROW_MODEL_TYPE_SERVER_SIDE = "serverSide";
            Constants.DEPRECATED_ROW_MODEL_TYPE_NORMAL = "normal";
            Constants.ALWAYS = "always";
            Constants.ONLY_WHEN_GROUPING = "onlyWhenGrouping";
            Constants.PINNED_TOP = "top";
            Constants.PINNED_BOTTOM = "bottom";
            return Constants;
        }();
        exports.Constants = Constants;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var eventService_1 = __webpack_require__(3);
        var utils_1 = __webpack_require__(1);
        var context_1 = __webpack_require__(0);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var columnUtils_1 = __webpack_require__(31);
        var columnApi_1 = __webpack_require__(7);
        var gridApi_1 = __webpack_require__(6);
        var Column = function() {
            function Column(colDef, colId, primary) {
                this.moving = false;
                this.menuVisible = false;
                this.filterActive = false;
                this.eventService = new eventService_1.EventService();
                this.rowGroupActive = false;
                this.pivotActive = false;
                this.aggregationActive = false;
                this.colDef = colDef;
                this.visible = !colDef.hide;
                this.sort = colDef.sort;
                this.sortedAt = colDef.sortedAt;
                this.colId = colId;
                this.primary = primary;
                this.lockPosition = colDef.lockPosition === true;
                this.lockPinned = colDef.lockPinned === true;
                this.lockVisible = colDef.lockVisible === true;
            }
            Column.prototype.isLockPosition = function() {
                return this.lockPosition;
            };
            Column.prototype.isLockVisible = function() {
                return this.lockVisible;
            };
            Column.prototype.isLockPinned = function() {
                return this.lockPinned;
            };
            Column.prototype.setParent = function(parent) {
                this.parent = parent;
            };
            Column.prototype.getParent = function() {
                return this.parent;
            };
            Column.prototype.initialise = function() {
                this.setPinned(this.colDef.pinned);
                var minColWidth = this.gridOptionsWrapper.getMinColWidth();
                var maxColWidth = this.gridOptionsWrapper.getMaxColWidth();
                if (this.colDef.minWidth) {
                    this.minWidth = this.colDef.minWidth;
                } else {
                    this.minWidth = minColWidth;
                }
                if (this.colDef.maxWidth) {
                    this.maxWidth = this.colDef.maxWidth;
                } else {
                    this.maxWidth = maxColWidth;
                }
                this.actualWidth = this.columnUtils.calculateColInitialWidth(this.colDef);
                var suppressDotNotation = this.gridOptionsWrapper.isSuppressFieldDotNotation();
                this.fieldContainsDots = utils_1.Utils.exists(this.colDef.field) && this.colDef.field.indexOf(".") >= 0 && !suppressDotNotation;
                this.tooltipFieldContainsDots = utils_1.Utils.exists(this.colDef.tooltipField) && this.colDef.tooltipField.indexOf(".") >= 0 && !suppressDotNotation;
                this.validate();
            };
            Column.prototype.isEmptyGroup = function() {
                return false;
            };
            Column.prototype.isRowGroupDisplayed = function(colId) {
                if (utils_1.Utils.missing(this.colDef) || utils_1.Utils.missing(this.colDef.showRowGroup)) {
                    return false;
                }
                var showingAllGroups = this.colDef.showRowGroup === true;
                var showingThisGroup = this.colDef.showRowGroup === colId;
                return showingAllGroups || showingThisGroup;
            };
            Column.prototype.getUniqueId = function() {
                return this.getId();
            };
            Column.prototype.isPrimary = function() {
                return this.primary;
            };
            Column.prototype.isFilterAllowed = function() {
                return this.primary && !this.colDef.suppressFilter;
            };
            Column.prototype.isFieldContainsDots = function() {
                return this.fieldContainsDots;
            };
            Column.prototype.isTooltipFieldContainsDots = function() {
                return this.tooltipFieldContainsDots;
            };
            Column.prototype.validate = function() {
                var colDefAny = this.colDef;
                if (!this.gridOptionsWrapper.isEnterprise()) {
                    var itemsNotAllowedWithoutEnterprise = [ "enableRowGroup", "rowGroup", "rowGroupIndex", "enablePivot", "pivot", "pivotIndex", "aggFunc" ];
                    itemsNotAllowedWithoutEnterprise.forEach(function(item) {
                        if (utils_1.Utils.exists(colDefAny[item])) {
                            console.warn("ag-Grid: " + item + " is only valid in ag-Grid-Enterprise, your column definition should not have " + item);
                        }
                    });
                }
                if (this.gridOptionsWrapper.isTreeData()) {
                    var itemsNotAllowedWithTreeData = [ "enableRowGroup", "rowGroup", "rowGroupIndex", "enablePivot", "pivot", "pivotIndex" ];
                    itemsNotAllowedWithTreeData.forEach(function(item) {
                        if (utils_1.Utils.exists(colDefAny[item])) {
                            console.warn("ag-Grid: " + item + " is not possible when doing tree data, your column definition should not have " + item);
                        }
                    });
                }
                if (utils_1.Utils.exists(this.colDef.width) && typeof this.colDef.width !== "number") {
                    console.warn("ag-Grid: colDef.width should be a number, not " + typeof this.colDef.width);
                }
                if (utils_1.Utils.get(this, "colDef.cellRendererParams.restrictToOneGroup", null)) {
                    console.warn("ag-Grid: Since ag-grid 11.0.0 cellRendererParams.restrictToOneGroup is deprecated. You should use showRowGroup");
                }
                if (utils_1.Utils.get(this, "colDef.cellRendererParams.keyMap", null)) {
                    console.warn("ag-Grid: Since ag-grid 11.0.0 cellRendererParams.keyMap is deprecated. You should use colDef.keyCreator");
                }
                if (utils_1.Utils.get(this, "colDef.cellRendererParams.keyMap", null)) {
                    console.warn("ag-Grid: Since ag-grid 11.0.0 cellRendererParams.keyMap is deprecated. You should use colDef.keyCreator");
                }
                if (colDefAny.floatingCellRenderer) {
                    console.warn("ag-Grid: since v11, floatingCellRenderer is now pinnedRowCellRenderer");
                    this.colDef.pinnedRowCellRenderer = colDefAny.floatingCellRenderer;
                }
                if (colDefAny.floatingRendererFramework) {
                    console.warn("ag-Grid: since v11, floatingRendererFramework is now pinnedRowCellRendererFramework");
                    this.colDef.pinnedRowCellRendererFramework = colDefAny.floatingRendererFramework;
                }
                if (colDefAny.floatingRendererParams) {
                    console.warn("ag-Grid: since v11, floatingRendererParams is now pinnedRowCellRendererParams");
                    this.colDef.pinnedRowCellRendererParams = colDefAny.floatingRendererParams;
                }
                if (colDefAny.floatingValueFormatter) {
                    console.warn("ag-Grid: since v11, floatingValueFormatter is now pinnedRowValueFormatter");
                    this.colDef.pinnedRowValueFormatter = colDefAny.floatingValueFormatter;
                }
                if (colDefAny.cellFormatter) {
                    console.warn("ag-Grid: since v12, cellFormatter is now valueFormatter");
                    if (utils_1.Utils.missing(this.colDef.valueFormatter)) {
                        this.colDef.valueFormatter = colDefAny.cellFormatter;
                    }
                }
                if (colDefAny.headerCellTemplate) {
                    console.warn("ag-Grid: since v15, headerCellTemplate is gone, use header component instead.");
                }
                if (colDefAny.headerCellRenderer) {
                    console.warn("ag-Grid: since v15, headerCellRenderer is gone, use header component instead.");
                }
                if (colDefAny.volatile) {
                    console.warn("ag-Grid: since v16, colDef.volatile is gone, please check refresh docs on how to refresh specific cells.");
                }
            };
            Column.prototype.addEventListener = function(eventType, listener) {
                this.eventService.addEventListener(eventType, listener);
            };
            Column.prototype.removeEventListener = function(eventType, listener) {
                this.eventService.removeEventListener(eventType, listener);
            };
            Column.prototype.createIsColumnFuncParams = function(rowNode) {
                return {
                    node: rowNode,
                    data: rowNode.data,
                    column: this,
                    colDef: this.colDef,
                    context: this.gridOptionsWrapper.getContext(),
                    api: this.gridOptionsWrapper.getApi(),
                    columnApi: this.gridOptionsWrapper.getColumnApi()
                };
            };
            Column.prototype.isSuppressNavigable = function(rowNode) {
                if (typeof this.colDef.suppressNavigable === "boolean") {
                    return this.colDef.suppressNavigable;
                }
                if (typeof this.colDef.suppressNavigable === "function") {
                    var params = this.createIsColumnFuncParams(rowNode);
                    var userFunc = this.colDef.suppressNavigable;
                    return userFunc(params);
                }
                return false;
            };
            Column.prototype.isCellEditable = function(rowNode) {
                if (rowNode.group && !this.gridOptionsWrapper.isEnableGroupEdit()) {
                    return false;
                }
                return this.isColumnFunc(rowNode, this.colDef.editable);
            };
            Column.prototype.isRowDrag = function(rowNode) {
                return this.isColumnFunc(rowNode, this.colDef.rowDrag);
            };
            Column.prototype.isCellCheckboxSelection = function(rowNode) {
                return this.isColumnFunc(rowNode, this.colDef.checkboxSelection);
            };
            Column.prototype.isSuppressPaste = function(rowNode) {
                return this.isColumnFunc(rowNode, this.colDef ? this.colDef.suppressPaste : null);
            };
            Column.prototype.isResizable = function() {
                var enableColResize = this.gridOptionsWrapper.isEnableColResize();
                var suppressResize = this.colDef && this.colDef.suppressResize;
                return enableColResize && !suppressResize;
            };
            Column.prototype.isColumnFunc = function(rowNode, value) {
                if (typeof value === "boolean") {
                    return value;
                }
                if (typeof value === "function") {
                    var params = this.createIsColumnFuncParams(rowNode);
                    var editableFunc = value;
                    return editableFunc(params);
                }
                return false;
            };
            Column.prototype.setMoving = function(moving, source) {
                if (source === void 0) {
                    source = "api";
                }
                this.moving = moving;
                this.eventService.dispatchEvent(this.createColumnEvent(Column.EVENT_MOVING_CHANGED, source));
            };
            Column.prototype.createColumnEvent = function(type, source) {
                return {
                    api: this.gridApi,
                    columnApi: this.columnApi,
                    type: type,
                    column: this,
                    columns: [ this ],
                    source: source
                };
            };
            Column.prototype.isMoving = function() {
                return this.moving;
            };
            Column.prototype.getSort = function() {
                return this.sort;
            };
            Column.prototype.setSort = function(sort, source) {
                if (source === void 0) {
                    source = "api";
                }
                if (this.sort !== sort) {
                    this.sort = sort;
                    this.eventService.dispatchEvent(this.createColumnEvent(Column.EVENT_SORT_CHANGED, source));
                }
            };
            Column.prototype.setMenuVisible = function(visible, source) {
                if (source === void 0) {
                    source = "api";
                }
                if (this.menuVisible !== visible) {
                    this.menuVisible = visible;
                    this.eventService.dispatchEvent(this.createColumnEvent(Column.EVENT_MENU_VISIBLE_CHANGED, source));
                }
            };
            Column.prototype.isMenuVisible = function() {
                return this.menuVisible;
            };
            Column.prototype.isSortAscending = function() {
                return this.sort === Column.SORT_ASC;
            };
            Column.prototype.isSortDescending = function() {
                return this.sort === Column.SORT_DESC;
            };
            Column.prototype.isSortNone = function() {
                return utils_1.Utils.missing(this.sort);
            };
            Column.prototype.isSorting = function() {
                return utils_1.Utils.exists(this.sort);
            };
            Column.prototype.getSortedAt = function() {
                return this.sortedAt;
            };
            Column.prototype.setSortedAt = function(sortedAt) {
                this.sortedAt = sortedAt;
            };
            Column.prototype.setAggFunc = function(aggFunc) {
                this.aggFunc = aggFunc;
            };
            Column.prototype.getAggFunc = function() {
                return this.aggFunc;
            };
            Column.prototype.getLeft = function() {
                return this.left;
            };
            Column.prototype.getOldLeft = function() {
                return this.oldLeft;
            };
            Column.prototype.getRight = function() {
                return this.left + this.actualWidth;
            };
            Column.prototype.setLeft = function(left, source) {
                if (source === void 0) {
                    source = "api";
                }
                this.oldLeft = this.left;
                if (this.left !== left) {
                    this.left = left;
                    this.eventService.dispatchEvent(this.createColumnEvent(Column.EVENT_LEFT_CHANGED, source));
                }
            };
            Column.prototype.isFilterActive = function() {
                return this.filterActive;
            };
            Column.prototype.setFilterActive = function(active, source) {
                if (source === void 0) {
                    source = "api";
                }
                if (this.filterActive !== active) {
                    this.filterActive = active;
                    this.eventService.dispatchEvent(this.createColumnEvent(Column.EVENT_FILTER_ACTIVE_CHANGED, source));
                }
                this.eventService.dispatchEvent(this.createColumnEvent(Column.EVENT_FILTER_CHANGED, source));
            };
            Column.prototype.setPinned = function(pinned) {
                if (pinned === true || pinned === Column.PINNED_LEFT) {
                    this.pinned = Column.PINNED_LEFT;
                } else if (pinned === Column.PINNED_RIGHT) {
                    this.pinned = Column.PINNED_RIGHT;
                } else {
                    this.pinned = null;
                }
            };
            Column.prototype.setFirstRightPinned = function(firstRightPinned, source) {
                if (source === void 0) {
                    source = "api";
                }
                if (this.firstRightPinned !== firstRightPinned) {
                    this.firstRightPinned = firstRightPinned;
                    this.eventService.dispatchEvent(this.createColumnEvent(Column.EVENT_FIRST_RIGHT_PINNED_CHANGED, source));
                }
            };
            Column.prototype.setLastLeftPinned = function(lastLeftPinned, source) {
                if (source === void 0) {
                    source = "api";
                }
                if (this.lastLeftPinned !== lastLeftPinned) {
                    this.lastLeftPinned = lastLeftPinned;
                    this.eventService.dispatchEvent(this.createColumnEvent(Column.EVENT_LAST_LEFT_PINNED_CHANGED, source));
                }
            };
            Column.prototype.isFirstRightPinned = function() {
                return this.firstRightPinned;
            };
            Column.prototype.isLastLeftPinned = function() {
                return this.lastLeftPinned;
            };
            Column.prototype.isPinned = function() {
                return this.pinned === Column.PINNED_LEFT || this.pinned === Column.PINNED_RIGHT;
            };
            Column.prototype.isPinnedLeft = function() {
                return this.pinned === Column.PINNED_LEFT;
            };
            Column.prototype.isPinnedRight = function() {
                return this.pinned === Column.PINNED_RIGHT;
            };
            Column.prototype.getPinned = function() {
                return this.pinned;
            };
            Column.prototype.setVisible = function(visible, source) {
                if (source === void 0) {
                    source = "api";
                }
                var newValue = visible === true;
                if (this.visible !== newValue) {
                    this.visible = newValue;
                    this.eventService.dispatchEvent(this.createColumnEvent(Column.EVENT_VISIBLE_CHANGED, source));
                }
            };
            Column.prototype.isVisible = function() {
                return this.visible;
            };
            Column.prototype.getColDef = function() {
                return this.colDef;
            };
            Column.prototype.getColumnGroupShow = function() {
                return this.colDef.columnGroupShow;
            };
            Column.prototype.getColId = function() {
                return this.colId;
            };
            Column.prototype.getId = function() {
                return this.getColId();
            };
            Column.prototype.getDefinition = function() {
                return this.colDef;
            };
            Column.prototype.getActualWidth = function() {
                return this.actualWidth;
            };
            Column.prototype.createBaseColDefParams = function(rowNode) {
                var params = {
                    node: rowNode,
                    data: rowNode.data,
                    colDef: this.colDef,
                    column: this,
                    api: this.gridOptionsWrapper.getApi(),
                    columnApi: this.gridOptionsWrapper.getColumnApi(),
                    context: this.gridOptionsWrapper.getContext()
                };
                return params;
            };
            Column.prototype.getColSpan = function(rowNode) {
                if (utils_1.Utils.missing(this.colDef.colSpan)) {
                    return 1;
                } else {
                    var params = this.createBaseColDefParams(rowNode);
                    var colSpan = this.colDef.colSpan(params);
                    if (colSpan > 1) {
                        return colSpan;
                    } else {
                        return 1;
                    }
                }
            };
            Column.prototype.getRowSpan = function(rowNode) {
                if (utils_1.Utils.missing(this.colDef.rowSpan)) {
                    return 1;
                } else {
                    var params = this.createBaseColDefParams(rowNode);
                    var rowSpan = this.colDef.rowSpan(params);
                    if (rowSpan > 1) {
                        return rowSpan;
                    } else {
                        return 1;
                    }
                }
            };
            Column.prototype.setActualWidth = function(actualWidth, source) {
                if (source === void 0) {
                    source = "api";
                }
                if (this.actualWidth !== actualWidth) {
                    this.actualWidth = actualWidth;
                    this.eventService.dispatchEvent(this.createColumnEvent(Column.EVENT_WIDTH_CHANGED, source));
                }
            };
            Column.prototype.isGreaterThanMax = function(width) {
                if (this.maxWidth) {
                    return width > this.maxWidth;
                } else {
                    return false;
                }
            };
            Column.prototype.getMinWidth = function() {
                return this.minWidth;
            };
            Column.prototype.getMaxWidth = function() {
                return this.maxWidth;
            };
            Column.prototype.setMinimum = function(source) {
                if (source === void 0) {
                    source = "api";
                }
                this.setActualWidth(this.minWidth, source);
            };
            Column.prototype.setRowGroupActive = function(rowGroup, source) {
                if (source === void 0) {
                    source = "api";
                }
                if (this.rowGroupActive !== rowGroup) {
                    this.rowGroupActive = rowGroup;
                    this.eventService.dispatchEvent(this.createColumnEvent(Column.EVENT_ROW_GROUP_CHANGED, source));
                }
            };
            Column.prototype.isRowGroupActive = function() {
                return this.rowGroupActive;
            };
            Column.prototype.setPivotActive = function(pivot, source) {
                if (source === void 0) {
                    source = "api";
                }
                if (this.pivotActive !== pivot) {
                    this.pivotActive = pivot;
                    this.eventService.dispatchEvent(this.createColumnEvent(Column.EVENT_PIVOT_CHANGED, source));
                }
            };
            Column.prototype.isPivotActive = function() {
                return this.pivotActive;
            };
            Column.prototype.isAnyFunctionActive = function() {
                return this.isPivotActive() || this.isRowGroupActive() || this.isValueActive();
            };
            Column.prototype.isAnyFunctionAllowed = function() {
                return this.isAllowPivot() || this.isAllowRowGroup() || this.isAllowValue();
            };
            Column.prototype.setValueActive = function(value, source) {
                if (source === void 0) {
                    source = "api";
                }
                if (this.aggregationActive !== value) {
                    this.aggregationActive = value;
                    this.eventService.dispatchEvent(this.createColumnEvent(Column.EVENT_VALUE_CHANGED, source));
                }
            };
            Column.prototype.isValueActive = function() {
                return this.aggregationActive;
            };
            Column.prototype.isAllowPivot = function() {
                return this.colDef.enablePivot === true;
            };
            Column.prototype.isAllowValue = function() {
                return this.colDef.enableValue === true;
            };
            Column.prototype.isAllowRowGroup = function() {
                return this.colDef.enableRowGroup === true;
            };
            Column.prototype.getMenuTabs = function(defaultValues) {
                var menuTabs = this.getColDef().menuTabs;
                if (menuTabs == null) {
                    menuTabs = defaultValues;
                }
                return menuTabs;
            };
            Column.EVENT_MOVING_CHANGED = "movingChanged";
            Column.EVENT_LEFT_CHANGED = "leftChanged";
            Column.EVENT_WIDTH_CHANGED = "widthChanged";
            Column.EVENT_LAST_LEFT_PINNED_CHANGED = "lastLeftPinnedChanged";
            Column.EVENT_FIRST_RIGHT_PINNED_CHANGED = "firstRightPinnedChanged";
            Column.EVENT_VISIBLE_CHANGED = "visibleChanged";
            Column.EVENT_FILTER_CHANGED = "filterChanged";
            Column.EVENT_FILTER_ACTIVE_CHANGED = "filterActiveChanged";
            Column.EVENT_SORT_CHANGED = "sortChanged";
            Column.EVENT_MENU_VISIBLE_CHANGED = "menuVisibleChanged";
            Column.EVENT_ROW_GROUP_CHANGED = "columnRowGroupChanged";
            Column.EVENT_PIVOT_CHANGED = "columnPivotChanged";
            Column.EVENT_VALUE_CHANGED = "columnValueChanged";
            Column.PINNED_RIGHT = "right";
            Column.PINNED_LEFT = "left";
            Column.SORT_ASC = "asc";
            Column.SORT_DESC = "desc";
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], Column.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("columnUtils"), __metadata("design:type", columnUtils_1.ColumnUtils) ], Column.prototype, "columnUtils", void 0);
            __decorate([ context_1.Autowired("frameworkFactory"), __metadata("design:type", Object) ], Column.prototype, "frameworkFactory", void 0);
            __decorate([ context_1.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], Column.prototype, "columnApi", void 0);
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], Column.prototype, "gridApi", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], Column.prototype, "initialise", null);
            return Column;
        }();
        exports.Column = Column;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        function QuerySelector(selector) {
            return querySelectorFunc.bind(this, selector);
        }
        exports.QuerySelector = QuerySelector;
        function RefSelector(ref) {
            return querySelectorFunc.bind(this, "[ref=" + ref + "]");
        }
        exports.RefSelector = RefSelector;
        function querySelectorFunc(selector, classPrototype, methodOrAttributeName, index) {
            if (selector === null) {
                console.error("ag-Grid: QuerySelector selector should not be null");
                return;
            }
            if (typeof index === "number") {
                console.error("ag-Grid: QuerySelector should be on an attribute");
                return;
            }
            addToObjectProps(classPrototype, "querySelectors", {
                attributeName: methodOrAttributeName,
                querySelector: selector
            });
        }
        function Listener(eventName) {
            return listenerFunc.bind(this, eventName);
        }
        exports.Listener = Listener;
        function listenerFunc(eventName, target, methodName) {
            if (eventName === null) {
                console.error("ag-Grid: EventListener eventName should not be null");
                return;
            }
            addToObjectProps(target, "listenerMethods", {
                methodName: methodName,
                eventName: eventName
            });
        }
        function Method(eventName) {
            return methodFunc.bind(this, eventName);
        }
        exports.Method = Method;
        function methodFunc(alias, target, methodName) {
            if (alias === null) {
                console.error("ag-Grid: EventListener eventName should not be null");
                return;
            }
            addToObjectProps(target, "methods", {
                methodName: methodName,
                alias: alias
            });
        }
        function addToObjectProps(target, key, value) {
            var props = getOrCreateProps(target, target.constructor.name);
            if (!props[key]) {
                props[key] = [];
            }
            props[key].push(value);
        }
        function getOrCreateProps(target, instanceName) {
            if (!target.__agComponentMetaData) {
                target.__agComponentMetaData = {};
            }
            if (!target.__agComponentMetaData[instanceName]) {
                target.__agComponentMetaData[instanceName] = {};
            }
            return target.__agComponentMetaData[instanceName];
        }
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        var __param = this && this.__param || function(paramIndex, decorator) {
            return function(target, key) {
                decorator(target, key, paramIndex);
            };
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var context_1 = __webpack_require__(0);
        var context_2 = __webpack_require__(0);
        var LoggerFactory = function() {
            function LoggerFactory() {}
            LoggerFactory.prototype.setBeans = function(gridOptionsWrapper) {
                this.logging = gridOptionsWrapper.isDebug();
            };
            LoggerFactory.prototype.create = function(name) {
                return new Logger(name, this.isLogging.bind(this));
            };
            LoggerFactory.prototype.isLogging = function() {
                return this.logging;
            };
            __decorate([ __param(0, context_2.Qualifier("gridOptionsWrapper")), __metadata("design:type", Function), __metadata("design:paramtypes", [ gridOptionsWrapper_1.GridOptionsWrapper ]), __metadata("design:returntype", void 0) ], LoggerFactory.prototype, "setBeans", null);
            LoggerFactory = __decorate([ context_1.Bean("loggerFactory") ], LoggerFactory);
            return LoggerFactory;
        }();
        exports.LoggerFactory = LoggerFactory;
        var Logger = function() {
            function Logger(name, isLoggingFunc) {
                this.name = name;
                this.isLoggingFunc = isLoggingFunc;
            }
            Logger.prototype.isLogging = function() {
                return this.isLoggingFunc();
            };
            Logger.prototype.log = function(message) {
                if (this.isLoggingFunc()) {
                    console.log("ag-Grid." + this.name + ": " + message);
                }
            };
            return Logger;
        }();
        exports.Logger = Logger;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var eventService_1 = __webpack_require__(3);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var utils_1 = __webpack_require__(1);
        var BeanStub = function() {
            function BeanStub() {
                this.destroyFunctions = [];
                this.destroyed = false;
            }
            BeanStub.prototype.destroy = function() {
                this.destroyFunctions.forEach(function(func) {
                    return func();
                });
                this.destroyFunctions.length = 0;
                this.destroyed = true;
                this.dispatchEvent({
                    type: BeanStub.EVENT_DESTROYED
                });
            };
            BeanStub.prototype.addEventListener = function(eventType, listener) {
                if (!this.localEventService) {
                    this.localEventService = new eventService_1.EventService();
                }
                this.localEventService.addEventListener(eventType, listener);
            };
            BeanStub.prototype.removeEventListener = function(eventType, listener) {
                if (this.localEventService) {
                    this.localEventService.removeEventListener(eventType, listener);
                }
            };
            BeanStub.prototype.dispatchEventAsync = function(event) {
                var _this = this;
                setTimeout(function() {
                    return _this.dispatchEvent(event);
                }, 0);
            };
            BeanStub.prototype.dispatchEvent = function(event) {
                if (this.localEventService) {
                    this.localEventService.dispatchEvent(event);
                }
            };
            BeanStub.prototype.addDestroyableEventListener = function(eElement, event, listener) {
                if (this.destroyed) {
                    return;
                }
                if (eElement instanceof HTMLElement) {
                    utils_1._.addSafePassiveEventListener(eElement, event, listener);
                } else if (eElement instanceof Window) {
                    eElement.addEventListener(event, listener);
                } else if (eElement instanceof gridOptionsWrapper_1.GridOptionsWrapper) {
                    eElement.addEventListener(event, listener);
                } else {
                    eElement.addEventListener(event, listener);
                }
                this.destroyFunctions.push(function() {
                    if (eElement instanceof HTMLElement) {
                        eElement.removeEventListener(event, listener);
                    } else if (eElement instanceof Window) {
                        eElement.removeEventListener(event, listener);
                    } else if (eElement instanceof gridOptionsWrapper_1.GridOptionsWrapper) {
                        eElement.removeEventListener(event, listener);
                    } else {
                        eElement.removeEventListener(event, listener);
                    }
                });
            };
            BeanStub.prototype.isAlive = function() {
                return !this.destroyed;
            };
            BeanStub.prototype.addDestroyFunc = function(func) {
                if (this.isAlive()) {
                    this.destroyFunctions.push(func);
                } else {
                    func();
                }
            };
            BeanStub.EVENT_DESTROYED = "destroyed";
            return BeanStub;
        }();
        exports.BeanStub = BeanStub;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var eventService_1 = __webpack_require__(3);
        var events_1 = __webpack_require__(5);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var selectionController_1 = __webpack_require__(17);
        var valueService_1 = __webpack_require__(16);
        var columnController_1 = __webpack_require__(4);
        var columnApi_1 = __webpack_require__(7);
        var context_1 = __webpack_require__(0);
        var constants_1 = __webpack_require__(9);
        var utils_1 = __webpack_require__(1);
        var valueCache_1 = __webpack_require__(33);
        var gridApi_1 = __webpack_require__(6);
        var RowNode = function() {
            function RowNode() {
                this.childrenMapped = {};
                this.selectable = true;
                this.selected = false;
            }
            RowNode.prototype.setData = function(data) {
                var oldData = this.data;
                this.data = data;
                this.valueCache.onDataChanged();
                this.updateDataOnDetailNode();
                this.checkRowSelectable();
                var event = this.createDataChangedEvent(data, oldData, false);
                this.dispatchLocalEvent(event);
            };
            RowNode.prototype.updateDataOnDetailNode = function() {
                if (this.detailNode) {
                    this.detailNode.data = this.data;
                }
            };
            RowNode.prototype.createDataChangedEvent = function(newData, oldData, update) {
                return {
                    type: RowNode.EVENT_DATA_CHANGED,
                    node: this,
                    oldData: oldData,
                    newData: newData,
                    update: update
                };
            };
            RowNode.prototype.createLocalRowEvent = function(type) {
                return {
                    type: type,
                    node: this
                };
            };
            RowNode.prototype.updateData = function(data) {
                var oldData = this.data;
                this.data = data;
                this.updateDataOnDetailNode();
                this.checkRowSelectable();
                this.updateDataOnDetailNode();
                var event = this.createDataChangedEvent(data, oldData, true);
                this.dispatchLocalEvent(event);
            };
            RowNode.prototype.getRowIndexString = function() {
                if (this.rowPinned === constants_1.Constants.PINNED_TOP) {
                    return "t-" + this.rowIndex;
                } else if (this.rowPinned === constants_1.Constants.PINNED_BOTTOM) {
                    return "b-" + this.rowIndex;
                } else {
                    return this.rowIndex.toString();
                }
            };
            RowNode.prototype.createDaemonNode = function() {
                var oldNode = new RowNode();
                this.context.wireBean(oldNode);
                oldNode.id = this.id;
                oldNode.data = this.data;
                oldNode.daemon = true;
                oldNode.selected = this.selected;
                oldNode.level = this.level;
                return oldNode;
            };
            RowNode.prototype.setDataAndId = function(data, id) {
                var oldNode = utils_1.Utils.exists(this.id) ? this.createDaemonNode() : null;
                var oldData = this.data;
                this.data = data;
                this.updateDataOnDetailNode();
                this.setId(id);
                this.selectionController.syncInRowNode(this, oldNode);
                this.checkRowSelectable();
                var event = this.createDataChangedEvent(data, oldData, false);
                this.dispatchLocalEvent(event);
            };
            RowNode.prototype.checkRowSelectable = function() {
                var isRowSelectableFunc = this.gridOptionsWrapper.getIsRowSelectableFunc();
                var shouldInvokeIsRowSelectable = isRowSelectableFunc && utils_1.Utils.exists(this);
                this.setRowSelectable(shouldInvokeIsRowSelectable ? isRowSelectableFunc(this) : true);
            };
            RowNode.prototype.setRowSelectable = function(newVal) {
                if (this.selectable !== newVal) {
                    this.selectable = newVal;
                    if (this.eventService) {
                        this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_SELECTABLE_CHANGED));
                    }
                }
            };
            RowNode.prototype.setId = function(id) {
                var getRowNodeId = this.gridOptionsWrapper.getRowNodeIdFunc();
                if (getRowNodeId) {
                    if (this.data) {
                        this.id = getRowNodeId(this.data);
                    } else {
                        this.id = undefined;
                    }
                } else {
                    this.id = id;
                }
            };
            RowNode.prototype.isPixelInRange = function(pixel) {
                return pixel >= this.rowTop && pixel < this.rowTop + this.rowHeight;
            };
            RowNode.prototype.clearRowTop = function() {
                this.oldRowTop = this.rowTop;
                this.setRowTop(null);
            };
            RowNode.prototype.setFirstChild = function(firstChild) {
                if (this.firstChild === firstChild) {
                    return;
                }
                this.firstChild = firstChild;
                if (this.eventService) {
                    this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_FIRST_CHILD_CHANGED));
                }
            };
            RowNode.prototype.setLastChild = function(lastChild) {
                if (this.lastChild === lastChild) {
                    return;
                }
                this.lastChild = lastChild;
                if (this.eventService) {
                    this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_LAST_CHILD_CHANGED));
                }
            };
            RowNode.prototype.setChildIndex = function(childIndex) {
                if (this.childIndex === childIndex) {
                    return;
                }
                this.childIndex = childIndex;
                if (this.eventService) {
                    this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_CHILD_INDEX_CHANGED));
                }
            };
            RowNode.prototype.setRowTop = function(rowTop) {
                if (this.rowTop === rowTop) {
                    return;
                }
                this.rowTop = rowTop;
                if (this.eventService) {
                    this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_TOP_CHANGED));
                }
            };
            RowNode.prototype.setDragging = function(dragging) {
                if (this.dragging === dragging) {
                    return;
                }
                this.dragging = dragging;
                if (this.eventService) {
                    this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_DRAGGING_CHANGED));
                }
            };
            RowNode.prototype.setAllChildrenCount = function(allChildrenCount) {
                if (this.allChildrenCount === allChildrenCount) {
                    return;
                }
                this.allChildrenCount = allChildrenCount;
                if (this.eventService) {
                    this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_ALL_CHILDREN_COUNT_CHANGED));
                }
            };
            RowNode.prototype.setRowHeight = function(rowHeight) {
                this.rowHeight = rowHeight;
                if (this.eventService) {
                    this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_HEIGHT_CHANGED));
                }
            };
            RowNode.prototype.setRowIndex = function(rowIndex) {
                this.rowIndex = rowIndex;
                if (this.eventService) {
                    this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_ROW_INDEX_CHANGED));
                }
            };
            RowNode.prototype.setUiLevel = function(uiLevel) {
                if (this.uiLevel === uiLevel) {
                    return;
                }
                this.uiLevel = uiLevel;
                if (this.eventService) {
                    this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_UI_LEVEL_CHANGED));
                }
            };
            RowNode.prototype.setExpanded = function(expanded) {
                if (this.expanded === expanded) {
                    return;
                }
                this.expanded = expanded;
                if (this.eventService) {
                    this.eventService.dispatchEvent(this.createLocalRowEvent(RowNode.EVENT_EXPANDED_CHANGED));
                }
                var event = this.createGlobalRowEvent(events_1.Events.EVENT_ROW_GROUP_OPENED);
                this.mainEventService.dispatchEvent(event);
            };
            RowNode.prototype.createGlobalRowEvent = function(type) {
                var event = {
                    type: type,
                    node: this,
                    data: this.data,
                    rowIndex: this.rowIndex,
                    rowPinned: this.rowPinned,
                    context: this.gridOptionsWrapper.getContext(),
                    api: this.gridOptionsWrapper.getApi(),
                    columnApi: this.gridOptionsWrapper.getColumnApi()
                };
                return event;
            };
            RowNode.prototype.dispatchLocalEvent = function(event) {
                if (this.eventService) {
                    this.eventService.dispatchEvent(event);
                }
            };
            RowNode.prototype.setDataValue = function(colKey, newValue) {
                var column = this.columnController.getPrimaryColumn(colKey);
                this.valueService.setValue(this, column, newValue);
                this.dispatchCellChangedEvent(column, newValue);
            };
            RowNode.prototype.setGroupValue = function(colKey, newValue) {
                var column = this.columnController.getGridColumn(colKey);
                if (utils_1.Utils.missing(this.groupData)) {
                    this.groupData = {};
                }
                this.groupData[column.getColId()] = newValue;
                this.dispatchCellChangedEvent(column, newValue);
            };
            RowNode.prototype.setAggData = function(newAggData) {
                var _this = this;
                var colIds = utils_1.Utils.getAllKeysInObjects([ this.aggData, newAggData ]);
                this.aggData = newAggData;
                if (this.eventService) {
                    colIds.forEach(function(colId) {
                        var column = _this.columnController.getGridColumn(colId);
                        var value = _this.aggData ? _this.aggData[colId] : undefined;
                        _this.dispatchCellChangedEvent(column, value);
                    });
                }
            };
            RowNode.prototype.hasChildren = function() {
                return this.group || this.childrenAfterGroup && this.childrenAfterGroup.length > 0;
            };
            RowNode.prototype.isEmptyFillerNode = function() {
                return this.group && utils_1.Utils.missingOrEmpty(this.childrenAfterGroup);
            };
            RowNode.prototype.dispatchCellChangedEvent = function(column, newValue) {
                var cellChangedEvent = {
                    type: RowNode.EVENT_CELL_CHANGED,
                    node: this,
                    column: column,
                    newValue: newValue
                };
                this.dispatchLocalEvent(cellChangedEvent);
            };
            RowNode.prototype.resetQuickFilterAggregateText = function() {
                this.quickFilterAggregateText = null;
            };
            RowNode.prototype.isExpandable = function() {
                return this.hasChildren() || this.master;
            };
            RowNode.prototype.isSelected = function() {
                if (this.footer) {
                    return this.sibling.isSelected();
                }
                return this.selected;
            };
            RowNode.prototype.depthFirstSearch = function(callback) {
                if (this.childrenAfterGroup) {
                    this.childrenAfterGroup.forEach(function(child) {
                        return child.depthFirstSearch(callback);
                    });
                }
                callback(this);
            };
            RowNode.prototype.calculateSelectedFromChildren = function() {
                var atLeastOneSelected = false;
                var atLeastOneDeSelected = false;
                var atLeastOneMixed = false;
                var newSelectedValue;
                if (this.childrenAfterGroup) {
                    for (var i = 0; i < this.childrenAfterGroup.length; i++) {
                        var child = this.childrenAfterGroup[i];
                        if (!child.selectable) continue;
                        var childState = child.isSelected();
                        switch (childState) {
                          case true:
                            atLeastOneSelected = true;
                            break;

                          case false:
                            atLeastOneDeSelected = true;
                            break;

                          default:
                            atLeastOneMixed = true;
                            break;
                        }
                    }
                }
                if (atLeastOneMixed) {
                    newSelectedValue = undefined;
                } else if (atLeastOneSelected && !atLeastOneDeSelected) {
                    newSelectedValue = true;
                } else if (!atLeastOneSelected && atLeastOneDeSelected) {
                    newSelectedValue = false;
                } else {
                    newSelectedValue = undefined;
                }
                this.selectThisNode(newSelectedValue);
            };
            RowNode.prototype.calculateSelectedFromChildrenBubbleUp = function() {
                this.calculateSelectedFromChildren();
                if (this.parent) {
                    this.parent.calculateSelectedFromChildrenBubbleUp();
                }
            };
            RowNode.prototype.setSelectedInitialValue = function(selected) {
                this.selected = selected;
            };
            RowNode.prototype.setSelected = function(newValue, clearSelection, tailingNodeInSequence) {
                if (clearSelection === void 0) {
                    clearSelection = false;
                }
                if (tailingNodeInSequence === void 0) {
                    tailingNodeInSequence = false;
                }
                this.setSelectedParams({
                    newValue: newValue,
                    clearSelection: clearSelection,
                    tailingNodeInSequence: tailingNodeInSequence,
                    rangeSelect: false
                });
            };
            RowNode.prototype.isRowPinned = function() {
                return this.rowPinned === constants_1.Constants.PINNED_TOP || this.rowPinned === constants_1.Constants.PINNED_BOTTOM;
            };
            RowNode.prototype.setSelectedParams = function(params) {
                var groupSelectsChildren = this.gridOptionsWrapper.isGroupSelectsChildren();
                var newValue = params.newValue === true;
                var clearSelection = params.clearSelection === true;
                var tailingNodeInSequence = params.tailingNodeInSequence === true;
                var rangeSelect = params.rangeSelect === true;
                var groupSelectsFiltered = groupSelectsChildren && params.groupSelectsFiltered === true;
                if (this.id === undefined) {
                    console.warn("ag-Grid: cannot select node until id for node is known");
                    return 0;
                }
                if (this.rowPinned) {
                    console.log("ag-Grid: cannot select pinned rows");
                    return 0;
                }
                if (this.footer) {
                    var count = this.sibling.setSelectedParams(params);
                    return count;
                }
                if (rangeSelect) {
                    var newRowClicked = this.selectionController.getLastSelectedNode() !== this;
                    var allowMultiSelect = this.gridOptionsWrapper.isRowSelectionMulti();
                    if (newRowClicked && allowMultiSelect) {
                        return this.doRowRangeSelection();
                    }
                }
                var updatedCount = 0;
                var skipThisNode = groupSelectsFiltered && this.group;
                if (!skipThisNode) {
                    var thisNodeWasSelected = this.selectThisNode(newValue);
                    if (thisNodeWasSelected) {
                        updatedCount++;
                    }
                }
                if (groupSelectsChildren && this.group) {
                    updatedCount += this.selectChildNodes(newValue, groupSelectsFiltered);
                }
                var actionWasOnThisNode = !tailingNodeInSequence;
                if (actionWasOnThisNode) {
                    if (newValue && (clearSelection || !this.gridOptionsWrapper.isRowSelectionMulti())) {
                        updatedCount += this.selectionController.clearOtherNodes(this);
                    }
                    if (updatedCount > 0) {
                        if (groupSelectsFiltered) {
                            this.calculatedSelectedForAllGroupNodes();
                        } else {
                            if (groupSelectsChildren && this.parent) {
                                this.parent.calculateSelectedFromChildrenBubbleUp();
                            }
                        }
                        var event_1 = {
                            type: events_1.Events.EVENT_SELECTION_CHANGED,
                            api: this.gridApi,
                            columnApi: this.columnApi
                        };
                        this.mainEventService.dispatchEvent(event_1);
                    }
                    if (newValue) {
                        this.selectionController.setLastSelectedNode(this);
                    }
                }
                return updatedCount;
            };
            RowNode.prototype.doRowRangeSelection = function() {
                var updatedCount = 0;
                var groupsSelectChildren = this.gridOptionsWrapper.isGroupSelectsChildren();
                var lastSelectedNode = this.selectionController.getLastSelectedNode();
                var nodesToSelect = this.rowModel.getNodesInRangeForSelection(lastSelectedNode, this);
                nodesToSelect.forEach(function(rowNode) {
                    if (rowNode.group && groupsSelectChildren) {
                        return;
                    }
                    var nodeWasSelected = rowNode.selectThisNode(true);
                    if (nodeWasSelected) {
                        updatedCount++;
                    }
                });
                if (groupsSelectChildren) {
                    this.calculatedSelectedForAllGroupNodes();
                }
                var event = {
                    type: events_1.Events.EVENT_SELECTION_CHANGED,
                    api: this.gridApi,
                    columnApi: this.columnApi
                };
                this.mainEventService.dispatchEvent(event);
                return updatedCount;
            };
            RowNode.prototype.isParentOfNode = function(potentialParent) {
                var parentNode = this.parent;
                while (parentNode) {
                    if (parentNode === potentialParent) {
                        return true;
                    }
                    parentNode = parentNode.parent;
                }
                return false;
            };
            RowNode.prototype.calculatedSelectedForAllGroupNodes = function() {
                var clientSideRowModel = this.rowModel;
                clientSideRowModel.getTopLevelNodes().forEach(function(topLevelNode) {
                    if (topLevelNode.group) {
                        topLevelNode.depthFirstSearch(function(childNode) {
                            if (childNode.group) {
                                childNode.calculateSelectedFromChildren();
                            }
                        });
                        topLevelNode.calculateSelectedFromChildren();
                    }
                });
            };
            RowNode.prototype.selectThisNode = function(newValue) {
                if (!this.selectable || this.selected === newValue) return false;
                this.selected = newValue;
                if (this.eventService) {
                    this.dispatchLocalEvent(this.createLocalRowEvent(RowNode.EVENT_ROW_SELECTED));
                }
                var event = this.createGlobalRowEvent(events_1.Events.EVENT_ROW_SELECTED);
                this.mainEventService.dispatchEvent(event);
                return true;
            };
            RowNode.prototype.selectChildNodes = function(newValue, groupSelectsFiltered) {
                var children = groupSelectsFiltered ? this.childrenAfterFilter : this.childrenAfterGroup;
                var updatedCount = 0;
                if (utils_1.Utils.missing(children)) {
                    return;
                }
                for (var i = 0; i < children.length; i++) {
                    updatedCount += children[i].setSelectedParams({
                        newValue: newValue,
                        clearSelection: false,
                        tailingNodeInSequence: true,
                        groupSelectsFiltered: groupSelectsFiltered
                    });
                }
                return updatedCount;
            };
            RowNode.prototype.addEventListener = function(eventType, listener) {
                if (!this.eventService) {
                    this.eventService = new eventService_1.EventService();
                }
                this.eventService.addEventListener(eventType, listener);
            };
            RowNode.prototype.removeEventListener = function(eventType, listener) {
                this.eventService.removeEventListener(eventType, listener);
            };
            RowNode.prototype.onMouseEnter = function() {
                this.dispatchLocalEvent(this.createLocalRowEvent(RowNode.EVENT_MOUSE_ENTER));
            };
            RowNode.prototype.onMouseLeave = function() {
                this.dispatchLocalEvent(this.createLocalRowEvent(RowNode.EVENT_MOUSE_LEAVE));
            };
            RowNode.prototype.getFirstChildOfFirstChild = function(rowGroupColumn) {
                var currentRowNode = this;
                var isCandidate = true;
                var foundFirstChildPath = false;
                var nodeToSwapIn;
                while (isCandidate && !foundFirstChildPath) {
                    var parentRowNode = currentRowNode.parent;
                    var firstChild = utils_1.Utils.exists(parentRowNode) && currentRowNode.firstChild;
                    if (firstChild) {
                        if (parentRowNode.rowGroupColumn === rowGroupColumn) {
                            foundFirstChildPath = true;
                            nodeToSwapIn = parentRowNode;
                        }
                    } else {
                        isCandidate = false;
                    }
                    currentRowNode = parentRowNode;
                }
                return foundFirstChildPath ? nodeToSwapIn : null;
            };
            RowNode.EVENT_ROW_SELECTED = "rowSelected";
            RowNode.EVENT_DATA_CHANGED = "dataChanged";
            RowNode.EVENT_CELL_CHANGED = "cellChanged";
            RowNode.EVENT_ALL_CHILDREN_COUNT_CHANGED = "allChildrenCountChanged";
            RowNode.EVENT_MOUSE_ENTER = "mouseEnter";
            RowNode.EVENT_MOUSE_LEAVE = "mouseLeave";
            RowNode.EVENT_HEIGHT_CHANGED = "heightChanged";
            RowNode.EVENT_TOP_CHANGED = "topChanged";
            RowNode.EVENT_FIRST_CHILD_CHANGED = "firstChildChanged";
            RowNode.EVENT_LAST_CHILD_CHANGED = "lastChildChanged";
            RowNode.EVENT_CHILD_INDEX_CHANGED = "childIndexChanged";
            RowNode.EVENT_ROW_INDEX_CHANGED = "rowIndexChanged";
            RowNode.EVENT_EXPANDED_CHANGED = "expandedChanged";
            RowNode.EVENT_SELECTABLE_CHANGED = "selectableChanged";
            RowNode.EVENT_UI_LEVEL_CHANGED = "uiLevelChanged";
            RowNode.EVENT_DRAGGING_CHANGED = "draggingChanged";
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], RowNode.prototype, "mainEventService", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], RowNode.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("selectionController"), __metadata("design:type", selectionController_1.SelectionController) ], RowNode.prototype, "selectionController", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], RowNode.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("valueService"), __metadata("design:type", valueService_1.ValueService) ], RowNode.prototype, "valueService", void 0);
            __decorate([ context_1.Autowired("rowModel"), __metadata("design:type", Object) ], RowNode.prototype, "rowModel", void 0);
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], RowNode.prototype, "context", void 0);
            __decorate([ context_1.Autowired("valueCache"), __metadata("design:type", valueCache_1.ValueCache) ], RowNode.prototype, "valueCache", void 0);
            __decorate([ context_1.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], RowNode.prototype, "columnApi", void 0);
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], RowNode.prototype, "gridApi", void 0);
            return RowNode;
        }();
        exports.RowNode = RowNode;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        var __param = this && this.__param || function(paramIndex, decorator) {
            return function(target, key) {
                decorator(target, key, paramIndex);
            };
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var logger_1 = __webpack_require__(12);
        var context_1 = __webpack_require__(0);
        var utils_1 = __webpack_require__(1);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var dragService_1 = __webpack_require__(40);
        var columnController_1 = __webpack_require__(4);
        var environment_1 = __webpack_require__(41);
        var DragSourceType;
        (function(DragSourceType) {
            DragSourceType[DragSourceType["ToolPanel"] = 0] = "ToolPanel";
            DragSourceType[DragSourceType["HeaderCell"] = 1] = "HeaderCell";
            DragSourceType[DragSourceType["RowDrag"] = 2] = "RowDrag";
        })(DragSourceType = exports.DragSourceType || (exports.DragSourceType = {}));
        var VDirection;
        (function(VDirection) {
            VDirection[VDirection["Up"] = 0] = "Up";
            VDirection[VDirection["Down"] = 1] = "Down";
        })(VDirection = exports.VDirection || (exports.VDirection = {}));
        var HDirection;
        (function(HDirection) {
            HDirection[HDirection["Left"] = 0] = "Left";
            HDirection[HDirection["Right"] = 1] = "Right";
        })(HDirection = exports.HDirection || (exports.HDirection = {}));
        var DragAndDropService = function() {
            function DragAndDropService() {
                this.dragSourceAndParamsList = [];
                this.dropTargets = [];
            }
            DragAndDropService_1 = DragAndDropService;
            DragAndDropService.prototype.init = function() {
                this.ePinnedIcon = utils_1.Utils.createIcon("columnMovePin", this.gridOptionsWrapper, null);
                this.ePlusIcon = utils_1.Utils.createIcon("columnMoveAdd", this.gridOptionsWrapper, null);
                this.eHiddenIcon = utils_1.Utils.createIcon("columnMoveHide", this.gridOptionsWrapper, null);
                this.eMoveIcon = utils_1.Utils.createIcon("columnMoveMove", this.gridOptionsWrapper, null);
                this.eLeftIcon = utils_1.Utils.createIcon("columnMoveLeft", this.gridOptionsWrapper, null);
                this.eRightIcon = utils_1.Utils.createIcon("columnMoveRight", this.gridOptionsWrapper, null);
                this.eGroupIcon = utils_1.Utils.createIcon("columnMoveGroup", this.gridOptionsWrapper, null);
                this.eAggregateIcon = utils_1.Utils.createIcon("columnMoveValue", this.gridOptionsWrapper, null);
                this.ePivotIcon = utils_1.Utils.createIcon("columnMovePivot", this.gridOptionsWrapper, null);
                this.eDropNotAllowedIcon = utils_1.Utils.createIcon("dropNotAllowed", this.gridOptionsWrapper, null);
            };
            DragAndDropService.prototype.setBeans = function(loggerFactory) {
                this.logger = loggerFactory.create("OldToolPanelDragAndDropService");
            };
            DragAndDropService.prototype.getStringType = function(type) {
                switch (type) {
                  case DragSourceType.RowDrag:
                    return "row";

                  case DragSourceType.HeaderCell:
                    return "headerCell";

                  case DragSourceType.ToolPanel:
                    return "toolPanel";

                  default:
                    console.warn("ag-Grid: bug - unknown drag type " + type);
                    return null;
                }
            };
            DragAndDropService.prototype.addDragSource = function(dragSource, allowTouch) {
                if (allowTouch === void 0) {
                    allowTouch = false;
                }
                var params = {
                    eElement: dragSource.eElement,
                    dragStartPixels: dragSource.dragStartPixels,
                    onDragStart: this.onDragStart.bind(this, dragSource),
                    onDragStop: this.onDragStop.bind(this),
                    onDragging: this.onDragging.bind(this)
                };
                this.dragSourceAndParamsList.push({
                    params: params,
                    dragSource: dragSource
                });
                this.dragService.addDragSource(params, allowTouch);
            };
            DragAndDropService.prototype.removeDragSource = function(dragSource) {
                var sourceAndParams = utils_1.Utils.find(this.dragSourceAndParamsList, function(item) {
                    return item.dragSource === dragSource;
                });
                if (sourceAndParams) {
                    this.dragService.removeDragSource(sourceAndParams.params);
                    utils_1.Utils.removeFromArray(this.dragSourceAndParamsList, sourceAndParams);
                }
            };
            DragAndDropService.prototype.destroy = function() {
                var _this = this;
                this.dragSourceAndParamsList.forEach(function(sourceAndParams) {
                    _this.dragService.removeDragSource(sourceAndParams.params);
                });
                this.dragSourceAndParamsList.length = 0;
            };
            DragAndDropService.prototype.nudge = function() {
                if (this.dragging) {
                    this.onDragging(this.eventLastTime, true);
                }
            };
            DragAndDropService.prototype.onDragStart = function(dragSource, mouseEvent) {
                this.dragging = true;
                this.dragSource = dragSource;
                this.eventLastTime = mouseEvent;
                this.dragItem = this.dragSource.dragItemCallback();
                this.lastDropTarget = this.dragSource.dragSourceDropTarget;
                if (this.dragSource.dragStarted) {
                    this.dragSource.dragStarted();
                }
                this.createGhost();
            };
            DragAndDropService.prototype.onDragStop = function(mouseEvent) {
                this.eventLastTime = null;
                this.dragging = false;
                if (this.dragSource.dragStopped) {
                    this.dragSource.dragStopped();
                }
                if (this.lastDropTarget && this.lastDropTarget.onDragStop) {
                    var draggingEvent = this.createDropTargetEvent(this.lastDropTarget, mouseEvent, null, null, false);
                    this.lastDropTarget.onDragStop(draggingEvent);
                }
                this.lastDropTarget = null;
                this.dragItem = null;
                this.removeGhost();
            };
            DragAndDropService.prototype.onDragging = function(mouseEvent, fromNudge) {
                var hDirection = this.workOutHDirection(mouseEvent);
                var vDirection = this.workOutVDirection(mouseEvent);
                this.eventLastTime = mouseEvent;
                this.positionGhost(mouseEvent);
                var dropTarget = utils_1.Utils.find(this.dropTargets, this.isMouseOnDropTarget.bind(this, mouseEvent));
                if (dropTarget !== this.lastDropTarget) {
                    this.leaveLastTargetIfExists(mouseEvent, hDirection, vDirection, fromNudge);
                    this.enterDragTargetIfExists(dropTarget, mouseEvent, hDirection, vDirection, fromNudge);
                    this.lastDropTarget = dropTarget;
                } else if (dropTarget) {
                    var draggingEvent = this.createDropTargetEvent(dropTarget, mouseEvent, hDirection, vDirection, fromNudge);
                    dropTarget.onDragging(draggingEvent);
                }
            };
            DragAndDropService.prototype.enterDragTargetIfExists = function(dropTarget, mouseEvent, hDirection, vDirection, fromNudge) {
                if (!dropTarget) {
                    return;
                }
                var dragEnterEvent = this.createDropTargetEvent(dropTarget, mouseEvent, hDirection, vDirection, fromNudge);
                dropTarget.onDragEnter(dragEnterEvent);
                this.setGhostIcon(dropTarget.getIconName ? dropTarget.getIconName() : null);
            };
            DragAndDropService.prototype.leaveLastTargetIfExists = function(mouseEvent, hDirection, vDirection, fromNudge) {
                if (!this.lastDropTarget) {
                    return;
                }
                var dragLeaveEvent = this.createDropTargetEvent(this.lastDropTarget, mouseEvent, hDirection, vDirection, fromNudge);
                this.lastDropTarget.onDragLeave(dragLeaveEvent);
                this.setGhostIcon(null);
            };
            DragAndDropService.prototype.getAllContainersFromDropTarget = function(dropTarget) {
                var containers = [ dropTarget.getContainer() ];
                var secondaryContainers = dropTarget.getSecondaryContainers ? dropTarget.getSecondaryContainers() : null;
                if (secondaryContainers) {
                    containers = containers.concat(secondaryContainers);
                }
                return containers;
            };
            DragAndDropService.prototype.isMouseOnDropTarget = function(mouseEvent, dropTarget) {
                var allContainers = this.getAllContainersFromDropTarget(dropTarget);
                var mouseOverTarget = false;
                allContainers.forEach(function(eContainer) {
                    if (!eContainer) {
                        return;
                    }
                    var rect = eContainer.getBoundingClientRect();
                    if (rect.width === 0 || rect.height === 0) {
                        return;
                    }
                    var horizontalFit = mouseEvent.clientX >= rect.left && mouseEvent.clientX <= rect.right;
                    var verticalFit = mouseEvent.clientY >= rect.top && mouseEvent.clientY <= rect.bottom;
                    if (horizontalFit && verticalFit) {
                        mouseOverTarget = true;
                    }
                });
                if (mouseOverTarget) {
                    var mouseOverTargetAndInterested = dropTarget.isInterestedIn(this.dragSource.type);
                    return mouseOverTargetAndInterested;
                } else {
                    return false;
                }
            };
            DragAndDropService.prototype.addDropTarget = function(dropTarget) {
                this.dropTargets.push(dropTarget);
            };
            DragAndDropService.prototype.workOutHDirection = function(event) {
                if (this.eventLastTime.clientX > event.clientX) {
                    return HDirection.Left;
                } else if (this.eventLastTime.clientX < event.clientX) {
                    return HDirection.Right;
                } else {
                    return null;
                }
            };
            DragAndDropService.prototype.workOutVDirection = function(event) {
                if (this.eventLastTime.clientY > event.clientY) {
                    return VDirection.Up;
                } else if (this.eventLastTime.clientY < event.clientY) {
                    return VDirection.Down;
                } else {
                    return null;
                }
            };
            DragAndDropService.prototype.createDropTargetEvent = function(dropTarget, event, hDirection, vDirection, fromNudge) {
                var rect = dropTarget.getContainer().getBoundingClientRect();
                var x = event.clientX - rect.left;
                var y = event.clientY - rect.top;
                var dropTargetEvent = {
                    event: event,
                    x: x,
                    y: y,
                    vDirection: vDirection,
                    hDirection: hDirection,
                    dragSource: this.dragSource,
                    fromNudge: fromNudge,
                    dragItem: this.dragItem
                };
                return dropTargetEvent;
            };
            DragAndDropService.prototype.positionGhost = function(event) {
                var ghostRect = this.eGhost.getBoundingClientRect();
                var ghostHeight = ghostRect.height;
                var browserWidth = utils_1.Utils.getBodyWidth() - 2;
                var browserHeight = utils_1.Utils.getBodyHeight() - 2;
                var top = event.pageY - ghostHeight / 2;
                var left = event.pageX - 30;
                var usrDocument = this.gridOptionsWrapper.getDocument();
                var windowScrollY = window.pageYOffset || usrDocument.documentElement.scrollTop;
                var windowScrollX = window.pageXOffset || usrDocument.documentElement.scrollLeft;
                if (browserWidth > 0) {
                    if (left + this.eGhost.clientWidth > browserWidth + windowScrollX) {
                        left = browserWidth + windowScrollX - this.eGhost.clientWidth;
                    }
                }
                if (left < 0) {
                    left = 0;
                }
                if (browserHeight > 0) {
                    if (top + this.eGhost.clientHeight > browserHeight + windowScrollY) {
                        top = browserHeight + windowScrollY - this.eGhost.clientHeight;
                    }
                }
                if (top < 0) {
                    top = 0;
                }
                this.eGhost.style.left = left + "px";
                this.eGhost.style.top = top + "px";
            };
            DragAndDropService.prototype.removeGhost = function() {
                if (this.eGhost && this.eGhostParent) {
                    this.eGhostParent.removeChild(this.eGhost);
                }
                this.eGhost = null;
            };
            DragAndDropService.prototype.createGhost = function() {
                this.eGhost = utils_1.Utils.loadTemplate(DragAndDropService_1.GHOST_TEMPLATE);
                utils_1.Utils.addCssClass(this.eGhost, this.environment.getTheme());
                this.eGhostIcon = this.eGhost.querySelector(".ag-dnd-ghost-icon");
                this.setGhostIcon(null);
                var eText = this.eGhost.querySelector(".ag-dnd-ghost-label");
                eText.innerHTML = this.dragSource.dragItemName;
                this.eGhost.style.height = "25px";
                this.eGhost.style.top = "20px";
                this.eGhost.style.left = "20px";
                var usrDocument = this.gridOptionsWrapper.getDocument();
                this.eGhostParent = usrDocument.querySelector("body");
                if (!this.eGhostParent) {
                    console.warn("ag-Grid: could not find document body, it is needed for dragging columns");
                } else {
                    this.eGhostParent.appendChild(this.eGhost);
                }
            };
            DragAndDropService.prototype.setGhostIcon = function(iconName, shake) {
                if (shake === void 0) {
                    shake = false;
                }
                utils_1.Utils.removeAllChildren(this.eGhostIcon);
                var eIcon;
                switch (iconName) {
                  case DragAndDropService_1.ICON_ADD:
                    eIcon = this.ePlusIcon;
                    break;

                  case DragAndDropService_1.ICON_PINNED:
                    eIcon = this.ePinnedIcon;
                    break;

                  case DragAndDropService_1.ICON_MOVE:
                    eIcon = this.eMoveIcon;
                    break;

                  case DragAndDropService_1.ICON_LEFT:
                    eIcon = this.eLeftIcon;
                    break;

                  case DragAndDropService_1.ICON_RIGHT:
                    eIcon = this.eRightIcon;
                    break;

                  case DragAndDropService_1.ICON_GROUP:
                    eIcon = this.eGroupIcon;
                    break;

                  case DragAndDropService_1.ICON_AGGREGATE:
                    eIcon = this.eAggregateIcon;
                    break;

                  case DragAndDropService_1.ICON_PIVOT:
                    eIcon = this.ePivotIcon;
                    break;

                  case DragAndDropService_1.ICON_NOT_ALLOWED:
                    eIcon = this.eDropNotAllowedIcon;
                    break;

                  default:
                    eIcon = this.eHiddenIcon;
                    break;
                }
                this.eGhostIcon.appendChild(eIcon);
                utils_1.Utils.addOrRemoveCssClass(this.eGhostIcon, "ag-shake-left-to-right", shake);
            };
            DragAndDropService.ICON_PINNED = "pinned";
            DragAndDropService.ICON_ADD = "add";
            DragAndDropService.ICON_MOVE = "move";
            DragAndDropService.ICON_LEFT = "left";
            DragAndDropService.ICON_RIGHT = "right";
            DragAndDropService.ICON_GROUP = "group";
            DragAndDropService.ICON_AGGREGATE = "aggregate";
            DragAndDropService.ICON_PIVOT = "pivot";
            DragAndDropService.ICON_NOT_ALLOWED = "notAllowed";
            DragAndDropService.GHOST_TEMPLATE = '<div class="ag-dnd-ghost">' + '  <span class="ag-dnd-ghost-icon ag-shake-left-to-right"></span>' + '  <div class="ag-dnd-ghost-label">' + "  </div>" + "</div>";
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], DragAndDropService.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("dragService"), __metadata("design:type", dragService_1.DragService) ], DragAndDropService.prototype, "dragService", void 0);
            __decorate([ context_1.Autowired("environment"), __metadata("design:type", environment_1.Environment) ], DragAndDropService.prototype, "environment", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], DragAndDropService.prototype, "columnController", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], DragAndDropService.prototype, "init", null);
            __decorate([ __param(0, context_1.Qualifier("loggerFactory")), __metadata("design:type", Function), __metadata("design:paramtypes", [ logger_1.LoggerFactory ]), __metadata("design:returntype", void 0) ], DragAndDropService.prototype, "setBeans", null);
            __decorate([ context_1.PreDestroy, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], DragAndDropService.prototype, "destroy", null);
            DragAndDropService = DragAndDropService_1 = __decorate([ context_1.Bean("dragAndDropService") ], DragAndDropService);
            return DragAndDropService;
            var DragAndDropService_1;
        }();
        exports.DragAndDropService = DragAndDropService;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var expressionService_1 = __webpack_require__(19);
        var columnController_1 = __webpack_require__(4);
        var context_1 = __webpack_require__(0);
        var utils_1 = __webpack_require__(1);
        var events_1 = __webpack_require__(5);
        var eventService_1 = __webpack_require__(3);
        var valueCache_1 = __webpack_require__(33);
        var ValueService = function() {
            function ValueService() {
                this.initialised = false;
            }
            ValueService.prototype.init = function() {
                this.cellExpressions = this.gridOptionsWrapper.isEnableCellExpressions();
                this.initialised = true;
            };
            ValueService.prototype.getValue = function(column, rowNode, forFilter, ignoreAggData) {
                if (forFilter === void 0) {
                    forFilter = false;
                }
                if (ignoreAggData === void 0) {
                    ignoreAggData = false;
                }
                if (!this.initialised) {
                    this.init();
                }
                var colDef = column.getColDef();
                var field = colDef.field;
                var colId = column.getId();
                var data = rowNode.data;
                var result;
                var groupDataExists = rowNode.groupData && rowNode.groupData[colId] !== undefined;
                var aggDataExists = !ignoreAggData && rowNode.aggData && rowNode.aggData[colId] !== undefined;
                if (forFilter && colDef.filterValueGetter) {
                    result = this.executeValueGetter(colDef.filterValueGetter, data, column, rowNode);
                } else if (groupDataExists) {
                    result = rowNode.groupData[colId];
                } else if (aggDataExists) {
                    result = rowNode.aggData[colId];
                } else if (colDef.valueGetter) {
                    result = this.executeValueGetter(colDef.valueGetter, data, column, rowNode);
                } else if (field && data) {
                    result = utils_1._.getValueUsingField(data, field, column.isFieldContainsDots());
                } else {
                    result = undefined;
                }
                if (this.cellExpressions && typeof result === "string" && result.indexOf("=") === 0) {
                    var cellValueGetter = result.substring(1);
                    result = this.executeValueGetter(cellValueGetter, data, column, rowNode);
                }
                return result;
            };
            ValueService.prototype.setValue = function(rowNode, colKey, newValue) {
                var column = this.columnController.getPrimaryColumn(colKey);
                if (!rowNode || !column) {
                    return;
                }
                var data = rowNode.data;
                if (utils_1._.missing(data)) {
                    rowNode.data = {};
                }
                var _a = column.getColDef(), field = _a.field, newValueHandler = _a.newValueHandler, valueSetter = _a.valueSetter;
                if (utils_1._.missing(field) && utils_1._.missing(newValueHandler) && utils_1._.missing(valueSetter)) {
                    console.warn("ag-Grid: you need either field or valueSetter set on colDef for editing to work");
                    return;
                }
                var params = {
                    node: rowNode,
                    data: rowNode.data,
                    oldValue: this.getValue(column, rowNode),
                    newValue: newValue,
                    colDef: column.getColDef(),
                    column: column,
                    api: this.gridOptionsWrapper.getApi(),
                    columnApi: this.gridOptionsWrapper.getColumnApi(),
                    context: this.gridOptionsWrapper.getContext()
                };
                params.newValue = newValue;
                var valueWasDifferent;
                if (utils_1._.exists(newValueHandler)) {
                    valueWasDifferent = newValueHandler(params);
                } else if (utils_1._.exists(valueSetter)) {
                    valueWasDifferent = this.expressionService.evaluate(valueSetter, params);
                } else {
                    valueWasDifferent = this.setValueUsingField(data, field, newValue, column.isFieldContainsDots());
                }
                if (valueWasDifferent === undefined) {
                    valueWasDifferent = true;
                }
                if (!valueWasDifferent) {
                    return;
                }
                rowNode.resetQuickFilterAggregateText();
                this.valueCache.onDataChanged();
                params.newValue = this.getValue(column, rowNode);
                if (typeof column.getColDef().onCellValueChanged === "function") {
                    setTimeout(function() {
                        return column.getColDef().onCellValueChanged(params);
                    }, 0);
                }
                var event = {
                    type: events_1.Events.EVENT_CELL_VALUE_CHANGED,
                    event: null,
                    rowIndex: rowNode.rowIndex,
                    rowPinned: rowNode.rowPinned,
                    column: params.column,
                    api: params.api,
                    colDef: params.colDef,
                    columnApi: params.columnApi,
                    context: params.context,
                    data: rowNode.data,
                    node: rowNode,
                    oldValue: params.oldValue,
                    newValue: params.newValue,
                    value: params.newValue
                };
                this.eventService.dispatchEvent(event);
            };
            ValueService.prototype.setValueUsingField = function(data, field, newValue, isFieldContainsDots) {
                var valuesAreSame;
                if (!isFieldContainsDots) {
                    data[field] = newValue;
                } else {
                    var fieldPieces = field.split(".");
                    var currentObject = data;
                    while (fieldPieces.length > 0 && currentObject) {
                        var fieldPiece = fieldPieces.shift();
                        if (fieldPieces.length === 0) {
                            currentObject[fieldPiece] = newValue;
                        } else {
                            currentObject = currentObject[fieldPiece];
                        }
                    }
                }
                return !valuesAreSame;
            };
            ValueService.prototype.executeValueGetter = function(filterValueGetter, data, column, rowNode) {
                var colId = column.getId();
                var valueFromCache = this.valueCache.getValue(rowNode, colId);
                if (valueFromCache !== undefined) {
                    return valueFromCache;
                }
                var params = {
                    data: data,
                    node: rowNode,
                    column: column,
                    colDef: column.getColDef(),
                    api: this.gridOptionsWrapper.getApi(),
                    columnApi: this.gridOptionsWrapper.getColumnApi(),
                    context: this.gridOptionsWrapper.getContext(),
                    getValue: this.getValueCallback.bind(this, rowNode)
                };
                var result = this.expressionService.evaluate(filterValueGetter, params);
                this.valueCache.setValue(rowNode, colId, result);
                return result;
            };
            ValueService.prototype.getValueCallback = function(node, field) {
                var otherColumn = this.columnController.getPrimaryColumn(field);
                if (otherColumn) {
                    return this.getValue(otherColumn, node);
                } else {
                    return null;
                }
            };
            ValueService.prototype.getKeyForNode = function(col, rowNode) {
                var value = this.getValue(col, rowNode);
                var result;
                var keyCreator = col.getColDef().keyCreator;
                if (keyCreator) {
                    result = keyCreator({
                        value: value
                    });
                } else {
                    result = value;
                }
                if (typeof result === "string" || result === null || result === undefined) {
                    return result;
                }
                result = String(result);
                if (result === "[object Object]") {
                    utils_1._.doOnce(function() {
                        console.warn("ag-Grid: a column you are grouping or pivoting by has objects as values. If you want to group by complex objects then either a) use a colDef.keyCreator (se ag-Grid docs) or b) to toString() on the object to return a key");
                    }, "getKeyForNode - warn about [object,object]");
                }
                return result;
            };
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], ValueService.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("expressionService"), __metadata("design:type", expressionService_1.ExpressionService) ], ValueService.prototype, "expressionService", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], ValueService.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], ValueService.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("valueCache"), __metadata("design:type", valueCache_1.ValueCache) ], ValueService.prototype, "valueCache", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], ValueService.prototype, "init", null);
            ValueService = __decorate([ context_1.Bean("valueService") ], ValueService);
            return ValueService;
        }();
        exports.ValueService = ValueService;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        var __param = this && this.__param || function(paramIndex, decorator) {
            return function(target, key) {
                decorator(target, key, paramIndex);
            };
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var context_1 = __webpack_require__(0);
        var context_2 = __webpack_require__(0);
        var logger_1 = __webpack_require__(12);
        var eventService_1 = __webpack_require__(3);
        var events_1 = __webpack_require__(5);
        var context_3 = __webpack_require__(0);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var context_4 = __webpack_require__(0);
        var constants_1 = __webpack_require__(9);
        var columnApi_1 = __webpack_require__(7);
        var gridApi_1 = __webpack_require__(6);
        var SelectionController = function() {
            function SelectionController() {}
            SelectionController.prototype.setBeans = function(loggerFactory) {
                this.logger = loggerFactory.create("SelectionController");
                this.reset();
                if (this.gridOptionsWrapper.isRowModelDefault()) {
                    this.eventService.addEventListener(events_1.Events.EVENT_ROW_DATA_CHANGED, this.reset.bind(this));
                } else {
                    this.logger.log("dont know what to do here");
                }
            };
            SelectionController.prototype.init = function() {
                this.groupSelectsChildren = this.gridOptionsWrapper.isGroupSelectsChildren();
                this.eventService.addEventListener(events_1.Events.EVENT_ROW_SELECTED, this.onRowSelected.bind(this));
            };
            SelectionController.prototype.setLastSelectedNode = function(rowNode) {
                this.lastSelectedNode = rowNode;
            };
            SelectionController.prototype.getLastSelectedNode = function() {
                return this.lastSelectedNode;
            };
            SelectionController.prototype.getSelectedNodes = function() {
                var selectedNodes = [];
                utils_1.Utils.iterateObject(this.selectedNodes, function(key, rowNode) {
                    if (rowNode) {
                        selectedNodes.push(rowNode);
                    }
                });
                return selectedNodes;
            };
            SelectionController.prototype.getSelectedRows = function() {
                var selectedRows = [];
                utils_1.Utils.iterateObject(this.selectedNodes, function(key, rowNode) {
                    if (rowNode && rowNode.data) {
                        selectedRows.push(rowNode.data);
                    }
                });
                return selectedRows;
            };
            SelectionController.prototype.removeGroupsFromSelection = function() {
                var _this = this;
                utils_1.Utils.iterateObject(this.selectedNodes, function(key, rowNode) {
                    if (rowNode && rowNode.group) {
                        _this.selectedNodes[rowNode.id] = undefined;
                    }
                });
            };
            SelectionController.prototype.updateGroupsFromChildrenSelections = function() {
                if (this.rowModel.getType() !== constants_1.Constants.ROW_MODEL_TYPE_CLIENT_SIDE) {
                    console.warn("updateGroupsFromChildrenSelections not available when rowModel is not normal");
                }
                var clientSideRowModel = this.rowModel;
                clientSideRowModel.getTopLevelNodes().forEach(function(rowNode) {
                    rowNode.depthFirstSearch(function(rowNode) {
                        if (rowNode.group) {
                            rowNode.calculateSelectedFromChildren();
                        }
                    });
                });
            };
            SelectionController.prototype.getNodeForIdIfSelected = function(id) {
                return this.selectedNodes[id];
            };
            SelectionController.prototype.clearOtherNodes = function(rowNodeToKeepSelected) {
                var _this = this;
                var groupsToRefresh = {};
                var updatedCount = 0;
                utils_1.Utils.iterateObject(this.selectedNodes, function(key, otherRowNode) {
                    if (otherRowNode && otherRowNode.id !== rowNodeToKeepSelected.id) {
                        var rowNode = _this.selectedNodes[otherRowNode.id];
                        updatedCount += rowNode.setSelectedParams({
                            newValue: false,
                            clearSelection: false,
                            tailingNodeInSequence: true
                        });
                        if (_this.groupSelectsChildren && otherRowNode.parent) {
                            groupsToRefresh[otherRowNode.parent.id] = otherRowNode.parent;
                        }
                    }
                });
                utils_1.Utils.iterateObject(groupsToRefresh, function(key, group) {
                    group.calculateSelectedFromChildren();
                });
                return updatedCount;
            };
            SelectionController.prototype.onRowSelected = function(event) {
                var rowNode = event.node;
                if (this.groupSelectsChildren && rowNode.group) {
                    return;
                }
                if (rowNode.isSelected()) {
                    this.selectedNodes[rowNode.id] = rowNode;
                } else {
                    this.selectedNodes[rowNode.id] = undefined;
                }
            };
            SelectionController.prototype.syncInRowNode = function(rowNode, oldNode) {
                this.syncInOldRowNode(rowNode, oldNode);
                this.syncInNewRowNode(rowNode);
            };
            SelectionController.prototype.syncInOldRowNode = function(rowNode, oldNode) {
                var oldNodeHasDifferentId = utils_1.Utils.exists(oldNode) && rowNode.id !== oldNode.id;
                if (oldNodeHasDifferentId) {
                    var oldNodeSelected = utils_1.Utils.exists(this.selectedNodes[oldNode.id]);
                    if (oldNodeSelected) {
                        this.selectedNodes[oldNode.id] = oldNode;
                    }
                }
            };
            SelectionController.prototype.syncInNewRowNode = function(rowNode) {
                if (utils_1.Utils.exists(this.selectedNodes[rowNode.id])) {
                    rowNode.setSelectedInitialValue(true);
                    this.selectedNodes[rowNode.id] = rowNode;
                } else {
                    rowNode.setSelectedInitialValue(false);
                }
            };
            SelectionController.prototype.reset = function() {
                this.logger.log("reset");
                this.selectedNodes = {};
                this.lastSelectedNode = null;
            };
            SelectionController.prototype.getBestCostNodeSelection = function() {
                if (this.rowModel.getType() !== constants_1.Constants.ROW_MODEL_TYPE_CLIENT_SIDE) {
                    console.warn("getBestCostNodeSelection is only avilable when using normal row model");
                }
                var clientSideRowModel = this.rowModel;
                var topLevelNodes = clientSideRowModel.getTopLevelNodes();
                if (topLevelNodes === null) {
                    console.warn("selectAll not available doing rowModel=virtual");
                    return;
                }
                var result = [];
                function traverse(nodes) {
                    for (var i = 0, l = nodes.length; i < l; i++) {
                        var node = nodes[i];
                        if (node.isSelected()) {
                            result.push(node);
                        } else {
                            if (node.group && node.children) {
                                traverse(node.children);
                            }
                        }
                    }
                }
                traverse(topLevelNodes);
                return result;
            };
            SelectionController.prototype.setRowModel = function(rowModel) {
                this.rowModel = rowModel;
            };
            SelectionController.prototype.isEmpty = function() {
                var count = 0;
                utils_1.Utils.iterateObject(this.selectedNodes, function(nodeId, rowNode) {
                    if (rowNode) {
                        count++;
                    }
                });
                return count === 0;
            };
            SelectionController.prototype.deselectAllRowNodes = function(justFiltered) {
                if (justFiltered === void 0) {
                    justFiltered = false;
                }
                var callback = function(rowNode) {
                    return rowNode.selectThisNode(false);
                };
                var rowModelClientSide = this.rowModel.getType() === constants_1.Constants.ROW_MODEL_TYPE_CLIENT_SIDE;
                if (justFiltered) {
                    if (!rowModelClientSide) {
                        console.error("ag-Grid: selecting just filtered only works with In Memory Row Model");
                        return;
                    }
                    var clientSideRowModel = this.rowModel;
                    clientSideRowModel.forEachNodeAfterFilter(callback);
                } else {
                    utils_1.Utils.iterateObject(this.selectedNodes, function(id, rowNode) {
                        if (rowNode) {
                            callback(rowNode);
                        }
                    });
                    this.reset();
                }
                if (rowModelClientSide && this.groupSelectsChildren) {
                    this.updateGroupsFromChildrenSelections();
                }
                var event = {
                    type: events_1.Events.EVENT_SELECTION_CHANGED,
                    api: this.gridApi,
                    columnApi: this.columnApi
                };
                this.eventService.dispatchEvent(event);
            };
            SelectionController.prototype.selectAllRowNodes = function(justFiltered) {
                if (justFiltered === void 0) {
                    justFiltered = false;
                }
                if (this.rowModel.getType() !== constants_1.Constants.ROW_MODEL_TYPE_CLIENT_SIDE) {
                    throw "selectAll only available with normal row model, ie not " + this.rowModel.getType();
                }
                var clientSideRowModel = this.rowModel;
                var callback = function(rowNode) {
                    return rowNode.selectThisNode(true);
                };
                if (justFiltered) {
                    clientSideRowModel.forEachNodeAfterFilter(callback);
                } else {
                    clientSideRowModel.forEachNode(callback);
                }
                if (this.rowModel.getType() === constants_1.Constants.ROW_MODEL_TYPE_CLIENT_SIDE && this.groupSelectsChildren) {
                    this.updateGroupsFromChildrenSelections();
                }
                var event = {
                    type: events_1.Events.EVENT_SELECTION_CHANGED,
                    api: this.gridApi,
                    columnApi: this.columnApi
                };
                this.eventService.dispatchEvent(event);
            };
            SelectionController.prototype.selectNode = function(rowNode, tryMulti) {
                rowNode.setSelectedParams({
                    newValue: true,
                    clearSelection: !tryMulti
                });
            };
            SelectionController.prototype.deselectIndex = function(rowIndex) {
                var node = this.rowModel.getRow(rowIndex);
                this.deselectNode(node);
            };
            SelectionController.prototype.deselectNode = function(rowNode) {
                rowNode.setSelectedParams({
                    newValue: false,
                    clearSelection: false
                });
            };
            SelectionController.prototype.selectIndex = function(index, tryMulti) {
                var node = this.rowModel.getRow(index);
                this.selectNode(node, tryMulti);
            };
            __decorate([ context_3.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], SelectionController.prototype, "eventService", void 0);
            __decorate([ context_3.Autowired("rowModel"), __metadata("design:type", Object) ], SelectionController.prototype, "rowModel", void 0);
            __decorate([ context_3.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], SelectionController.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_3.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], SelectionController.prototype, "columnApi", void 0);
            __decorate([ context_3.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], SelectionController.prototype, "gridApi", void 0);
            __decorate([ __param(0, context_2.Qualifier("loggerFactory")), __metadata("design:type", Function), __metadata("design:paramtypes", [ logger_1.LoggerFactory ]), __metadata("design:returntype", void 0) ], SelectionController.prototype, "setBeans", null);
            __decorate([ context_4.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], SelectionController.prototype, "init", null);
            SelectionController = __decorate([ context_1.Bean("selectionController") ], SelectionController);
            return SelectionController;
        }();
        exports.SelectionController = SelectionController;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var popupService_1 = __webpack_require__(35);
        var valueService_1 = __webpack_require__(16);
        var columnController_1 = __webpack_require__(4);
        var columnApi_1 = __webpack_require__(7);
        var context_1 = __webpack_require__(0);
        var eventService_1 = __webpack_require__(3);
        var events_1 = __webpack_require__(5);
        var gridApi_1 = __webpack_require__(6);
        var componentResolver_1 = __webpack_require__(27);
        var FilterManager = function() {
            function FilterManager() {
                this.allFilters = {};
                this.quickFilter = null;
                this.quickFilterParts = null;
            }
            FilterManager_1 = FilterManager;
            FilterManager.prototype.init = function() {
                this.eventService.addEventListener(events_1.Events.EVENT_ROW_DATA_CHANGED, this.onNewRowsLoaded.bind(this));
                this.eventService.addEventListener(events_1.Events.EVENT_NEW_COLUMNS_LOADED, this.onNewColumnsLoaded.bind(this));
                this.quickFilter = this.parseQuickFilter(this.gridOptionsWrapper.getQuickFilterText());
                this.setQuickFilterParts();
                this.checkExternalFilter();
            };
            FilterManager.prototype.setQuickFilterParts = function() {
                if (this.quickFilter) {
                    this.quickFilterParts = this.quickFilter.split(" ");
                } else {
                    this.quickFilterParts = null;
                }
            };
            FilterManager.prototype.setFilterModel = function(model) {
                var _this = this;
                var allPromises = [];
                if (model) {
                    var modelKeys_1 = Object.keys(model);
                    utils_1.Utils.iterateObject(this.allFilters, function(colId, filterWrapper) {
                        utils_1.Utils.removeFromArray(modelKeys_1, colId);
                        var newModel = model[colId];
                        _this.setModelOnFilterWrapper(filterWrapper.filterPromise, newModel);
                        allPromises.push(filterWrapper.filterPromise);
                    });
                    utils_1.Utils.iterateArray(modelKeys_1, function(colId) {
                        var column = _this.columnController.getPrimaryColumn(colId);
                        if (!column) {
                            console.warn("Warning ag-grid setFilterModel - no column found for colId " + colId);
                            return;
                        }
                        var filterWrapper = _this.getOrCreateFilterWrapper(column);
                        _this.setModelOnFilterWrapper(filterWrapper.filterPromise, model[colId]);
                        allPromises.push(filterWrapper.filterPromise);
                    });
                } else {
                    utils_1.Utils.iterateObject(this.allFilters, function(key, filterWrapper) {
                        _this.setModelOnFilterWrapper(filterWrapper.filterPromise, null);
                        allPromises.push(filterWrapper.filterPromise);
                    });
                }
                utils_1.Promise.all(allPromises).then(function(whatever) {
                    _this.onFilterChanged();
                });
            };
            FilterManager.prototype.setModelOnFilterWrapper = function(filterPromise, newModel) {
                filterPromise.then(function(filter) {
                    if (typeof filter.setModel !== "function") {
                        console.warn("Warning ag-grid - filter missing setModel method, which is needed for setFilterModel");
                        return;
                    }
                    filter.setModel(newModel);
                });
            };
            FilterManager.prototype.getFilterModel = function() {
                var result = {};
                utils_1.Utils.iterateObject(this.allFilters, function(key, filterWrapper) {
                    var filterPromise = filterWrapper.filterPromise;
                    var filter = filterPromise.resolveNow(null, function(filter) {
                        return filter;
                    });
                    if (filter == null) {
                        return null;
                    }
                    if (typeof filter.getModel !== "function") {
                        console.warn("Warning ag-grid - filter API missing getModel method, which is needed for getFilterModel");
                        return;
                    }
                    var model = filter.getModel();
                    if (utils_1.Utils.exists(model)) {
                        result[key] = model;
                    }
                });
                return result;
            };
            FilterManager.prototype.isAdvancedFilterPresent = function() {
                return this.advancedFilterPresent;
            };
            FilterManager.prototype.setAdvancedFilterPresent = function() {
                var atLeastOneActive = false;
                utils_1.Utils.iterateObject(this.allFilters, function(key, filterWrapper) {
                    if (filterWrapper.filterPromise.resolveNow(false, function(filter) {
                        return filter.isFilterActive();
                    })) {
                        atLeastOneActive = true;
                    }
                });
                this.advancedFilterPresent = atLeastOneActive;
            };
            FilterManager.prototype.updateFilterFlagInColumns = function(source) {
                utils_1.Utils.iterateObject(this.allFilters, function(key, filterWrapper) {
                    var filterActive = filterWrapper.filterPromise.resolveNow(false, function(filter) {
                        return filter.isFilterActive();
                    });
                    filterWrapper.column.setFilterActive(filterActive, source);
                });
            };
            FilterManager.prototype.isAnyFilterPresent = function() {
                return this.isQuickFilterPresent() || this.advancedFilterPresent || this.externalFilterPresent;
            };
            FilterManager.prototype.doesFilterPass = function(node, filterToSkip) {
                var data = node.data;
                var colKeys = Object.keys(this.allFilters);
                for (var i = 0, l = colKeys.length; i < l; i++) {
                    var colId = colKeys[i];
                    var filterWrapper = this.allFilters[colId];
                    if (filterWrapper === undefined) {
                        continue;
                    }
                    var filter = filterWrapper.filterPromise.resolveNow(undefined, function(filter) {
                        return filter;
                    });
                    if (filter === undefined) {
                        continue;
                    }
                    if (filter === filterToSkip) {
                        continue;
                    }
                    if (!filter.isFilterActive()) {
                        continue;
                    }
                    if (!filter.doesFilterPass) {
                        console.error("Filter is missing method doesFilterPass");
                    }
                    var params = {
                        node: node,
                        data: data
                    };
                    if (!filter.doesFilterPass(params)) {
                        return false;
                    }
                }
                return true;
            };
            FilterManager.prototype.parseQuickFilter = function(newFilter) {
                if (utils_1.Utils.missing(newFilter) || newFilter === "") {
                    return null;
                }
                if (this.gridOptionsWrapper.isRowModelInfinite()) {
                    console.warn("ag-grid: cannot do quick filtering when doing virtual paging");
                    return null;
                }
                return newFilter.toUpperCase();
            };
            FilterManager.prototype.setQuickFilter = function(newFilter) {
                var parsedFilter = this.parseQuickFilter(newFilter);
                if (this.quickFilter !== parsedFilter) {
                    this.quickFilter = parsedFilter;
                    this.setQuickFilterParts();
                    this.onFilterChanged();
                }
            };
            FilterManager.prototype.checkExternalFilter = function() {
                this.externalFilterPresent = this.gridOptionsWrapper.isExternalFilterPresent();
            };
            FilterManager.prototype.onFilterChanged = function() {
                this.setAdvancedFilterPresent();
                this.updateFilterFlagInColumns("filterChanged");
                this.checkExternalFilter();
                utils_1.Utils.iterateObject(this.allFilters, function(key, filterWrapper) {
                    filterWrapper.filterPromise.then(function(filter) {
                        if (filter.onAnyFilterChanged) {
                            filter.onAnyFilterChanged();
                        }
                    });
                });
                var event = {
                    type: events_1.Events.EVENT_FILTER_CHANGED,
                    api: this.gridApi,
                    columnApi: this.columnApi
                };
                this.eventService.dispatchEvent(event);
            };
            FilterManager.prototype.isQuickFilterPresent = function() {
                return this.quickFilter !== null;
            };
            FilterManager.prototype.doesRowPassOtherFilters = function(filterToSkip, node) {
                return this.doesRowPassFilter(node, filterToSkip);
            };
            FilterManager.prototype.doesRowPassQuickFilterNoCache = function(node, filterPart) {
                var _this = this;
                var columns = this.columnController.getAllColumnsForQuickFilter();
                var filterPasses = false;
                columns.forEach(function(column) {
                    if (filterPasses) {
                        return;
                    }
                    var part = _this.getQuickFilterTextForColumn(column, node);
                    if (utils_1.Utils.exists(part)) {
                        if (part.indexOf(filterPart) >= 0) {
                            filterPasses = true;
                        }
                    }
                });
                return filterPasses;
            };
            FilterManager.prototype.doesRowPassQuickFilterCache = function(node, filterPart) {
                if (!node.quickFilterAggregateText) {
                    this.aggregateRowForQuickFilter(node);
                }
                var filterPasses = node.quickFilterAggregateText.indexOf(filterPart) >= 0;
                return filterPasses;
            };
            FilterManager.prototype.doesRowPassQuickFilter = function(node) {
                var _this = this;
                var filterPasses = true;
                var usingCache = this.gridOptionsWrapper.isCacheQuickFilter();
                this.quickFilterParts.forEach(function(filterPart) {
                    var partPasses = usingCache ? _this.doesRowPassQuickFilterCache(node, filterPart) : _this.doesRowPassQuickFilterNoCache(node, filterPart);
                    if (!partPasses) {
                        filterPasses = false;
                    }
                });
                return filterPasses;
            };
            FilterManager.prototype.doesRowPassFilter = function(node, filterToSkip) {
                if (this.isQuickFilterPresent()) {
                    if (!this.doesRowPassQuickFilter(node)) {
                        return false;
                    }
                }
                if (this.externalFilterPresent) {
                    if (!this.gridOptionsWrapper.doesExternalFilterPass(node)) {
                        return false;
                    }
                }
                if (this.advancedFilterPresent) {
                    if (!this.doesFilterPass(node, filterToSkip)) {
                        return false;
                    }
                }
                return true;
            };
            FilterManager.prototype.getQuickFilterTextForColumn = function(column, rowNode) {
                var value = this.valueService.getValue(column, rowNode, true);
                var valueAfterCallback;
                var colDef = column.getColDef();
                if (column.getColDef().getQuickFilterText) {
                    var params = {
                        value: value,
                        node: rowNode,
                        data: rowNode.data,
                        column: column,
                        colDef: colDef
                    };
                    valueAfterCallback = column.getColDef().getQuickFilterText(params);
                } else {
                    valueAfterCallback = value;
                }
                if (valueAfterCallback && valueAfterCallback !== "") {
                    return valueAfterCallback.toString().toUpperCase();
                } else {
                    return null;
                }
            };
            FilterManager.prototype.aggregateRowForQuickFilter = function(node) {
                var _this = this;
                var stringParts = [];
                var columns = this.columnController.getAllColumnsForQuickFilter();
                columns.forEach(function(column) {
                    var part = _this.getQuickFilterTextForColumn(column, node);
                    if (utils_1.Utils.exists(part)) {
                        stringParts.push(part);
                    }
                });
                node.quickFilterAggregateText = stringParts.join(FilterManager_1.QUICK_FILTER_SEPARATOR);
            };
            FilterManager.prototype.onNewRowsLoaded = function(source) {
                utils_1.Utils.iterateObject(this.allFilters, function(key, filterWrapper) {
                    filterWrapper.filterPromise.then(function(filter) {
                        if (filter.onNewRowsLoaded) {
                            filter.onNewRowsLoaded();
                        }
                    });
                });
                this.updateFilterFlagInColumns(source);
                this.setAdvancedFilterPresent();
            };
            FilterManager.prototype.createValueGetter = function(column) {
                var _this = this;
                return function(node) {
                    return _this.valueService.getValue(column, node, true);
                };
            };
            FilterManager.prototype.getFilterComponent = function(column) {
                var filterWrapper = this.getOrCreateFilterWrapper(column);
                return filterWrapper.filterPromise;
            };
            FilterManager.prototype.getOrCreateFilterWrapper = function(column) {
                var filterWrapper = this.cachedFilter(column);
                if (!filterWrapper) {
                    filterWrapper = this.createFilterWrapper(column);
                    this.allFilters[column.getColId()] = filterWrapper;
                }
                return filterWrapper;
            };
            FilterManager.prototype.cachedFilter = function(column) {
                return this.allFilters[column.getColId()];
            };
            FilterManager.prototype.createFilterInstance = function(column, $scope) {
                var _this = this;
                var defaultFilter = "agTextColumnFilter";
                if (this.gridOptionsWrapper.isEnterprise()) {
                    defaultFilter = "agSetColumnFilter";
                }
                var sanitisedColDef = utils_1.Utils.cloneObject(column.getColDef());
                var event = {
                    type: events_1.Events.EVENT_FILTER_MODIFIED,
                    api: this.gridApi,
                    columnApi: this.columnApi
                };
                var filterChangedCallback = this.onFilterChanged.bind(this);
                var filterModifiedCallback = function() {
                    return _this.eventService.dispatchEvent(event);
                };
                var params = {
                    column: column,
                    colDef: sanitisedColDef,
                    rowModel: this.rowModel,
                    filterChangedCallback: filterChangedCallback,
                    filterModifiedCallback: filterModifiedCallback,
                    valueGetter: this.createValueGetter(column),
                    context: this.gridOptionsWrapper.getContext(),
                    doesRowPassOtherFilter: null,
                    $scope: $scope
                };
                return this.componentResolver.createAgGridComponent(sanitisedColDef, params, "filter", {
                    api: this.gridApi,
                    columnApi: this.columnApi,
                    column: column,
                    colDef: sanitisedColDef
                }, defaultFilter, true, function(params, filter) {
                    return utils_1.Utils.assign(params, {
                        doesRowPassOtherFilter: _this.doesRowPassOtherFilters.bind(_this, filter)
                    });
                });
            };
            FilterManager.prototype.createFilterWrapper = function(column) {
                var filterWrapper = {
                    column: column,
                    filterPromise: null,
                    scope: null,
                    compiledElement: null,
                    guiPromise: utils_1.Promise.external()
                };
                filterWrapper.scope = this.gridOptionsWrapper.isAngularCompileFilters() ? this.$scope.$new() : null;
                filterWrapper.filterPromise = this.createFilterInstance(column, filterWrapper.scope);
                this.putIntoGui(filterWrapper);
                return filterWrapper;
            };
            FilterManager.prototype.putIntoGui = function(filterWrapper) {
                var _this = this;
                var eFilterGui = document.createElement("div");
                eFilterGui.className = "ag-filter";
                filterWrapper.filterPromise.then(function(filter) {
                    var guiFromFilter = filter.getGui();
                    if (utils_1.Utils.missing(guiFromFilter)) {
                        console.warn("getGui method from filter returned " + guiFromFilter + ", it should be a DOM element or an HTML template string.");
                    }
                    if (typeof guiFromFilter === "string") {
                        guiFromFilter = utils_1.Utils.loadTemplate(guiFromFilter);
                    }
                    eFilterGui.appendChild(guiFromFilter);
                    if (filterWrapper.scope) {
                        var compiledElement = _this.$compile(eFilterGui)(filterWrapper.scope);
                        filterWrapper.compiledElement = compiledElement;
                        setTimeout(function() {
                            return filterWrapper.scope.$apply();
                        }, 0);
                    }
                    filterWrapper.guiPromise.resolve(eFilterGui);
                });
            };
            FilterManager.prototype.onNewColumnsLoaded = function() {
                this.destroy();
            };
            FilterManager.prototype.destroyFilter = function(column, source) {
                if (source === void 0) {
                    source = "api";
                }
                var filterWrapper = this.allFilters[column.getColId()];
                if (filterWrapper) {
                    this.disposeFilterWrapper(filterWrapper, source);
                    this.onFilterChanged();
                }
            };
            FilterManager.prototype.disposeFilterWrapper = function(filterWrapper, source) {
                var _this = this;
                filterWrapper.filterPromise.then(function(filter) {
                    filter.setModel(null);
                    if (filter.destroy) {
                        filter.destroy();
                    }
                    filterWrapper.column.setFilterActive(false, source);
                    if (filterWrapper.scope) {
                        if (filterWrapper.compiledElement) {
                            filterWrapper.compiledElement.remove();
                        }
                        filterWrapper.scope.$destroy();
                    }
                    delete _this.allFilters[filterWrapper.column.getColId()];
                });
            };
            FilterManager.prototype.destroy = function() {
                var _this = this;
                utils_1.Utils.iterateObject(this.allFilters, function(key, filterWrapper) {
                    _this.disposeFilterWrapper(filterWrapper, "filterDestroyed");
                });
            };
            FilterManager.QUICK_FILTER_SEPARATOR = "\n";
            __decorate([ context_1.Autowired("$compile"), __metadata("design:type", Object) ], FilterManager.prototype, "$compile", void 0);
            __decorate([ context_1.Autowired("$scope"), __metadata("design:type", Object) ], FilterManager.prototype, "$scope", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], FilterManager.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("gridCore"), __metadata("design:type", Object) ], FilterManager.prototype, "gridCore", void 0);
            __decorate([ context_1.Autowired("popupService"), __metadata("design:type", popupService_1.PopupService) ], FilterManager.prototype, "popupService", void 0);
            __decorate([ context_1.Autowired("valueService"), __metadata("design:type", valueService_1.ValueService) ], FilterManager.prototype, "valueService", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], FilterManager.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("rowModel"), __metadata("design:type", Object) ], FilterManager.prototype, "rowModel", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], FilterManager.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("enterprise"), __metadata("design:type", Boolean) ], FilterManager.prototype, "enterprise", void 0);
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], FilterManager.prototype, "context", void 0);
            __decorate([ context_1.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], FilterManager.prototype, "columnApi", void 0);
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], FilterManager.prototype, "gridApi", void 0);
            __decorate([ context_1.Autowired("componentResolver"), __metadata("design:type", componentResolver_1.ComponentResolver) ], FilterManager.prototype, "componentResolver", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], FilterManager.prototype, "init", null);
            __decorate([ context_1.PreDestroy, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], FilterManager.prototype, "destroy", null);
            FilterManager = FilterManager_1 = __decorate([ context_1.Bean("filterManager") ], FilterManager);
            return FilterManager;
            var FilterManager_1;
        }();
        exports.FilterManager = FilterManager;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        var __param = this && this.__param || function(paramIndex, decorator) {
            return function(target, key) {
                decorator(target, key, paramIndex);
            };
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var logger_1 = __webpack_require__(12);
        var context_1 = __webpack_require__(0);
        var context_2 = __webpack_require__(0);
        var ExpressionService = function() {
            function ExpressionService() {
                this.expressionToFunctionCache = {};
            }
            ExpressionService.prototype.setBeans = function(loggerFactory) {
                this.logger = loggerFactory.create("ExpressionService");
            };
            ExpressionService.prototype.evaluate = function(expressionOrFunc, params) {
                if (typeof expressionOrFunc === "function") {
                    var func = expressionOrFunc;
                    return func(params);
                } else if (typeof expressionOrFunc === "string") {
                    var expression = expressionOrFunc;
                    return this.evaluateExpression(expression, params);
                } else {
                    console.error("ag-Grid: value should be either a string or a function", expressionOrFunc);
                }
            };
            ExpressionService.prototype.evaluateExpression = function(expression, params) {
                try {
                    var javaScriptFunction = this.createExpressionFunction(expression);
                    var result = javaScriptFunction(params.value, params.context, params.oldValue, params.newValue, params.value, params.node, params.data, params.colDef, params.rowIndex, params.api, params.columnApi, params.getValue, params.column, params.columnGroup);
                    return result;
                } catch (e) {
                    console.log("Processing of the expression failed");
                    console.log("Expression = " + expression);
                    console.log("Exception = " + e);
                    return null;
                }
            };
            ExpressionService.prototype.createExpressionFunction = function(expression) {
                if (this.expressionToFunctionCache[expression]) {
                    return this.expressionToFunctionCache[expression];
                }
                var functionBody = this.createFunctionBody(expression);
                var theFunction = new Function("x, ctx, oldValue, newValue, value, node, data, colDef, rowIndex, api, columnApi, getValue, column, columnGroup", functionBody);
                this.expressionToFunctionCache[expression] = theFunction;
                return theFunction;
            };
            ExpressionService.prototype.createFunctionBody = function(expression) {
                if (expression.indexOf("return") >= 0) {
                    return expression;
                } else {
                    return "return " + expression + ";";
                }
            };
            __decorate([ __param(0, context_2.Qualifier("loggerFactory")), __metadata("design:type", Function), __metadata("design:paramtypes", [ logger_1.LoggerFactory ]), __metadata("design:returntype", void 0) ], ExpressionService.prototype, "setBeans", null);
            ExpressionService = __decorate([ context_1.Bean("expressionService") ], ExpressionService);
            return ExpressionService;
        }();
        exports.ExpressionService = ExpressionService;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        var __param = this && this.__param || function(paramIndex, decorator) {
            return function(target, key) {
                decorator(target, key, paramIndex);
            };
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var expressionService_1 = __webpack_require__(19);
        var templateService_1 = __webpack_require__(49);
        var valueService_1 = __webpack_require__(16);
        var eventService_1 = __webpack_require__(3);
        var rowComp_1 = __webpack_require__(50);
        var events_1 = __webpack_require__(5);
        var constants_1 = __webpack_require__(9);
        var cellComp_1 = __webpack_require__(34);
        var context_1 = __webpack_require__(0);
        var gridCore_1 = __webpack_require__(42);
        var columnApi_1 = __webpack_require__(7);
        var columnController_1 = __webpack_require__(4);
        var logger_1 = __webpack_require__(12);
        var focusedCellController_1 = __webpack_require__(22);
        var cellNavigationService_1 = __webpack_require__(82);
        var gridCell_1 = __webpack_require__(23);
        var beanStub_1 = __webpack_require__(13);
        var paginationProxy_1 = __webpack_require__(29);
        var gridApi_1 = __webpack_require__(6);
        var pinnedRowModel_1 = __webpack_require__(30);
        var beans_1 = __webpack_require__(28);
        var animationFrameService_1 = __webpack_require__(37);
        var heightScaler_1 = __webpack_require__(57);
        var RowRenderer = function(_super) {
            __extends(RowRenderer, _super);
            function RowRenderer() {
                var _this = _super !== null && _super.apply(this, arguments) || this;
                _this.rowCompsByIndex = {};
                _this.floatingTopRowComps = [];
                _this.floatingBottomRowComps = [];
                _this.refreshInProgress = false;
                return _this;
            }
            RowRenderer.prototype.agWire = function(loggerFactory) {
                this.logger = loggerFactory.create("RowRenderer");
            };
            RowRenderer.prototype.registerGridComp = function(gridPanel) {
                this.gridPanel = gridPanel;
                this.rowContainers = this.gridPanel.getRowContainers();
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_PAGINATION_CHANGED, this.onPageLoaded.bind(this));
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_PINNED_ROW_DATA_CHANGED, this.onPinnedRowDataChanged.bind(this));
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_DISPLAYED_COLUMNS_CHANGED, this.onDisplayedColumnsChanged.bind(this));
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_BODY_SCROLL, this.redrawAfterScroll.bind(this));
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_BODY_HEIGHT_CHANGED, this.redrawAfterScroll.bind(this));
                this.redrawAfterModelUpdate();
            };
            RowRenderer.prototype.onPageLoaded = function(refreshEvent) {
                if (utils_1.Utils.missing(refreshEvent)) {
                    refreshEvent = {
                        type: events_1.Events.EVENT_MODEL_UPDATED,
                        api: this.gridApi,
                        columnApi: this.columnApi,
                        animate: false,
                        keepRenderedRows: false,
                        newData: false,
                        newPage: false
                    };
                }
                this.onModelUpdated(refreshEvent);
            };
            RowRenderer.prototype.getAllCellsForColumn = function(column) {
                var eCells = [];
                utils_1.Utils.iterateObject(this.rowCompsByIndex, callback);
                utils_1.Utils.iterateObject(this.floatingBottomRowComps, callback);
                utils_1.Utils.iterateObject(this.floatingTopRowComps, callback);
                function callback(key, rowComp) {
                    var eCell = rowComp.getCellForCol(column);
                    if (eCell) {
                        eCells.push(eCell);
                    }
                }
                return eCells;
            };
            RowRenderer.prototype.refreshFloatingRowComps = function() {
                this.refreshFloatingRows(this.floatingTopRowComps, this.pinnedRowModel.getPinnedTopRowData(), this.rowContainers.floatingTopPinnedLeft, this.rowContainers.floatingTopPinnedRight, this.rowContainers.floatingTop, this.rowContainers.floatingTopFullWidth);
                this.refreshFloatingRows(this.floatingBottomRowComps, this.pinnedRowModel.getPinnedBottomRowData(), this.rowContainers.floatingBottomPinnedLeft, this.rowContainers.floatingBottomPinnedRight, this.rowContainers.floatingBottom, this.rowContainers.floatingBottomFullWith);
            };
            RowRenderer.prototype.refreshFloatingRows = function(rowComps, rowNodes, pinnedLeftContainerComp, pinnedRightContainerComp, bodyContainerComp, fullWidthContainerComp) {
                var _this = this;
                rowComps.forEach(function(row) {
                    row.destroy();
                });
                rowComps.length = 0;
                if (rowNodes) {
                    rowNodes.forEach(function(node) {
                        var rowComp = new rowComp_1.RowComp(_this.$scope, bodyContainerComp, pinnedLeftContainerComp, pinnedRightContainerComp, fullWidthContainerComp, node, _this.beans, false, false);
                        rowComp.init();
                        rowComps.push(rowComp);
                    });
                }
                this.flushContainers(rowComps);
            };
            RowRenderer.prototype.onPinnedRowDataChanged = function() {
                this.redrawAfterModelUpdate();
            };
            RowRenderer.prototype.onModelUpdated = function(refreshEvent) {
                var params = {
                    recycleRows: refreshEvent.keepRenderedRows,
                    animate: refreshEvent.animate,
                    newData: refreshEvent.newData,
                    newPage: refreshEvent.newPage,
                    onlyBody: true
                };
                this.redrawAfterModelUpdate(params);
            };
            RowRenderer.prototype.getRenderedIndexesForRowNodes = function(rowNodes) {
                var result = [];
                if (utils_1.Utils.missing(rowNodes)) {
                    return result;
                }
                utils_1.Utils.iterateObject(this.rowCompsByIndex, function(index, renderedRow) {
                    var rowNode = renderedRow.getRowNode();
                    if (rowNodes.indexOf(rowNode) >= 0) {
                        result.push(index);
                    }
                });
                return result;
            };
            RowRenderer.prototype.redrawRows = function(rowNodes) {
                if (!rowNodes || rowNodes.length == 0) {
                    return;
                }
                var indexesToRemove = this.getRenderedIndexesForRowNodes(rowNodes);
                this.removeRowComps(indexesToRemove);
                this.redrawAfterModelUpdate({
                    recycleRows: true
                });
            };
            RowRenderer.prototype.getCellToRestoreFocusToAfterRefresh = function(params) {
                var focusedCell = params.suppressKeepFocus ? null : this.focusedCellController.getFocusCellToUseAfterRefresh();
                if (utils_1.Utils.missing(focusedCell)) {
                    return null;
                }
                var activeElement = document.activeElement;
                var domData = this.gridOptionsWrapper.getDomData(activeElement, cellComp_1.CellComp.DOM_DATA_KEY_CELL_COMP);
                var elementIsNotACellDev = utils_1.Utils.missing(domData);
                if (elementIsNotACellDev) {
                    return null;
                }
                return focusedCell;
            };
            RowRenderer.prototype.redrawAfterModelUpdate = function(params) {
                if (params === void 0) {
                    params = {};
                }
                this.getLockOnRefresh();
                var focusedCell = this.getCellToRestoreFocusToAfterRefresh(params);
                this.sizeContainerToPageHeight();
                this.scrollToTopIfNewData(params);
                var recycleRows = params.recycleRows;
                var animate = params.animate && this.gridOptionsWrapper.isAnimateRows();
                var rowsToRecycle = this.binRowComps(recycleRows);
                this.redraw(rowsToRecycle, animate);
                if (!params.onlyBody) {
                    this.refreshFloatingRowComps();
                }
                this.restoreFocusedCell(focusedCell);
                this.releaseLockOnRefresh();
            };
            RowRenderer.prototype.scrollToTopIfNewData = function(params) {
                var scrollToTop = params.newData || params.newPage;
                var suppressScrollToTop = this.gridOptionsWrapper.isSuppressScrollOnNewData();
                if (scrollToTop && !suppressScrollToTop) {
                    this.gridPanel.scrollToTop();
                }
            };
            RowRenderer.prototype.sizeContainerToPageHeight = function() {
                var containerHeight = this.paginationProxy.getCurrentPageHeight();
                if (containerHeight === 0) {
                    containerHeight = 1;
                }
                this.heightScaler.setModelHeight(containerHeight);
                var realHeight = this.heightScaler.getUiContainerHeight();
                this.rowContainers.body.setHeight(realHeight);
                this.rowContainers.fullWidth.setHeight(realHeight);
                this.rowContainers.pinnedLeft.setHeight(realHeight);
                this.rowContainers.pinnedRight.setHeight(realHeight);
            };
            RowRenderer.prototype.getLockOnRefresh = function() {
                if (this.refreshInProgress) {
                    throw new Error("ag-Grid: cannot get grid to draw rows when it is in the middle of drawing rows. " + "Your code probably called a grid API method while the grid was in the render stage. To overcome " + "this, put the API call into a timeout, eg instead of api.refreshView(), " + "call setTimeout(function(){api.refreshView(),0}). To see what part of your code " + "that caused the refresh check this stacktrace.");
                }
                this.refreshInProgress = true;
            };
            RowRenderer.prototype.releaseLockOnRefresh = function() {
                this.refreshInProgress = false;
            };
            RowRenderer.prototype.restoreFocusedCell = function(gridCell) {
                if (gridCell) {
                    this.focusedCellController.setFocusedCell(gridCell.rowIndex, gridCell.column, gridCell.floating, true);
                }
            };
            RowRenderer.prototype.stopEditing = function(cancel) {
                if (cancel === void 0) {
                    cancel = false;
                }
                this.forEachRowComp(function(key, rowComp) {
                    rowComp.stopEditing(cancel);
                });
            };
            RowRenderer.prototype.forEachCellComp = function(callback) {
                this.forEachRowComp(function(key, rowComp) {
                    return rowComp.forEachCellComp(callback);
                });
            };
            RowRenderer.prototype.forEachRowComp = function(callback) {
                utils_1.Utils.iterateObject(this.rowCompsByIndex, callback);
                utils_1.Utils.iterateObject(this.floatingTopRowComps, callback);
                utils_1.Utils.iterateObject(this.floatingBottomRowComps, callback);
            };
            RowRenderer.prototype.addRenderedRowListener = function(eventName, rowIndex, callback) {
                var rowComp = this.rowCompsByIndex[rowIndex];
                if (rowComp) {
                    rowComp.addEventListener(eventName, callback);
                }
            };
            RowRenderer.prototype.flashCells = function(params) {
                if (params === void 0) {
                    params = {};
                }
                this.forEachCellCompFiltered(params.rowNodes, params.columns, function(cellComp) {
                    return cellComp.flashCell();
                });
            };
            RowRenderer.prototype.refreshCells = function(params) {
                if (params === void 0) {
                    params = {};
                }
                var refreshCellParams = {
                    forceRefresh: params.force,
                    newData: false
                };
                this.forEachCellCompFiltered(params.rowNodes, params.columns, function(cellComp) {
                    return cellComp.refreshCell(refreshCellParams);
                });
            };
            RowRenderer.prototype.getCellRendererInstances = function(params) {
                var res = [];
                this.forEachCellCompFiltered(params.rowNodes, params.columns, function(cellComp) {
                    var cellRenderer = cellComp.getCellRenderer();
                    if (cellRenderer) {
                        res.push(cellRenderer);
                    }
                });
                return res;
            };
            RowRenderer.prototype.getCellEditorInstances = function(params) {
                var res = [];
                this.forEachCellCompFiltered(params.rowNodes, params.columns, function(cellComp) {
                    var cellEditor = cellComp.getCellEditor();
                    if (cellEditor) {
                        res.push(cellEditor);
                    }
                });
                return res;
            };
            RowRenderer.prototype.getEditingCells = function() {
                var res = [];
                this.forEachCellComp(function(cellComp) {
                    if (cellComp.isEditing()) {
                        var gridCellDef = cellComp.getGridCell().getGridCellDef();
                        res.push(gridCellDef);
                    }
                });
                return res;
            };
            RowRenderer.prototype.forEachCellCompFiltered = function(rowNodes, columns, callback) {
                var _this = this;
                var rowIdsMap;
                if (utils_1.Utils.exists(rowNodes)) {
                    rowIdsMap = {
                        top: {},
                        bottom: {},
                        normal: {}
                    };
                    rowNodes.forEach(function(rowNode) {
                        if (rowNode.rowPinned === constants_1.Constants.PINNED_TOP) {
                            rowIdsMap.top[rowNode.id] = true;
                        } else if (rowNode.rowPinned === constants_1.Constants.PINNED_BOTTOM) {
                            rowIdsMap.bottom[rowNode.id] = true;
                        } else {
                            rowIdsMap.normal[rowNode.id] = true;
                        }
                    });
                }
                var colIdsMap;
                if (utils_1.Utils.exists(columns)) {
                    colIdsMap = {};
                    columns.forEach(function(colKey) {
                        var column = _this.columnController.getGridColumn(colKey);
                        if (utils_1.Utils.exists(column)) {
                            colIdsMap[column.getId()] = true;
                        }
                    });
                }
                var processRow = function(rowComp) {
                    var rowNode = rowComp.getRowNode();
                    var id = rowNode.id;
                    var floating = rowNode.rowPinned;
                    if (utils_1.Utils.exists(rowIdsMap)) {
                        if (floating === constants_1.Constants.PINNED_BOTTOM) {
                            if (!rowIdsMap.bottom[id]) {
                                return;
                            }
                        } else if (floating === constants_1.Constants.PINNED_TOP) {
                            if (!rowIdsMap.top[id]) {
                                return;
                            }
                        } else {
                            if (!rowIdsMap.normal[id]) {
                                return;
                            }
                        }
                    }
                    rowComp.forEachCellComp(function(cellComp) {
                        var colId = cellComp.getColumn().getId();
                        var excludeColFromRefresh = colIdsMap && !colIdsMap[colId];
                        if (excludeColFromRefresh) {
                            return;
                        }
                        callback(cellComp);
                    });
                };
                utils_1.Utils.iterateObject(this.rowCompsByIndex, function(index, rowComp) {
                    processRow(rowComp);
                });
                if (this.floatingTopRowComps) {
                    this.floatingTopRowComps.forEach(processRow);
                }
                if (this.floatingBottomRowComps) {
                    this.floatingBottomRowComps.forEach(processRow);
                }
            };
            RowRenderer.prototype.destroy = function() {
                _super.prototype.destroy.call(this);
                var rowIndexesToRemove = Object.keys(this.rowCompsByIndex);
                this.removeRowComps(rowIndexesToRemove);
            };
            RowRenderer.prototype.binRowComps = function(recycleRows) {
                var _this = this;
                var indexesToRemove;
                var rowsToRecycle = {};
                if (recycleRows) {
                    indexesToRemove = [];
                    utils_1.Utils.iterateObject(this.rowCompsByIndex, function(index, rowComp) {
                        var rowNode = rowComp.getRowNode();
                        if (utils_1.Utils.exists(rowNode.id)) {
                            rowsToRecycle[rowNode.id] = rowComp;
                            delete _this.rowCompsByIndex[index];
                        } else {
                            indexesToRemove.push(index);
                        }
                    });
                } else {
                    indexesToRemove = Object.keys(this.rowCompsByIndex);
                }
                this.removeRowComps(indexesToRemove);
                return rowsToRecycle;
            };
            RowRenderer.prototype.removeRowComps = function(rowsToRemove) {
                var _this = this;
                rowsToRemove.forEach(function(indexToRemove) {
                    var renderedRow = _this.rowCompsByIndex[indexToRemove];
                    renderedRow.destroy();
                    delete _this.rowCompsByIndex[indexToRemove];
                });
            };
            RowRenderer.prototype.redrawAfterScroll = function() {
                this.getLockOnRefresh();
                this.redraw(null, false, true);
                this.releaseLockOnRefresh();
            };
            RowRenderer.prototype.removeRowCompsNotToDraw = function(indexesToDraw) {
                var indexesToDrawMap = {};
                indexesToDraw.forEach(function(index) {
                    return indexesToDrawMap[index] = true;
                });
                var existingIndexes = Object.keys(this.rowCompsByIndex);
                var indexesNotToDraw = utils_1.Utils.filter(existingIndexes, function(index) {
                    return !indexesToDrawMap[index];
                });
                this.removeRowComps(indexesNotToDraw);
            };
            RowRenderer.prototype.calculateIndexesToDraw = function() {
                var _this = this;
                var indexesToDraw = utils_1.Utils.createArrayOfNumbers(this.firstRenderedRow, this.lastRenderedRow);
                utils_1.Utils.iterateObject(this.rowCompsByIndex, function(indexStr, rowComp) {
                    var index = Number(indexStr);
                    if (index < _this.firstRenderedRow || index > _this.lastRenderedRow) {
                        if (_this.keepRowBecauseEditing(rowComp)) {
                            indexesToDraw.push(index);
                        }
                    }
                });
                indexesToDraw.sort(function(a, b) {
                    return a - b;
                });
                return indexesToDraw;
            };
            RowRenderer.prototype.redraw = function(rowsToRecycle, animate, afterScroll) {
                var _this = this;
                if (animate === void 0) {
                    animate = false;
                }
                if (afterScroll === void 0) {
                    afterScroll = false;
                }
                this.heightScaler.update();
                this.workOutFirstAndLastRowsToRender();
                var indexesToDraw = this.calculateIndexesToDraw();
                this.removeRowCompsNotToDraw(indexesToDraw);
                var nextVmTurnFunctions = [];
                var rowComps = [];
                indexesToDraw.forEach(function(rowIndex) {
                    var rowComp = _this.createOrUpdateRowComp(rowIndex, rowsToRecycle, animate, afterScroll);
                    if (utils_1.Utils.exists(rowComp)) {
                        rowComps.push(rowComp);
                        utils_1.Utils.pushAll(nextVmTurnFunctions, rowComp.getAndClearNextVMTurnFunctions());
                    }
                });
                this.flushContainers(rowComps);
                utils_1.Utils.executeNextVMTurn(nextVmTurnFunctions);
                if (afterScroll && !this.gridOptionsWrapper.isSuppressAnimationFrame()) {
                    this.beans.taskQueue.addP2Task(this.destroyRowComps.bind(this, rowsToRecycle, animate));
                } else {
                    this.destroyRowComps(rowsToRecycle, animate);
                }
                this.checkAngularCompile();
            };
            RowRenderer.prototype.flushContainers = function(rowComps) {
                utils_1.Utils.iterateObject(this.rowContainers, function(key, rowContainerComp) {
                    if (rowContainerComp) {
                        rowContainerComp.flushRowTemplates();
                    }
                });
                rowComps.forEach(function(rowComp) {
                    return rowComp.afterFlush();
                });
            };
            RowRenderer.prototype.onDisplayedColumnsChanged = function() {
                var pinningLeft = this.columnController.isPinningLeft();
                var pinningRight = this.columnController.isPinningRight();
                var atLeastOneChanged = this.pinningLeft !== pinningLeft || pinningRight !== this.pinningRight;
                if (atLeastOneChanged) {
                    this.pinningLeft = pinningLeft;
                    this.pinningRight = pinningRight;
                    if (this.gridOptionsWrapper.isEmbedFullWidthRows()) {
                        this.redrawFullWidthEmbeddedRows();
                    }
                }
            };
            RowRenderer.prototype.redrawFullWidthEmbeddedRows = function() {
                var rowsToRemove = [];
                utils_1.Utils.iterateObject(this.rowCompsByIndex, function(id, rowComp) {
                    if (rowComp.isFullWidth()) {
                        var rowIndex = rowComp.getRowNode().rowIndex;
                        rowsToRemove.push(rowIndex.toString());
                    }
                });
                this.refreshFloatingRowComps();
                this.removeRowComps(rowsToRemove);
                this.redrawAfterScroll();
            };
            RowRenderer.prototype.createOrUpdateRowComp = function(rowIndex, rowsToRecycle, animate, afterScroll) {
                var rowNode;
                var rowComp = this.rowCompsByIndex[rowIndex];
                if (!rowComp) {
                    rowNode = this.paginationProxy.getRow(rowIndex);
                    if (utils_1.Utils.exists(rowNode) && utils_1.Utils.exists(rowsToRecycle) && rowsToRecycle[rowNode.id]) {
                        rowComp = rowsToRecycle[rowNode.id];
                        rowsToRecycle[rowNode.id] = null;
                    }
                }
                var creatingNewRowComp = !rowComp;
                if (creatingNewRowComp) {
                    if (!rowNode) {
                        rowNode = this.paginationProxy.getRow(rowIndex);
                    }
                    if (utils_1.Utils.exists(rowNode)) {
                        rowComp = this.createRowComp(rowNode, animate, afterScroll);
                    } else {
                        return;
                    }
                } else {
                    rowComp.ensureDomOrder();
                }
                this.rowCompsByIndex[rowIndex] = rowComp;
                return rowComp;
            };
            RowRenderer.prototype.destroyRowComps = function(rowCompsMap, animate) {
                var delayedFuncs = [];
                utils_1.Utils.iterateObject(rowCompsMap, function(nodeId, rowComp) {
                    if (!rowComp) {
                        return;
                    }
                    rowComp.destroy(animate);
                    utils_1.Utils.pushAll(delayedFuncs, rowComp.getAndClearDelayedDestroyFunctions());
                });
                utils_1.Utils.executeInAWhile(delayedFuncs);
            };
            RowRenderer.prototype.checkAngularCompile = function() {
                var _this = this;
                if (this.gridOptionsWrapper.isAngularCompileRows()) {
                    setTimeout(function() {
                        _this.$scope.$apply();
                    }, 0);
                }
            };
            RowRenderer.prototype.workOutFirstAndLastRowsToRender = function() {
                var newFirst;
                var newLast;
                if (!this.paginationProxy.isRowsToRender()) {
                    newFirst = 0;
                    newLast = -1;
                } else {
                    var pageFirstRow = this.paginationProxy.getPageFirstRow();
                    var pageLastRow = this.paginationProxy.getPageLastRow();
                    var pixelOffset = this.paginationProxy ? this.paginationProxy.getPixelOffset() : 0;
                    var heightOffset = this.heightScaler.getOffset();
                    var bodyVRange = this.gridPanel.getVScrollPosition();
                    var topPixel = bodyVRange.top;
                    var bottomPixel = bodyVRange.bottom;
                    var realPixelTop = topPixel + pixelOffset + heightOffset;
                    var realPixelBottom = bottomPixel + pixelOffset + heightOffset;
                    var first = this.paginationProxy.getRowIndexAtPixel(realPixelTop);
                    var last = this.paginationProxy.getRowIndexAtPixel(realPixelBottom);
                    var buffer = this.gridOptionsWrapper.getRowBuffer();
                    first = first - buffer;
                    last = last + buffer;
                    if (first < pageFirstRow) {
                        first = pageFirstRow;
                    }
                    if (last > pageLastRow) {
                        last = pageLastRow;
                    }
                    newFirst = first;
                    newLast = last;
                }
                var firstDiffers = newFirst !== this.firstRenderedRow;
                var lastDiffers = newLast !== this.lastRenderedRow;
                if (firstDiffers || lastDiffers) {
                    this.firstRenderedRow = newFirst;
                    this.lastRenderedRow = newLast;
                    var event_1 = {
                        type: events_1.Events.EVENT_VIEWPORT_CHANGED,
                        firstRow: newFirst,
                        lastRow: newLast,
                        api: this.gridApi,
                        columnApi: this.columnApi
                    };
                    this.eventService.dispatchEvent(event_1);
                }
            };
            RowRenderer.prototype.getFirstVirtualRenderedRow = function() {
                return this.firstRenderedRow;
            };
            RowRenderer.prototype.getLastVirtualRenderedRow = function() {
                return this.lastRenderedRow;
            };
            RowRenderer.prototype.keepRowBecauseEditing = function(rowComp) {
                var REMOVE_ROW = false;
                var KEEP_ROW = true;
                var rowNode = rowComp.getRowNode();
                var rowHasFocus = this.focusedCellController.isRowNodeFocused(rowNode);
                var rowIsEditing = rowComp.isEditing();
                var mightWantToKeepRow = rowHasFocus || rowIsEditing;
                if (!mightWantToKeepRow) {
                    return REMOVE_ROW;
                }
                var rowNodePresent = this.paginationProxy.isRowPresent(rowNode);
                return rowNodePresent ? KEEP_ROW : REMOVE_ROW;
            };
            RowRenderer.prototype.createRowComp = function(rowNode, animate, afterScroll) {
                var useAnimationFrameForCreate = afterScroll && !this.gridOptionsWrapper.isSuppressAnimationFrame();
                var rowComp = new rowComp_1.RowComp(this.$scope, this.rowContainers.body, this.rowContainers.pinnedLeft, this.rowContainers.pinnedRight, this.rowContainers.fullWidth, rowNode, this.beans, animate, useAnimationFrameForCreate);
                rowComp.init();
                return rowComp;
            };
            RowRenderer.prototype.getRenderedNodes = function() {
                var renderedRows = this.rowCompsByIndex;
                return Object.keys(renderedRows).map(function(key) {
                    return renderedRows[key].getRowNode();
                });
            };
            RowRenderer.prototype.navigateToNextCell = function(event, key, previousCell, allowUserOverride) {
                var nextCell = previousCell;
                while (true) {
                    nextCell = this.cellNavigationService.getNextCellToFocus(key, nextCell);
                    if (utils_1.Utils.missing(nextCell)) {
                        break;
                    }
                    var skipGroupRows = this.gridOptionsWrapper.isGroupUseEntireRow();
                    if (skipGroupRows) {
                        var rowNode = this.paginationProxy.getRow(nextCell.rowIndex);
                        if (!rowNode.group) {
                            break;
                        }
                    } else {
                        break;
                    }
                }
                if (allowUserOverride) {
                    var userFunc = this.gridOptionsWrapper.getNavigateToNextCellFunc();
                    if (utils_1.Utils.exists(userFunc)) {
                        var params = {
                            key: key,
                            previousCellDef: previousCell,
                            nextCellDef: nextCell ? nextCell.getGridCellDef() : null,
                            event: event
                        };
                        var nextCellDef = userFunc(params);
                        if (utils_1.Utils.exists(nextCellDef)) {
                            nextCell = new gridCell_1.GridCell(nextCellDef);
                        } else {
                            nextCell = null;
                        }
                    }
                }
                if (!nextCell) {
                    return;
                }
                this.ensureCellVisible(nextCell);
                this.focusedCellController.setFocusedCell(nextCell.rowIndex, nextCell.column, nextCell.floating, true);
                if (this.rangeController) {
                    var gridCell = new gridCell_1.GridCell({
                        rowIndex: nextCell.rowIndex,
                        floating: nextCell.floating,
                        column: nextCell.column
                    });
                    this.rangeController.setRangeToCell(gridCell);
                }
            };
            RowRenderer.prototype.ensureCellVisible = function(gridCell) {
                if (utils_1.Utils.missing(gridCell.floating)) {
                    this.gridPanel.ensureIndexVisible(gridCell.rowIndex);
                }
                if (!gridCell.column.isPinned()) {
                    this.gridPanel.ensureColumnVisible(gridCell.column);
                }
                this.gridPanel.horizontallyScrollHeaderCenterAndFloatingCenter();
                this.animationFrameService.flushAllFrames();
            };
            RowRenderer.prototype.startEditingCell = function(gridCell, keyPress, charPress) {
                var cell = this.getComponentForCell(gridCell);
                if (cell) {
                    cell.startRowOrCellEdit(keyPress, charPress);
                }
            };
            RowRenderer.prototype.getComponentForCell = function(gridCell) {
                var rowComponent;
                switch (gridCell.floating) {
                  case constants_1.Constants.PINNED_TOP:
                    rowComponent = this.floatingTopRowComps[gridCell.rowIndex];
                    break;

                  case constants_1.Constants.PINNED_BOTTOM:
                    rowComponent = this.floatingBottomRowComps[gridCell.rowIndex];
                    break;

                  default:
                    rowComponent = this.rowCompsByIndex[gridCell.rowIndex];
                    break;
                }
                if (!rowComponent) {
                    return null;
                }
                var cellComponent = rowComponent.getRenderedCellForColumn(gridCell.column);
                return cellComponent;
            };
            RowRenderer.prototype.onTabKeyDown = function(previousRenderedCell, keyboardEvent) {
                var backwards = keyboardEvent.shiftKey;
                var success = this.moveToCellAfter(previousRenderedCell, backwards);
                if (success) {
                    keyboardEvent.preventDefault();
                }
            };
            RowRenderer.prototype.tabToNextCell = function(backwards) {
                var focusedCell = this.focusedCellController.getFocusedCell();
                if (utils_1.Utils.missing(focusedCell)) {
                    return false;
                }
                var renderedCell = this.getComponentForCell(focusedCell);
                if (utils_1.Utils.missing(renderedCell)) {
                    return false;
                }
                var result = this.moveToCellAfter(renderedCell, backwards);
                return result;
            };
            RowRenderer.prototype.moveToCellAfter = function(previousRenderedCell, backwards) {
                var editing = previousRenderedCell.isEditing();
                var res;
                if (editing) {
                    if (this.gridOptionsWrapper.isFullRowEdit()) {
                        res = this.moveToNextEditingRow(previousRenderedCell, backwards);
                    } else {
                        res = this.moveToNextEditingCell(previousRenderedCell, backwards);
                    }
                } else {
                    res = this.moveToNextCellNotEditing(previousRenderedCell, backwards);
                }
                return res;
            };
            RowRenderer.prototype.moveToNextEditingCell = function(previousRenderedCell, backwards) {
                var gridCell = previousRenderedCell.getGridCell();
                previousRenderedCell.stopEditing();
                var nextRenderedCell = this.findNextCellToFocusOn(gridCell, backwards, true);
                var foundCell = utils_1.Utils.exists(nextRenderedCell);
                if (foundCell) {
                    nextRenderedCell.startEditingIfEnabled(null, null, true);
                    nextRenderedCell.focusCell(false);
                }
                return foundCell;
            };
            RowRenderer.prototype.moveToNextEditingRow = function(previousRenderedCell, backwards) {
                var gridCell = previousRenderedCell.getGridCell();
                var nextRenderedCell = this.findNextCellToFocusOn(gridCell, backwards, true);
                var foundCell = utils_1.Utils.exists(nextRenderedCell);
                if (foundCell) {
                    this.moveEditToNextCellOrRow(previousRenderedCell, nextRenderedCell);
                }
                return foundCell;
            };
            RowRenderer.prototype.moveToNextCellNotEditing = function(previousRenderedCell, backwards) {
                var gridCell = previousRenderedCell.getGridCell();
                var nextRenderedCell = this.findNextCellToFocusOn(gridCell, backwards, false);
                var foundCell = utils_1.Utils.exists(nextRenderedCell);
                if (foundCell) {
                    nextRenderedCell.focusCell(true);
                }
                return foundCell;
            };
            RowRenderer.prototype.moveEditToNextCellOrRow = function(previousRenderedCell, nextRenderedCell) {
                var pGridCell = previousRenderedCell.getGridCell();
                var nGridCell = nextRenderedCell.getGridCell();
                var rowsMatch = pGridCell.rowIndex === nGridCell.rowIndex && pGridCell.floating === nGridCell.floating;
                if (rowsMatch) {
                    previousRenderedCell.setFocusOutOnEditor();
                    nextRenderedCell.setFocusInOnEditor();
                } else {
                    var pRow = previousRenderedCell.getRenderedRow();
                    var nRow = nextRenderedCell.getRenderedRow();
                    previousRenderedCell.setFocusOutOnEditor();
                    pRow.stopEditing();
                    nRow.startRowEditing();
                    nextRenderedCell.setFocusInOnEditor();
                }
                nextRenderedCell.focusCell();
            };
            RowRenderer.prototype.findNextCellToFocusOn = function(gridCell, backwards, startEditing) {
                var nextCell = gridCell;
                while (true) {
                    nextCell = this.cellNavigationService.getNextTabbedCell(nextCell, backwards);
                    var userFunc = this.gridOptionsWrapper.getTabToNextCellFunc();
                    if (utils_1.Utils.exists(userFunc)) {
                        var params = {
                            backwards: backwards,
                            editing: startEditing,
                            previousCellDef: gridCell.getGridCellDef(),
                            nextCellDef: nextCell ? nextCell.getGridCellDef() : null
                        };
                        var nextCellDef = userFunc(params);
                        if (utils_1.Utils.exists(nextCellDef)) {
                            nextCell = new gridCell_1.GridCell(nextCellDef);
                        } else {
                            nextCell = null;
                        }
                    }
                    if (!nextCell) {
                        return null;
                    }
                    if (startEditing) {
                        var rowNode = this.paginationProxy.getRow(nextCell.rowIndex);
                        var cellIsEditable = nextCell.column.isCellEditable(rowNode);
                        if (!cellIsEditable) {
                            continue;
                        }
                    }
                    var cellIsNotFloating = utils_1.Utils.missing(nextCell.floating);
                    if (cellIsNotFloating) {
                        this.gridPanel.ensureIndexVisible(nextCell.rowIndex);
                    }
                    if (!nextCell.column.isPinned()) {
                        this.gridPanel.ensureColumnVisible(nextCell.column);
                    }
                    this.gridPanel.horizontallyScrollHeaderCenterAndFloatingCenter();
                    this.animationFrameService.flushAllFrames();
                    var nextCellComp = this.getComponentForCell(nextCell);
                    if (utils_1.Utils.missing(nextCellComp)) {
                        continue;
                    }
                    if (nextCellComp.isSuppressNavigable()) {
                        continue;
                    }
                    if (this.rangeController) {
                        var gridCell_2 = new gridCell_1.GridCell({
                            rowIndex: nextCell.rowIndex,
                            floating: nextCell.floating,
                            column: nextCell.column
                        });
                        this.rangeController.setRangeToCell(gridCell_2);
                    }
                    return nextCellComp;
                }
            };
            __decorate([ context_1.Autowired("paginationProxy"), __metadata("design:type", paginationProxy_1.PaginationProxy) ], RowRenderer.prototype, "paginationProxy", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], RowRenderer.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], RowRenderer.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("gridCore"), __metadata("design:type", gridCore_1.GridCore) ], RowRenderer.prototype, "gridCore", void 0);
            __decorate([ context_1.Autowired("$scope"), __metadata("design:type", Object) ], RowRenderer.prototype, "$scope", void 0);
            __decorate([ context_1.Autowired("expressionService"), __metadata("design:type", expressionService_1.ExpressionService) ], RowRenderer.prototype, "expressionService", void 0);
            __decorate([ context_1.Autowired("templateService"), __metadata("design:type", templateService_1.TemplateService) ], RowRenderer.prototype, "templateService", void 0);
            __decorate([ context_1.Autowired("valueService"), __metadata("design:type", valueService_1.ValueService) ], RowRenderer.prototype, "valueService", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], RowRenderer.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("pinnedRowModel"), __metadata("design:type", pinnedRowModel_1.PinnedRowModel) ], RowRenderer.prototype, "pinnedRowModel", void 0);
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], RowRenderer.prototype, "context", void 0);
            __decorate([ context_1.Autowired("loggerFactory"), __metadata("design:type", logger_1.LoggerFactory) ], RowRenderer.prototype, "loggerFactory", void 0);
            __decorate([ context_1.Autowired("focusedCellController"), __metadata("design:type", focusedCellController_1.FocusedCellController) ], RowRenderer.prototype, "focusedCellController", void 0);
            __decorate([ context_1.Autowired("cellNavigationService"), __metadata("design:type", cellNavigationService_1.CellNavigationService) ], RowRenderer.prototype, "cellNavigationService", void 0);
            __decorate([ context_1.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], RowRenderer.prototype, "columnApi", void 0);
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], RowRenderer.prototype, "gridApi", void 0);
            __decorate([ context_1.Autowired("beans"), __metadata("design:type", beans_1.Beans) ], RowRenderer.prototype, "beans", void 0);
            __decorate([ context_1.Autowired("heightScaler"), __metadata("design:type", heightScaler_1.HeightScaler) ], RowRenderer.prototype, "heightScaler", void 0);
            __decorate([ context_1.Autowired("animationFrameService"), __metadata("design:type", animationFrameService_1.AnimationFrameService) ], RowRenderer.prototype, "animationFrameService", void 0);
            __decorate([ context_1.Optional("rangeController"), __metadata("design:type", Object) ], RowRenderer.prototype, "rangeController", void 0);
            __decorate([ __param(0, context_1.Qualifier("loggerFactory")), __metadata("design:type", Function), __metadata("design:paramtypes", [ logger_1.LoggerFactory ]), __metadata("design:returntype", void 0) ], RowRenderer.prototype, "agWire", null);
            __decorate([ context_1.PreDestroy, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], RowRenderer.prototype, "destroy", null);
            RowRenderer = __decorate([ context_1.Bean("rowRenderer") ], RowRenderer);
            return RowRenderer;
        }(beanStub_1.BeanStub);
        exports.RowRenderer = RowRenderer;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var floatingFilter_1 = __webpack_require__(91);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var floatingFilterWrapper_1 = __webpack_require__(122);
        var filterManager_1 = __webpack_require__(18);
        var componentResolver_1 = __webpack_require__(27);
        var utils_1 = __webpack_require__(1);
        var overlayWrapperComponent_1 = __webpack_require__(124);
        var gridApi_1 = __webpack_require__(6);
        var columnApi_1 = __webpack_require__(7);
        var ComponentType;
        (function(ComponentType) {
            ComponentType[ComponentType["AG_GRID"] = 0] = "AG_GRID";
            ComponentType[ComponentType["FRAMEWORK"] = 1] = "FRAMEWORK";
        })(ComponentType || (ComponentType = {}));
        var ComponentRecipes = function() {
            function ComponentRecipes() {}
            ComponentRecipes_1 = ComponentRecipes;
            ComponentRecipes.prototype.newDateComponent = function(params) {
                return this.componentResolver.createAgGridComponent(this.gridOptions, params, "dateComponent", {
                    api: this.gridApi,
                    columnApi: this.columnApi
                }, "agDateInput");
            };
            ComponentRecipes.prototype.newHeaderComponent = function(params) {
                return this.componentResolver.createAgGridComponent(params.column.getColDef(), params, "headerComponent", {
                    api: this.gridApi,
                    columnApi: this.columnApi,
                    column: params.column,
                    colDef: params.column.getColDef()
                }, "agColumnHeader");
            };
            ComponentRecipes.prototype.newHeaderGroupComponent = function(params) {
                return this.componentResolver.createAgGridComponent(params.columnGroup.getColGroupDef(), params, "headerGroupComponent", {
                    api: this.gridApi,
                    columnApi: this.columnApi
                }, "agColumnGroupHeader");
            };
            ComponentRecipes.prototype.newFloatingFilterWrapperComponent = function(column, params) {
                var _this = this;
                var colDef = column.getColDef();
                if (colDef.suppressFilter) {
                    return this.newEmptyFloatingFilterWrapperComponent(column);
                }
                var defaultFloatingFilterType;
                if (!colDef.filter) {
                    defaultFloatingFilterType = this.gridOptionsWrapper.isEnterprise() ? "agSetColumnFloatingFilter" : "agTextColumnFloatingFilter";
                } else if (typeof colDef.filter === "string" && Object.keys(ComponentRecipes_1.filterToFloatingFilterNames).indexOf(colDef.filter) > -1) {
                    defaultFloatingFilterType = ComponentRecipes_1.filterToFloatingFilterNames[colDef.filter];
                }
                var dynamicComponentParams = {
                    column: column,
                    colDef: colDef,
                    api: this.gridApi,
                    columnApi: this.columnApi
                };
                var floatingFilter = this.componentResolver.createAgGridComponent(colDef, params, "floatingFilterComponent", dynamicComponentParams, defaultFloatingFilterType, false);
                var floatingFilterWrapperComponentParams = {
                    column: column,
                    floatingFilterComp: floatingFilter,
                    suppressFilterButton: this.componentResolver.mergeParams(colDef, "floatingFilterComponent", dynamicComponentParams, params).suppressFilterButton
                };
                if (!floatingFilter) {
                    var filterComponent = this.getFilterComponentPrototype(colDef);
                    if (filterComponent && !filterComponent.component.prototype.getModelAsString) {
                        return this.newEmptyFloatingFilterWrapperComponent(column);
                    }
                    var rawModelFn_1 = params.currentParentModel;
                    params.currentParentModel = function() {
                        var parentPromise = _this.filterManager.getFilterComponent(column);
                        return parentPromise.resolveNow(null, function(parent) {
                            return parent.getModelAsString ? parent.getModelAsString(rawModelFn_1()) : null;
                        });
                    };
                    floatingFilterWrapperComponentParams.floatingFilterComp = utils_1.Promise.resolve(this.componentResolver.createInternalAgGridComponent(floatingFilter_1.ReadModelAsStringFloatingFilterComp, params));
                }
                return this.componentResolver.createInternalAgGridComponent(floatingFilterWrapper_1.FloatingFilterWrapperComp, floatingFilterWrapperComponentParams);
            };
            ComponentRecipes.prototype.newFullWidthGroupRowInnerCellRenderer = function(params) {
                return this.componentResolver.createAgGridComponent(this.gridOptions, params, "groupRowInnerRenderer", params, null, false);
            };
            ComponentRecipes.prototype.newCellRenderer = function(target, params) {
                return this.componentResolver.createAgGridComponent(target, params, "cellRenderer", params, null, false);
            };
            ComponentRecipes.prototype.newInnerCellRenderer = function(target, params) {
                return this.componentResolver.createAgGridComponent(target, params, "innerRenderer", params, null);
            };
            ComponentRecipes.prototype.newFullRowGroupRenderer = function(params) {
                return this.componentResolver.createAgGridComponent(this.gridOptionsWrapper, params, "fullWidthCellRenderer", params, null);
            };
            ComponentRecipes.prototype.newOverlayWrapperComponent = function() {
                return this.componentResolver.createInternalAgGridComponent(overlayWrapperComponent_1.OverlayWrapperComponent, null);
            };
            ComponentRecipes.prototype.newLoadingOverlayComponent = function() {
                return this.componentResolver.createAgGridComponent(this.gridOptions, null, "loadingOverlayComponent", {
                    api: this.gridApi,
                    columnApi: this.columnApi
                }, "agLoadingOverlay");
            };
            ComponentRecipes.prototype.newNoRowsOverlayComponent = function() {
                return this.componentResolver.createAgGridComponent(this.gridOptions, null, "noRowsOverlayComponent", {
                    api: this.gridApi,
                    columnApi: this.columnApi
                }, "agNoRowsOverlay");
            };
            ComponentRecipes.prototype.getFilterComponentPrototype = function(colDef) {
                return this.componentResolver.getComponentToUse(colDef, "filter", {
                    api: this.gridApi,
                    columnApi: this.columnApi,
                    colDef: colDef
                });
            };
            ComponentRecipes.prototype.newEmptyFloatingFilterWrapperComponent = function(column) {
                var floatingFilterWrapperComponentParams = {
                    column: column,
                    floatingFilterComp: null
                };
                return this.componentResolver.createInternalAgGridComponent(floatingFilterWrapper_1.EmptyFloatingFilterWrapperComp, floatingFilterWrapperComponentParams);
            };
            ComponentRecipes.filterToFloatingFilterNames = {
                set: "agSetColumnFloatingFilter",
                agSetColumnFilter: "agSetColumnFloatingFilter",
                number: "agNumberColumnFloatingFilter",
                agNumberColumnFilter: "agNumberColumnFloatingFilter",
                date: "agDateColumnFloatingFilter",
                agDateColumnFilter: "agDateColumnFloatingFilter",
                text: "agTextColumnFloatingFilter",
                agTextColumnFilter: "agTextColumnFloatingFilter"
            };
            __decorate([ context_1.Autowired("componentResolver"), __metadata("design:type", componentResolver_1.ComponentResolver) ], ComponentRecipes.prototype, "componentResolver", void 0);
            __decorate([ context_1.Autowired("gridOptions"), __metadata("design:type", Object) ], ComponentRecipes.prototype, "gridOptions", void 0);
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], ComponentRecipes.prototype, "gridApi", void 0);
            __decorate([ context_1.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], ComponentRecipes.prototype, "columnApi", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], ComponentRecipes.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("filterManager"), __metadata("design:type", filterManager_1.FilterManager) ], ComponentRecipes.prototype, "filterManager", void 0);
            ComponentRecipes = ComponentRecipes_1 = __decorate([ context_1.Bean("componentRecipes") ], ComponentRecipes);
            return ComponentRecipes;
            var ComponentRecipes_1;
        }();
        exports.ComponentRecipes = ComponentRecipes;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var eventService_1 = __webpack_require__(3);
        var events_1 = __webpack_require__(5);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var columnApi_1 = __webpack_require__(7);
        var columnController_1 = __webpack_require__(4);
        var utils_1 = __webpack_require__(1);
        var gridCell_1 = __webpack_require__(23);
        var gridApi_1 = __webpack_require__(6);
        var cellComp_1 = __webpack_require__(34);
        var FocusedCellController = function() {
            function FocusedCellController() {}
            FocusedCellController.prototype.init = function() {
                this.eventService.addEventListener(events_1.Events.EVENT_COLUMN_PIVOT_MODE_CHANGED, this.clearFocusedCell.bind(this));
                this.eventService.addEventListener(events_1.Events.EVENT_COLUMN_EVERYTHING_CHANGED, this.clearFocusedCell.bind(this));
                this.eventService.addEventListener(events_1.Events.EVENT_COLUMN_GROUP_OPENED, this.clearFocusedCell.bind(this));
                this.eventService.addEventListener(events_1.Events.EVENT_COLUMN_MOVED, this.clearFocusedCell.bind(this));
                this.eventService.addEventListener(events_1.Events.EVENT_COLUMN_PINNED, this.clearFocusedCell.bind(this));
                this.eventService.addEventListener(events_1.Events.EVENT_COLUMN_ROW_GROUP_CHANGED, this.clearFocusedCell.bind(this));
                this.eventService.addEventListener(events_1.Events.EVENT_COLUMN_VISIBLE, this.clearFocusedCell.bind(this));
            };
            FocusedCellController.prototype.clearFocusedCell = function() {
                this.focusedCell = null;
                this.onCellFocused(false);
            };
            FocusedCellController.prototype.getFocusedCell = function() {
                return this.focusedCell;
            };
            FocusedCellController.prototype.getFocusCellToUseAfterRefresh = function() {
                if (this.gridOptionsWrapper.isSuppressFocusAfterRefresh()) {
                    return null;
                }
                if (!this.focusedCell) {
                    return null;
                }
                var browserFocusedCell = this.getGridCellForDomElement(document.activeElement);
                if (!browserFocusedCell) {
                    return null;
                }
                return this.focusedCell;
            };
            FocusedCellController.prototype.getGridCellForDomElement = function(eBrowserCell) {
                var ePointer = eBrowserCell;
                while (ePointer) {
                    var cellComp = this.gridOptionsWrapper.getDomData(ePointer, cellComp_1.CellComp.DOM_DATA_KEY_CELL_COMP);
                    if (cellComp) {
                        return cellComp.getGridCell();
                    }
                    ePointer = ePointer.parentNode;
                }
                return null;
            };
            FocusedCellController.prototype.setFocusedCell = function(rowIndex, colKey, floating, forceBrowserFocus) {
                if (forceBrowserFocus === void 0) {
                    forceBrowserFocus = false;
                }
                var column = utils_1.Utils.makeNull(this.columnController.getGridColumn(colKey));
                this.focusedCell = new gridCell_1.GridCell({
                    rowIndex: rowIndex,
                    floating: utils_1.Utils.makeNull(floating),
                    column: column
                });
                this.onCellFocused(forceBrowserFocus);
            };
            FocusedCellController.prototype.isCellFocused = function(gridCell) {
                if (utils_1.Utils.missing(this.focusedCell)) {
                    return false;
                }
                return this.focusedCell.column === gridCell.column && this.isRowFocused(gridCell.rowIndex, gridCell.floating);
            };
            FocusedCellController.prototype.isRowNodeFocused = function(rowNode) {
                return this.isRowFocused(rowNode.rowIndex, rowNode.rowPinned);
            };
            FocusedCellController.prototype.isAnyCellFocused = function() {
                return !!this.focusedCell;
            };
            FocusedCellController.prototype.isRowFocused = function(rowIndex, floating) {
                if (utils_1.Utils.missing(this.focusedCell)) {
                    return false;
                }
                var floatingOrNull = utils_1.Utils.makeNull(floating);
                return this.focusedCell.rowIndex === rowIndex && this.focusedCell.floating === floatingOrNull;
            };
            FocusedCellController.prototype.onCellFocused = function(forceBrowserFocus) {
                var event = {
                    type: events_1.Events.EVENT_CELL_FOCUSED,
                    forceBrowserFocus: forceBrowserFocus,
                    rowIndex: null,
                    column: null,
                    floating: null,
                    api: this.gridApi,
                    columnApi: this.columnApi,
                    rowPinned: null
                };
                if (this.focusedCell) {
                    event.rowIndex = this.focusedCell.rowIndex;
                    event.column = this.focusedCell.column;
                    event.rowPinned = this.focusedCell.floating;
                }
                this.eventService.dispatchEvent(event);
            };
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], FocusedCellController.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], FocusedCellController.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], FocusedCellController.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], FocusedCellController.prototype, "columnApi", void 0);
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], FocusedCellController.prototype, "gridApi", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], FocusedCellController.prototype, "init", null);
            FocusedCellController = __decorate([ context_1.Bean("focusedCellController") ], FocusedCellController);
            return FocusedCellController;
        }();
        exports.FocusedCellController = FocusedCellController;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var gridRow_1 = __webpack_require__(64);
        var GridCell = function() {
            function GridCell(gridCellDef) {
                this.rowIndex = gridCellDef.rowIndex;
                this.column = gridCellDef.column;
                this.floating = utils_1.Utils.makeNull(gridCellDef.floating);
            }
            GridCell.prototype.getGridCellDef = function() {
                return {
                    rowIndex: this.rowIndex,
                    column: this.column,
                    floating: this.floating
                };
            };
            GridCell.prototype.getGridRow = function() {
                return new gridRow_1.GridRow(this.rowIndex, this.floating);
            };
            GridCell.prototype.toString = function() {
                return "rowIndex = " + this.rowIndex + ", floating = " + this.floating + ", column = " + (this.column ? this.column.getId() : null);
            };
            GridCell.prototype.createId = function() {
                return this.rowIndex + "." + this.floating + "." + this.column.getId();
            };
            GridCell.prototype.equals = function(other) {
                var colsMatch = this.column === other.column;
                var floatingMatch = this.floating === other.floating;
                var indexMatch = this.rowIndex === other.rowIndex;
                return colsMatch && floatingMatch && indexMatch;
            };
            return GridCell;
        }();
        exports.GridCell = GridCell;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var column_1 = __webpack_require__(10);
        var context_1 = __webpack_require__(0);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var columnApi_1 = __webpack_require__(7);
        var columnController_1 = __webpack_require__(4);
        var eventService_1 = __webpack_require__(3);
        var events_1 = __webpack_require__(5);
        var context_2 = __webpack_require__(0);
        var utils_1 = __webpack_require__(1);
        var gridApi_1 = __webpack_require__(6);
        var SortController = function() {
            function SortController() {}
            SortController_1 = SortController;
            SortController.prototype.progressSort = function(column, multiSort, source) {
                if (source === void 0) {
                    source = "api";
                }
                var nextDirection = this.getNextSortDirection(column);
                this.setSortForColumn(column, nextDirection, multiSort, source);
            };
            SortController.prototype.setSortForColumn = function(column, sort, multiSort, source) {
                if (source === void 0) {
                    source = "api";
                }
                if (sort !== column_1.Column.SORT_ASC && sort !== column_1.Column.SORT_DESC) {
                    sort = null;
                }
                column.setSort(sort, source);
                if (column.getSort()) {
                    var sortedAt = Number(new Date().valueOf());
                    column.setSortedAt(sortedAt);
                } else {
                    column.setSortedAt(null);
                }
                var doingMultiSort = multiSort && !this.gridOptionsWrapper.isSuppressMultiSort();
                if (!doingMultiSort) {
                    this.clearSortBarThisColumn(column, source);
                }
                this.dispatchSortChangedEvents();
            };
            SortController.prototype.onSortChanged = function() {
                this.dispatchSortChangedEvents();
            };
            SortController.prototype.dispatchSortChangedEvents = function() {
                var event = {
                    type: events_1.Events.EVENT_SORT_CHANGED,
                    api: this.gridApi,
                    columnApi: this.columnApi
                };
                this.eventService.dispatchEvent(event);
            };
            SortController.prototype.clearSortBarThisColumn = function(columnToSkip, source) {
                this.columnController.getPrimaryAndSecondaryAndAutoColumns().forEach(function(columnToClear) {
                    if (!(columnToClear === columnToSkip)) {
                        columnToClear.setSort(null, source);
                    }
                });
            };
            SortController.prototype.getNextSortDirection = function(column) {
                var sortingOrder;
                if (column.getColDef().sortingOrder) {
                    sortingOrder = column.getColDef().sortingOrder;
                } else if (this.gridOptionsWrapper.getSortingOrder()) {
                    sortingOrder = this.gridOptionsWrapper.getSortingOrder();
                } else {
                    sortingOrder = SortController_1.DEFAULT_SORTING_ORDER;
                }
                if (!Array.isArray(sortingOrder) || sortingOrder.length <= 0) {
                    console.warn("ag-grid: sortingOrder must be an array with at least one element, currently it's " + sortingOrder);
                    return;
                }
                var currentIndex = sortingOrder.indexOf(column.getSort());
                var notInArray = currentIndex < 0;
                var lastItemInArray = currentIndex == sortingOrder.length - 1;
                var result;
                if (notInArray || lastItemInArray) {
                    result = sortingOrder[0];
                } else {
                    result = sortingOrder[currentIndex + 1];
                }
                if (SortController_1.DEFAULT_SORTING_ORDER.indexOf(result) < 0) {
                    console.warn("ag-grid: invalid sort type " + result);
                    return null;
                }
                return result;
            };
            SortController.prototype.getSortModel = function() {
                var columnsWithSorting = this.getColumnsWithSortingOrdered();
                return utils_1.Utils.map(columnsWithSorting, function(column) {
                    return {
                        colId: column.getColId(),
                        sort: column.getSort()
                    };
                });
            };
            SortController.prototype.setSortModel = function(sortModel, source) {
                var _this = this;
                if (source === void 0) {
                    source = "api";
                }
                if (!this.gridOptionsWrapper.isEnableSorting()) {
                    console.warn("ag-grid: You are setting the sort model on a grid that does not have sorting enabled");
                    return;
                }
                var sortModelProvided = sortModel && sortModel.length > 0;
                var allColumnsIncludingAuto = this.columnController.getPrimaryAndSecondaryAndAutoColumns();
                allColumnsIncludingAuto.forEach(function(column) {
                    var sortForCol = null;
                    var sortedAt = -1;
                    if (sortModelProvided && !column.getColDef().suppressSorting) {
                        for (var j = 0; j < sortModel.length; j++) {
                            var sortModelEntry = sortModel[j];
                            if (typeof sortModelEntry.colId === "string" && typeof column.getColId() === "string" && _this.compareColIds(sortModelEntry, column)) {
                                sortForCol = sortModelEntry.sort;
                                sortedAt = j;
                            }
                        }
                    }
                    if (sortForCol) {
                        column.setSort(sortForCol, source);
                        column.setSortedAt(sortedAt);
                    } else {
                        column.setSort(null, source);
                        column.setSortedAt(null);
                    }
                });
                this.dispatchSortChangedEvents();
            };
            SortController.prototype.compareColIds = function(sortModelEntry, column) {
                return sortModelEntry.colId === column.getColId();
            };
            SortController.prototype.getColumnsWithSortingOrdered = function() {
                var allColumnsIncludingAuto = this.columnController.getPrimaryAndSecondaryAndAutoColumns();
                var columnsWithSorting = utils_1.Utils.filter(allColumnsIncludingAuto, function(column) {
                    return !!column.getSort();
                });
                columnsWithSorting.sort(function(a, b) {
                    return a.sortedAt - b.sortedAt;
                });
                return columnsWithSorting;
            };
            SortController.prototype.getSortForRowController = function() {
                var columnsWithSorting = this.getColumnsWithSortingOrdered();
                return utils_1.Utils.map(columnsWithSorting, function(column) {
                    var ascending = column.getSort() === column_1.Column.SORT_ASC;
                    return {
                        inverter: ascending ? 1 : -1,
                        column: column
                    };
                });
            };
            SortController.DEFAULT_SORTING_ORDER = [ column_1.Column.SORT_ASC, column_1.Column.SORT_DESC, null ];
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], SortController.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], SortController.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], SortController.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], SortController.prototype, "columnApi", void 0);
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], SortController.prototype, "gridApi", void 0);
            SortController = SortController_1 = __decorate([ context_2.Bean("sortController") ], SortController);
            return SortController;
            var SortController_1;
        }();
        exports.SortController = SortController;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var Events = function() {
            function Events() {}
            Events.EVENT_COLUMN_EVERYTHING_CHANGED = "columnEverythingChanged";
            Events.EVENT_NEW_COLUMNS_LOADED = "newColumnsLoaded";
            Events.EVENT_COLUMN_PIVOT_MODE_CHANGED = "columnPivotModeChanged";
            Events.EVENT_COLUMN_ROW_GROUP_CHANGED = "columnRowGroupChanged";
            Events.EVENT_COLUMN_PIVOT_CHANGED = "columnPivotChanged";
            Events.EVENT_GRID_COLUMNS_CHANGED = "gridColumnsChanged";
            Events.EVENT_COLUMN_VALUE_CHANGED = "columnValueChanged";
            Events.EVENT_COLUMN_MOVED = "columnMoved";
            Events.EVENT_COLUMN_VISIBLE = "columnVisible";
            Events.EVENT_COLUMN_PINNED = "columnPinned";
            Events.EVENT_COLUMN_GROUP_OPENED = "columnGroupOpened";
            Events.EVENT_COLUMN_RESIZED = "columnResized";
            Events.EVENT_DISPLAYED_COLUMNS_CHANGED = "displayedColumnsChanged";
            Events.EVENT_VIRTUAL_COLUMNS_CHANGED = "virtualColumnsChanged";
            Events.EVENT_ROW_GROUP_OPENED = "rowGroupOpened";
            Events.EVENT_ROW_DATA_CHANGED = "rowDataChanged";
            Events.EVENT_ROW_DATA_UPDATED = "rowDataUpdated";
            Events.EVENT_PINNED_ROW_DATA_CHANGED = "pinnedRowDataChanged";
            Events.EVENT_RANGE_SELECTION_CHANGED = "rangeSelectionChanged";
            Events.EVENT_TOOL_PANEL_VISIBLE_CHANGED = "toolPanelVisibleChanged";
            Events.EVENT_MODEL_UPDATED = "modelUpdated";
            Events.EVENT_PASTE_START = "pasteStart";
            Events.EVENT_PASTE_END = "pasteEnd";
            Events.EVENT_CELL_CLICKED = "cellClicked";
            Events.EVENT_CELL_DOUBLE_CLICKED = "cellDoubleClicked";
            Events.EVENT_CELL_MOUSE_DOWN = "cellMouseDown";
            Events.EVENT_CELL_CONTEXT_MENU = "cellContextMenu";
            Events.EVENT_CELL_VALUE_CHANGED = "cellValueChanged";
            Events.EVENT_ROW_VALUE_CHANGED = "rowValueChanged";
            Events.EVENT_CELL_FOCUSED = "cellFocused";
            Events.EVENT_ROW_SELECTED = "rowSelected";
            Events.EVENT_SELECTION_CHANGED = "selectionChanged";
            Events.EVENT_CELL_MOUSE_OVER = "cellMouseOver";
            Events.EVENT_CELL_MOUSE_OUT = "cellMouseOut";
            Events.EVENT_FILTER_CHANGED = "filterChanged";
            Events.EVENT_FILTER_MODIFIED = "filterModified";
            Events.EVENT_SORT_CHANGED = "sortChanged";
            Events.EVENT_VIRTUAL_ROW_REMOVED = "virtualRowRemoved";
            Events.EVENT_ROW_CLICKED = "rowClicked";
            Events.EVENT_ROW_DOUBLE_CLICKED = "rowDoubleClicked";
            Events.EVENT_GRID_READY = "gridReady";
            Events.DEPRECATED_EVENT_GRID_SIZE_CHANGED = "gridSizeChanged";
            Events.EVENT_VIEWPORT_CHANGED = "viewportChanged";
            Events.EVENT_DRAG_STARTED = "dragStarted";
            Events.EVENT_DRAG_STOPPED = "dragStopped";
            Events.EVENT_ROW_EDITING_STARTED = "rowEditingStarted";
            Events.EVENT_ROW_EDITING_STOPPED = "rowEditingStopped";
            Events.EVENT_CELL_EDITING_STARTED = "cellEditingStarted";
            Events.EVENT_CELL_EDITING_STOPPED = "cellEditingStopped";
            Events.EVENT_BODY_SCROLL = "bodyScroll";
            Events.EVENT_ANIMATION_QUEUE_EMPTY = "animationQueueEmpty";
            Events.EVENT_HEIGHT_SCALE_CHANGED = "heightScaleChanged";
            Events.EVENT_PAGINATION_CHANGED = "paginationChanged";
            Events.EVENT_COMPONENT_STATE_CHANGED = "componentStateChanged";
            Events.EVENT_BODY_HEIGHT_CHANGED = "bodyHeightChanged";
            Events.EVENT_DISPLAYED_COLUMNS_WIDTH_CHANGED = "displayedColumnsWidthChanged";
            Events.EVENT_SCROLL_VISIBILITY_CHANGED = "scrollVisibilityChanged";
            Events.EVENT_COLUMN_HOVER_CHANGED = "columnHoverChanged";
            Events.EVENT_FLASH_CELLS = "flashCells";
            Events.EVENT_ROW_DRAG_ENTER = "rowDragEnter";
            Events.EVENT_ROW_DRAG_MOVE = "rowDragMove";
            Events.EVENT_ROW_DRAG_LEAVE = "rowDragLeave";
            Events.EVENT_ROW_DRAG_END = "rowDragEnd";
            Events.EVENT_COLUMN_ROW_GROUP_CHANGE_REQUEST = "columnRowGroupChangeRequest";
            Events.EVENT_COLUMN_PIVOT_CHANGE_REQUEST = "columnPivotChangeRequest";
            Events.EVENT_COLUMN_VALUE_CHANGE_REQUEST = "columnValueChangeRequest";
            Events.EVENT_COLUMN_AGG_FUNC_CHANGE_REQUEST = "columnAggFuncChangeRequest";
            return Events;
        }();
        exports.Events = Events;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var column_1 = __webpack_require__(10);
        var eventService_1 = __webpack_require__(3);
        var context_1 = __webpack_require__(0);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var columnApi_1 = __webpack_require__(7);
        var gridApi_1 = __webpack_require__(6);
        var ColumnGroup = function() {
            function ColumnGroup(originalColumnGroup, groupId, instanceId) {
                this.displayedChildren = [];
                this.localEventService = new eventService_1.EventService();
                this.groupId = groupId;
                this.instanceId = instanceId;
                this.originalColumnGroup = originalColumnGroup;
            }
            ColumnGroup.createUniqueId = function(groupId, instanceId) {
                return groupId + "_" + instanceId;
            };
            ColumnGroup.prototype.reset = function() {
                this.parent = null;
                this.children = null;
                this.displayedChildren = null;
            };
            ColumnGroup.prototype.getParent = function() {
                return this.parent;
            };
            ColumnGroup.prototype.setParent = function(parent) {
                this.parent = parent;
            };
            ColumnGroup.prototype.getUniqueId = function() {
                return ColumnGroup.createUniqueId(this.groupId, this.instanceId);
            };
            ColumnGroup.prototype.isEmptyGroup = function() {
                return this.displayedChildren.length === 0;
            };
            ColumnGroup.prototype.isMoving = function() {
                var allLeafColumns = this.getOriginalColumnGroup().getLeafColumns();
                if (!allLeafColumns || allLeafColumns.length === 0) {
                    return false;
                }
                var allMoving = true;
                allLeafColumns.forEach(function(col) {
                    if (!col.isMoving()) {
                        allMoving = false;
                    }
                });
                return allMoving;
            };
            ColumnGroup.prototype.checkLeft = function() {
                this.displayedChildren.forEach(function(child) {
                    if (child instanceof ColumnGroup) {
                        child.checkLeft();
                    }
                });
                if (this.displayedChildren.length > 0) {
                    if (this.gridOptionsWrapper.isEnableRtl()) {
                        var lastChild = this.displayedChildren[this.displayedChildren.length - 1];
                        var lastChildLeft = lastChild.getLeft();
                        this.setLeft(lastChildLeft);
                    } else {
                        var firstChildLeft = this.displayedChildren[0].getLeft();
                        this.setLeft(firstChildLeft);
                    }
                } else {
                    this.setLeft(null);
                }
            };
            ColumnGroup.prototype.getLeft = function() {
                return this.left;
            };
            ColumnGroup.prototype.getOldLeft = function() {
                return this.oldLeft;
            };
            ColumnGroup.prototype.setLeft = function(left) {
                this.oldLeft = left;
                if (this.left !== left) {
                    this.left = left;
                    this.localEventService.dispatchEvent(this.createAgEvent(ColumnGroup.EVENT_LEFT_CHANGED));
                }
            };
            ColumnGroup.prototype.createAgEvent = function(type) {
                return {
                    type: type
                };
            };
            ColumnGroup.prototype.addEventListener = function(eventType, listener) {
                this.localEventService.addEventListener(eventType, listener);
            };
            ColumnGroup.prototype.removeEventListener = function(eventType, listener) {
                this.localEventService.removeEventListener(eventType, listener);
            };
            ColumnGroup.prototype.getGroupId = function() {
                return this.groupId;
            };
            ColumnGroup.prototype.getInstanceId = function() {
                return this.instanceId;
            };
            ColumnGroup.prototype.isChildInThisGroupDeepSearch = function(wantedChild) {
                var result = false;
                this.children.forEach(function(foundChild) {
                    if (wantedChild === foundChild) {
                        result = true;
                    }
                    if (foundChild instanceof ColumnGroup) {
                        if (foundChild.isChildInThisGroupDeepSearch(wantedChild)) {
                            result = true;
                        }
                    }
                });
                return result;
            };
            ColumnGroup.prototype.getActualWidth = function() {
                var groupActualWidth = 0;
                if (this.displayedChildren) {
                    this.displayedChildren.forEach(function(child) {
                        groupActualWidth += child.getActualWidth();
                    });
                }
                return groupActualWidth;
            };
            ColumnGroup.prototype.isResizable = function() {
                if (!this.displayedChildren) {
                    return false;
                }
                var result = false;
                this.displayedChildren.forEach(function(child) {
                    if (child.isResizable()) {
                        result = true;
                    }
                });
                return result;
            };
            ColumnGroup.prototype.getMinWidth = function() {
                var result = 0;
                this.displayedChildren.forEach(function(groupChild) {
                    result += groupChild.getMinWidth();
                });
                return result;
            };
            ColumnGroup.prototype.addChild = function(child) {
                if (!this.children) {
                    this.children = [];
                }
                this.children.push(child);
            };
            ColumnGroup.prototype.getDisplayedChildren = function() {
                return this.displayedChildren;
            };
            ColumnGroup.prototype.getLeafColumns = function() {
                var result = [];
                this.addLeafColumns(result);
                return result;
            };
            ColumnGroup.prototype.getDisplayedLeafColumns = function() {
                var result = [];
                this.addDisplayedLeafColumns(result);
                return result;
            };
            ColumnGroup.prototype.getDefinition = function() {
                return this.originalColumnGroup.getColGroupDef();
            };
            ColumnGroup.prototype.getColGroupDef = function() {
                return this.originalColumnGroup.getColGroupDef();
            };
            ColumnGroup.prototype.isPadding = function() {
                return this.originalColumnGroup.isPadding();
            };
            ColumnGroup.prototype.isExpandable = function() {
                return this.originalColumnGroup.isExpandable();
            };
            ColumnGroup.prototype.isExpanded = function() {
                return this.originalColumnGroup.isExpanded();
            };
            ColumnGroup.prototype.setExpanded = function(expanded) {
                this.originalColumnGroup.setExpanded(expanded);
            };
            ColumnGroup.prototype.addDisplayedLeafColumns = function(leafColumns) {
                this.displayedChildren.forEach(function(child) {
                    if (child instanceof column_1.Column) {
                        leafColumns.push(child);
                    } else if (child instanceof ColumnGroup) {
                        child.addDisplayedLeafColumns(leafColumns);
                    }
                });
            };
            ColumnGroup.prototype.addLeafColumns = function(leafColumns) {
                this.children.forEach(function(child) {
                    if (child instanceof column_1.Column) {
                        leafColumns.push(child);
                    } else if (child instanceof ColumnGroup) {
                        child.addLeafColumns(leafColumns);
                    }
                });
            };
            ColumnGroup.prototype.getChildren = function() {
                return this.children;
            };
            ColumnGroup.prototype.getColumnGroupShow = function() {
                return this.originalColumnGroup.getColumnGroupShow();
            };
            ColumnGroup.prototype.getOriginalColumnGroup = function() {
                return this.originalColumnGroup;
            };
            ColumnGroup.prototype.calculateDisplayedColumns = function() {
                var _this = this;
                this.displayedChildren = [];
                if (!this.originalColumnGroup.isExpandable()) {
                    this.displayedChildren = this.children;
                } else {
                    this.children.forEach(function(abstractColumn) {
                        var headerGroupShow = abstractColumn.getColumnGroupShow();
                        switch (headerGroupShow) {
                          case ColumnGroup.HEADER_GROUP_SHOW_OPEN:
                            if (_this.originalColumnGroup.isExpanded()) {
                                _this.displayedChildren.push(abstractColumn);
                            }
                            break;

                          case ColumnGroup.HEADER_GROUP_SHOW_CLOSED:
                            if (!_this.originalColumnGroup.isExpanded()) {
                                _this.displayedChildren.push(abstractColumn);
                            }
                            break;

                          default:
                            _this.displayedChildren.push(abstractColumn);
                            break;
                        }
                    });
                }
                this.localEventService.dispatchEvent(this.createAgEvent(ColumnGroup.EVENT_DISPLAYED_CHILDREN_CHANGED));
            };
            ColumnGroup.HEADER_GROUP_SHOW_OPEN = "open";
            ColumnGroup.HEADER_GROUP_SHOW_CLOSED = "closed";
            ColumnGroup.EVENT_LEFT_CHANGED = "leftChanged";
            ColumnGroup.EVENT_DISPLAYED_CHILDREN_CHANGED = "displayedChildrenChanged";
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], ColumnGroup.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], ColumnGroup.prototype, "columnApi", void 0);
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], ColumnGroup.prototype, "gridApi", void 0);
            return ColumnGroup;
        }();
        exports.ColumnGroup = ColumnGroup;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var utils_1 = __webpack_require__(1);
        var componentProvider_1 = __webpack_require__(66);
        var agComponentUtils_1 = __webpack_require__(76);
        var componentMetadataProvider_1 = __webpack_require__(77);
        var ComponentType;
        (function(ComponentType) {
            ComponentType[ComponentType["AG_GRID"] = 0] = "AG_GRID";
            ComponentType[ComponentType["FRAMEWORK"] = 1] = "FRAMEWORK";
        })(ComponentType = exports.ComponentType || (exports.ComponentType = {}));
        var ComponentSource;
        (function(ComponentSource) {
            ComponentSource[ComponentSource["DEFAULT"] = 0] = "DEFAULT";
            ComponentSource[ComponentSource["REGISTERED_BY_NAME"] = 1] = "REGISTERED_BY_NAME";
            ComponentSource[ComponentSource["HARDCODED"] = 2] = "HARDCODED";
        })(ComponentSource = exports.ComponentSource || (exports.ComponentSource = {}));
        var ComponentResolver = function() {
            function ComponentResolver() {}
            ComponentResolver.prototype.getComponentToUse = function(holder, propertyName, dynamicComponentParams, defaultComponentName) {
                var hardcodedNameComponent = null;
                var HardcodedJsComponent = null;
                var hardcodedJsFunction = null;
                var HardcodedFwComponent = null;
                var dynamicComponentFn;
                if (holder != null) {
                    var componentPropertyValue = holder[propertyName];
                    if (componentPropertyValue != null) {
                        if (typeof componentPropertyValue === "string") {
                            hardcodedNameComponent = componentPropertyValue;
                        } else if (this.agComponentUtils.doesImplementIComponent(componentPropertyValue)) {
                            HardcodedJsComponent = componentPropertyValue;
                        } else {
                            hardcodedJsFunction = componentPropertyValue;
                        }
                    }
                    HardcodedFwComponent = holder[propertyName + "Framework"];
                    dynamicComponentFn = holder[propertyName + "Selector"];
                }
                if (HardcodedJsComponent && HardcodedFwComponent || hardcodedNameComponent && HardcodedFwComponent || hardcodedJsFunction && HardcodedFwComponent) {
                    throw Error("ag-grid: you are trying to specify: " + propertyName + " twice as a component.");
                }
                if (HardcodedFwComponent && !this.frameworkComponentWrapper) {
                    throw Error("ag-grid: you are specifying a framework component but you are not using a framework version of ag-grid for : " + propertyName);
                }
                if (dynamicComponentFn && (hardcodedNameComponent || HardcodedJsComponent || hardcodedJsFunction || HardcodedFwComponent)) {
                    throw Error("ag-grid: you can't specify both, the selector and the component of ag-grid for : " + propertyName);
                }
                if (HardcodedFwComponent) {
                    return {
                        type: ComponentType.FRAMEWORK,
                        component: HardcodedFwComponent,
                        source: ComponentSource.HARDCODED,
                        dynamicParams: null
                    };
                }
                if (HardcodedJsComponent) {
                    return {
                        type: ComponentType.AG_GRID,
                        component: HardcodedJsComponent,
                        source: ComponentSource.HARDCODED,
                        dynamicParams: null
                    };
                }
                if (hardcodedJsFunction) {
                    return this.agComponentUtils.adaptFunction(propertyName, hardcodedJsFunction, ComponentType.AG_GRID, ComponentSource.HARDCODED);
                }
                if (dynamicComponentFn) {
                    var dynamicComponentDef = dynamicComponentFn(dynamicComponentParams);
                    if (dynamicComponentDef != null) {
                        if (dynamicComponentDef.component == null) {
                            dynamicComponentDef.component = defaultComponentName;
                        }
                        var dynamicComponent = this.resolveByName(propertyName, dynamicComponentDef.component);
                        return utils_1._.assign(dynamicComponent, {
                            dynamicParams: dynamicComponentDef.params
                        });
                    }
                }
                var componentNameToUse;
                if (hardcodedNameComponent) {
                    componentNameToUse = hardcodedNameComponent;
                } else {
                    componentNameToUse = defaultComponentName;
                }
                return componentNameToUse == null ? null : this.resolveByName(propertyName, componentNameToUse);
            };
            ComponentResolver.prototype.resolveByName = function(propertyName, componentNameOpt) {
                var componentName = componentNameOpt != null ? componentNameOpt : propertyName;
                var registeredComponent = this.componentProvider.retrieve(componentName);
                if (registeredComponent == null) return null;
                if (registeredComponent.type == ComponentType.FRAMEWORK) {
                    return {
                        component: registeredComponent.component,
                        type: ComponentType.FRAMEWORK,
                        source: ComponentSource.REGISTERED_BY_NAME,
                        dynamicParams: null
                    };
                }
                if (this.agComponentUtils.doesImplementIComponent(registeredComponent.component)) {
                    return {
                        component: registeredComponent.component,
                        type: ComponentType.AG_GRID,
                        source: registeredComponent.source == componentProvider_1.RegisteredComponentSource.REGISTERED ? ComponentSource.REGISTERED_BY_NAME : ComponentSource.DEFAULT,
                        dynamicParams: null
                    };
                }
                return this.agComponentUtils.adaptFunction(propertyName, registeredComponent.component, registeredComponent.type, registeredComponent.source == componentProvider_1.RegisteredComponentSource.REGISTERED ? ComponentSource.REGISTERED_BY_NAME : ComponentSource.DEFAULT);
            };
            ComponentResolver.prototype.mergeParams = function(holder, propertyName, agGridParams, dynamicCustomParams, dynamicParams) {
                if (dynamicParams === void 0) {
                    dynamicParams = null;
                }
                var customParamsRaw = holder ? holder[propertyName + "Params"] : null;
                var finalParams = {};
                utils_1._.mergeDeep(finalParams, agGridParams);
                if (customParamsRaw != null) {
                    var customParams = null;
                    if (typeof customParamsRaw === "function") {
                        customParams = customParamsRaw(dynamicCustomParams);
                    } else {
                        customParams = customParamsRaw;
                    }
                    utils_1._.mergeDeep(finalParams, customParams);
                }
                utils_1._.mergeDeep(finalParams, dynamicParams);
                if (!finalParams.api) {
                    finalParams.api = this.gridOptions.api;
                }
                return finalParams;
            };
            ComponentResolver.prototype.createAgGridComponent = function(holderOpt, agGridParams, propertyName, dynamicComponentParams, defaultComponentName, mandatory, customInitParamsCb) {
                if (mandatory === void 0) {
                    mandatory = true;
                }
                var holder = holderOpt == null ? this.gridOptions : holderOpt;
                var componentAndParams = this.newAgGridComponent(holder, propertyName, dynamicComponentParams, defaultComponentName, mandatory);
                if (!componentAndParams) return null;
                var finalParams = this.mergeParams(holder, propertyName, agGridParams, dynamicComponentParams, componentAndParams[1]);
                finalParams.agGridReact = this.context.getBean("agGridReact") ? utils_1._.cloneObject(this.context.getBean("agGridReact")) : {};
                finalParams.frameworkComponentWrapper = this.context.getBean("frameworkComponentWrapper") ? this.context.getBean("frameworkComponentWrapper") : {};
                var deferredInit = this.initialiseComponent(componentAndParams[0], finalParams, customInitParamsCb);
                if (deferredInit == null) {
                    return utils_1.Promise.resolve(componentAndParams[0]);
                } else {
                    var asPromise = deferredInit;
                    return asPromise.map(function(notRelevant) {
                        return componentAndParams[0];
                    });
                }
            };
            ComponentResolver.prototype.createInternalAgGridComponent = function(clazz, agGridParams, customInitParamsCb) {
                var internalComponent = new clazz();
                this.initialiseComponent(internalComponent, agGridParams, customInitParamsCb);
                return internalComponent;
            };
            ComponentResolver.prototype.newAgGridComponent = function(holder, propertyName, dynamicComponentParams, defaultComponentName, mandatory) {
                if (mandatory === void 0) {
                    mandatory = true;
                }
                var componentToUse = this.getComponentToUse(holder, propertyName, dynamicComponentParams, defaultComponentName);
                if (!componentToUse || !componentToUse.component) {
                    if (mandatory) {
                        console.error("Error creating component " + propertyName + "=>" + defaultComponentName);
                    }
                    return null;
                }
                if (componentToUse.type === ComponentType.AG_GRID) {
                    return [ new componentToUse.component(), componentToUse.dynamicParams ];
                }
                var FrameworkComponentRaw = componentToUse.component;
                var thisComponentConfig = this.componentMetadataProvider.retrieve(propertyName);
                return [ this.frameworkComponentWrapper.wrap(FrameworkComponentRaw, thisComponentConfig.mandatoryMethodList, thisComponentConfig.optionalMethodList, defaultComponentName), componentToUse.dynamicParams ];
            };
            ComponentResolver.prototype.initialiseComponent = function(component, agGridParams, customInitParamsCb) {
                this.context.wireBean(component);
                if (customInitParamsCb == null) {
                    return component.init(agGridParams);
                } else {
                    return component.init(customInitParamsCb(agGridParams, component));
                }
            };
            __decorate([ context_1.Autowired("gridOptions"), __metadata("design:type", Object) ], ComponentResolver.prototype, "gridOptions", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], ComponentResolver.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], ComponentResolver.prototype, "context", void 0);
            __decorate([ context_1.Autowired("agComponentUtils"), __metadata("design:type", agComponentUtils_1.AgComponentUtils) ], ComponentResolver.prototype, "agComponentUtils", void 0);
            __decorate([ context_1.Autowired("componentMetadataProvider"), __metadata("design:type", componentMetadataProvider_1.ComponentMetadataProvider) ], ComponentResolver.prototype, "componentMetadataProvider", void 0);
            __decorate([ context_1.Autowired("componentProvider"), __metadata("design:type", componentProvider_1.ComponentProvider) ], ComponentResolver.prototype, "componentProvider", void 0);
            __decorate([ context_1.Optional("frameworkComponentWrapper"), __metadata("design:type", Object) ], ComponentResolver.prototype, "frameworkComponentWrapper", void 0);
            ComponentResolver = __decorate([ context_1.Bean("componentResolver") ], ComponentResolver);
            return ComponentResolver;
        }();
        exports.ComponentResolver = ComponentResolver;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var columnApi_1 = __webpack_require__(7);
        var columnController_1 = __webpack_require__(4);
        var gridApi_1 = __webpack_require__(6);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var expressionService_1 = __webpack_require__(19);
        var rowRenderer_1 = __webpack_require__(20);
        var templateService_1 = __webpack_require__(49);
        var valueService_1 = __webpack_require__(16);
        var eventService_1 = __webpack_require__(3);
        var columnAnimationService_1 = __webpack_require__(53);
        var focusedCellController_1 = __webpack_require__(22);
        var cellEditorFactory_1 = __webpack_require__(54);
        var cellRendererFactory_1 = __webpack_require__(55);
        var popupService_1 = __webpack_require__(35);
        var cellRendererService_1 = __webpack_require__(56);
        var valueFormatterService_1 = __webpack_require__(43);
        var stylingService_1 = __webpack_require__(73);
        var columnHoverService_1 = __webpack_require__(45);
        var paginationProxy_1 = __webpack_require__(29);
        var animationFrameService_1 = __webpack_require__(37);
        var componentResolver_1 = __webpack_require__(27);
        var dragAndDropService_1 = __webpack_require__(15);
        var sortController_1 = __webpack_require__(24);
        var filterManager_1 = __webpack_require__(18);
        var heightScaler_1 = __webpack_require__(57);
        var Beans = function() {
            function Beans() {}
            Beans.prototype.registerGridComp = function(gridPanel) {
                this.gridPanel = gridPanel;
            };
            Beans.prototype.postConstruct = function() {
                this.doingMasterDetail = this.gridOptionsWrapper.isMasterDetail();
            };
            __decorate([ context_1.Autowired("paginationProxy"), __metadata("design:type", paginationProxy_1.PaginationProxy) ], Beans.prototype, "paginationProxy", void 0);
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], Beans.prototype, "context", void 0);
            __decorate([ context_1.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], Beans.prototype, "columnApi", void 0);
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], Beans.prototype, "gridApi", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], Beans.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("expressionService"), __metadata("design:type", expressionService_1.ExpressionService) ], Beans.prototype, "expressionService", void 0);
            __decorate([ context_1.Autowired("rowRenderer"), __metadata("design:type", rowRenderer_1.RowRenderer) ], Beans.prototype, "rowRenderer", void 0);
            __decorate([ context_1.Autowired("$compile"), __metadata("design:type", Object) ], Beans.prototype, "$compile", void 0);
            __decorate([ context_1.Autowired("templateService"), __metadata("design:type", templateService_1.TemplateService) ], Beans.prototype, "templateService", void 0);
            __decorate([ context_1.Autowired("valueService"), __metadata("design:type", valueService_1.ValueService) ], Beans.prototype, "valueService", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], Beans.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], Beans.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("columnAnimationService"), __metadata("design:type", columnAnimationService_1.ColumnAnimationService) ], Beans.prototype, "columnAnimationService", void 0);
            __decorate([ context_1.Optional("rangeController"), __metadata("design:type", Object) ], Beans.prototype, "rangeController", void 0);
            __decorate([ context_1.Autowired("focusedCellController"), __metadata("design:type", focusedCellController_1.FocusedCellController) ], Beans.prototype, "focusedCellController", void 0);
            __decorate([ context_1.Optional("contextMenuFactory"), __metadata("design:type", Object) ], Beans.prototype, "contextMenuFactory", void 0);
            __decorate([ context_1.Autowired("cellEditorFactory"), __metadata("design:type", cellEditorFactory_1.CellEditorFactory) ], Beans.prototype, "cellEditorFactory", void 0);
            __decorate([ context_1.Autowired("cellRendererFactory"), __metadata("design:type", cellRendererFactory_1.CellRendererFactory) ], Beans.prototype, "cellRendererFactory", void 0);
            __decorate([ context_1.Autowired("popupService"), __metadata("design:type", popupService_1.PopupService) ], Beans.prototype, "popupService", void 0);
            __decorate([ context_1.Autowired("cellRendererService"), __metadata("design:type", cellRendererService_1.CellRendererService) ], Beans.prototype, "cellRendererService", void 0);
            __decorate([ context_1.Autowired("valueFormatterService"), __metadata("design:type", valueFormatterService_1.ValueFormatterService) ], Beans.prototype, "valueFormatterService", void 0);
            __decorate([ context_1.Autowired("stylingService"), __metadata("design:type", stylingService_1.StylingService) ], Beans.prototype, "stylingService", void 0);
            __decorate([ context_1.Autowired("columnHoverService"), __metadata("design:type", columnHoverService_1.ColumnHoverService) ], Beans.prototype, "columnHoverService", void 0);
            __decorate([ context_1.Autowired("enterprise"), __metadata("design:type", Boolean) ], Beans.prototype, "enterprise", void 0);
            __decorate([ context_1.Autowired("componentResolver"), __metadata("design:type", componentResolver_1.ComponentResolver) ], Beans.prototype, "componentResolver", void 0);
            __decorate([ context_1.Autowired("animationFrameService"), __metadata("design:type", animationFrameService_1.AnimationFrameService) ], Beans.prototype, "taskQueue", void 0);
            __decorate([ context_1.Autowired("dragAndDropService"), __metadata("design:type", dragAndDropService_1.DragAndDropService) ], Beans.prototype, "dragAndDropService", void 0);
            __decorate([ context_1.Autowired("sortController"), __metadata("design:type", sortController_1.SortController) ], Beans.prototype, "sortController", void 0);
            __decorate([ context_1.Autowired("filterManager"), __metadata("design:type", filterManager_1.FilterManager) ], Beans.prototype, "filterManager", void 0);
            __decorate([ context_1.Autowired("heightScaler"), __metadata("design:type", heightScaler_1.HeightScaler) ], Beans.prototype, "heightScaler", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], Beans.prototype, "postConstruct", null);
            Beans = __decorate([ context_1.Bean("beans") ], Beans);
            return Beans;
        }();
        exports.Beans = Beans;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var beanStub_1 = __webpack_require__(13);
        var eventService_1 = __webpack_require__(3);
        var events_1 = __webpack_require__(5);
        var utils_1 = __webpack_require__(1);
        var context_1 = __webpack_require__(0);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var scrollVisibleService_1 = __webpack_require__(36);
        var selectionController_1 = __webpack_require__(17);
        var columnApi_1 = __webpack_require__(7);
        var gridApi_1 = __webpack_require__(6);
        var PaginationAutoPageSizeService = function(_super) {
            __extends(PaginationAutoPageSizeService, _super);
            function PaginationAutoPageSizeService() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            PaginationAutoPageSizeService.prototype.registerGridComp = function(gridPanel) {
                this.gridPanel = gridPanel;
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_BODY_HEIGHT_CHANGED, this.onBodyHeightChanged.bind(this));
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_SCROLL_VISIBILITY_CHANGED, this.onScrollVisibilityChanged.bind(this));
                this.checkPageSize();
            };
            PaginationAutoPageSizeService.prototype.notActive = function() {
                return !this.gridOptionsWrapper.isPaginationAutoPageSize();
            };
            PaginationAutoPageSizeService.prototype.onScrollVisibilityChanged = function() {
                this.checkPageSize();
            };
            PaginationAutoPageSizeService.prototype.onBodyHeightChanged = function() {
                this.checkPageSize();
            };
            PaginationAutoPageSizeService.prototype.checkPageSize = function() {
                if (this.notActive()) {
                    return;
                }
                var rowHeight = this.gridOptionsWrapper.getRowHeightAsNumber();
                var bodyHeight = this.gridPanel.getBodyHeight();
                if (this.scrollVisibleService.isBodyHorizontalScrollShowing()) {
                    bodyHeight = bodyHeight - this.gridOptionsWrapper.getScrollbarWidth();
                }
                if (bodyHeight > 0) {
                    var newPageSize = Math.floor(bodyHeight / rowHeight);
                    this.gridOptionsWrapper.setProperty("paginationPageSize", newPageSize);
                }
            };
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], PaginationAutoPageSizeService.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], PaginationAutoPageSizeService.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("scrollVisibleService"), __metadata("design:type", scrollVisibleService_1.ScrollVisibleService) ], PaginationAutoPageSizeService.prototype, "scrollVisibleService", void 0);
            PaginationAutoPageSizeService = __decorate([ context_1.Bean("paginationAutoPageSizeService") ], PaginationAutoPageSizeService);
            return PaginationAutoPageSizeService;
        }(beanStub_1.BeanStub);
        exports.PaginationAutoPageSizeService = PaginationAutoPageSizeService;
        var PaginationProxy = function(_super) {
            __extends(PaginationProxy, _super);
            function PaginationProxy() {
                var _this = _super !== null && _super.apply(this, arguments) || this;
                _this.currentPage = 0;
                _this.topRowIndex = 0;
                _this.bottomRowIndex = 0;
                _this.pixelOffset = 0;
                return _this;
            }
            PaginationProxy.prototype.postConstruct = function() {
                this.active = this.gridOptionsWrapper.isPagination();
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_MODEL_UPDATED, this.onModelUpdated.bind(this));
                this.addDestroyableEventListener(this.gridOptionsWrapper, "paginationPageSize", this.onModelUpdated.bind(this));
                this.onModelUpdated();
            };
            PaginationProxy.prototype.isLastRowFound = function() {
                return this.rowModel.isLastRowFound();
            };
            PaginationProxy.prototype.onModelUpdated = function(modelUpdatedEvent) {
                this.setIndexesAndBounds();
                var paginationChangedEvent = {
                    type: events_1.Events.EVENT_PAGINATION_CHANGED,
                    animate: modelUpdatedEvent ? modelUpdatedEvent.animate : false,
                    newData: modelUpdatedEvent ? modelUpdatedEvent.newData : false,
                    newPage: modelUpdatedEvent ? modelUpdatedEvent.newPage : false,
                    keepRenderedRows: modelUpdatedEvent ? modelUpdatedEvent.keepRenderedRows : false,
                    api: this.gridApi,
                    columnApi: this.columnApi
                };
                this.eventService.dispatchEvent(paginationChangedEvent);
            };
            PaginationProxy.prototype.goToPage = function(page) {
                if (!this.active) {
                    return;
                }
                if (this.currentPage === page) {
                    return;
                }
                this.currentPage = page;
                var event = {
                    type: events_1.Events.EVENT_MODEL_UPDATED,
                    animate: false,
                    keepRenderedRows: false,
                    newData: false,
                    newPage: true,
                    api: this.gridApi,
                    columnApi: this.columnApi
                };
                this.onModelUpdated(event);
            };
            PaginationProxy.prototype.getPixelOffset = function() {
                return this.pixelOffset;
            };
            PaginationProxy.prototype.getRow = function(index) {
                return this.rowModel.getRow(index);
            };
            PaginationProxy.prototype.getRowNode = function(id) {
                return this.rowModel.getRowNode(id);
            };
            PaginationProxy.prototype.getRowIndexAtPixel = function(pixel) {
                return this.rowModel.getRowIndexAtPixel(pixel);
            };
            PaginationProxy.prototype.getCurrentPageHeight = function() {
                if (utils_1._.missing(this.topRowBounds) || utils_1._.missing(this.bottomRowBounds)) {
                    return 0;
                }
                return this.bottomRowBounds.rowTop + this.bottomRowBounds.rowHeight - this.topRowBounds.rowTop;
            };
            PaginationProxy.prototype.isRowPresent = function(rowNode) {
                if (!this.rowModel.isRowPresent(rowNode)) {
                    return false;
                }
                var nodeIsInPage = rowNode.rowIndex >= this.topRowIndex && rowNode.rowIndex <= this.bottomRowIndex;
                return nodeIsInPage;
            };
            PaginationProxy.prototype.isEmpty = function() {
                return this.rowModel.isEmpty();
            };
            PaginationProxy.prototype.isRowsToRender = function() {
                return this.rowModel.isRowsToRender();
            };
            PaginationProxy.prototype.getNodesInRangeForSelection = function(firstInRange, lastInRange) {
                return this.rowModel.getNodesInRangeForSelection(firstInRange, lastInRange);
            };
            PaginationProxy.prototype.forEachNode = function(callback) {
                return this.rowModel.forEachNode(callback);
            };
            PaginationProxy.prototype.getType = function() {
                return this.rowModel.getType();
            };
            PaginationProxy.prototype.getRowBounds = function(index) {
                return this.rowModel.getRowBounds(index);
            };
            PaginationProxy.prototype.getPageFirstRow = function() {
                return this.pageSize * this.currentPage;
            };
            PaginationProxy.prototype.getPageLastRow = function() {
                var totalLastRow = this.pageSize * (this.currentPage + 1) - 1;
                var pageLastRow = this.rowModel.getPageLastRow();
                if (pageLastRow > totalLastRow) {
                    return totalLastRow;
                } else {
                    return pageLastRow;
                }
            };
            PaginationProxy.prototype.getRowCount = function() {
                return this.rowModel.getRowCount();
            };
            PaginationProxy.prototype.goToPageWithIndex = function(index) {
                if (!this.active) {
                    return;
                }
                var pageNumber = Math.floor(index / this.pageSize);
                this.goToPage(pageNumber);
            };
            PaginationProxy.prototype.getTotalRowCount = function() {
                return this.rowModel.getPageLastRow() + 1;
            };
            PaginationProxy.prototype.isLastPageFound = function() {
                return this.rowModel.isLastRowFound();
            };
            PaginationProxy.prototype.getCurrentPage = function() {
                return this.currentPage;
            };
            PaginationProxy.prototype.goToNextPage = function() {
                this.goToPage(this.currentPage + 1);
            };
            PaginationProxy.prototype.goToPreviousPage = function() {
                this.goToPage(this.currentPage - 1);
            };
            PaginationProxy.prototype.goToFirstPage = function() {
                this.goToPage(0);
            };
            PaginationProxy.prototype.goToLastPage = function() {
                var rowCount = this.rowModel.getPageLastRow() + 1;
                var lastPage = Math.floor(rowCount / this.pageSize);
                this.goToPage(lastPage);
            };
            PaginationProxy.prototype.getPageSize = function() {
                return this.pageSize;
            };
            PaginationProxy.prototype.getTotalPages = function() {
                return this.totalPages;
            };
            PaginationProxy.prototype.setPageSize = function() {
                this.pageSize = this.gridOptionsWrapper.getPaginationPageSize();
                if (!(this.pageSize >= 1)) {
                    this.pageSize = 100;
                }
            };
            PaginationProxy.prototype.setIndexesAndBounds = function() {
                if (this.active) {
                    this.setPageSize();
                    var totalRowCount = this.getTotalRowCount();
                    this.totalPages = Math.floor((totalRowCount - 1) / this.pageSize) + 1;
                    if (this.currentPage >= this.totalPages) {
                        this.currentPage = this.totalPages - 1;
                    }
                    if (!utils_1._.isNumeric(this.currentPage) || this.currentPage < 0) {
                        this.currentPage = 0;
                    }
                    this.topRowIndex = this.pageSize * this.currentPage;
                    this.bottomRowIndex = this.pageSize * (this.currentPage + 1) - 1;
                    var maxRowAllowed = this.rowModel.getPageLastRow();
                    if (this.bottomRowIndex > maxRowAllowed) {
                        this.bottomRowIndex = maxRowAllowed;
                    }
                } else {
                    this.pageSize = this.rowModel.getPageLastRow() + 1;
                    this.totalPages = 1;
                    this.currentPage = 0;
                    this.topRowIndex = 0;
                    this.bottomRowIndex = this.rowModel.getPageLastRow();
                }
                this.topRowBounds = this.rowModel.getRowBounds(this.topRowIndex);
                this.bottomRowBounds = this.rowModel.getRowBounds(this.bottomRowIndex);
                this.pixelOffset = utils_1._.exists(this.topRowBounds) ? this.topRowBounds.rowTop : 0;
            };
            __decorate([ context_1.Autowired("rowModel"), __metadata("design:type", Object) ], PaginationProxy.prototype, "rowModel", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], PaginationProxy.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], PaginationProxy.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("selectionController"), __metadata("design:type", selectionController_1.SelectionController) ], PaginationProxy.prototype, "selectionController", void 0);
            __decorate([ context_1.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], PaginationProxy.prototype, "columnApi", void 0);
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], PaginationProxy.prototype, "gridApi", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], PaginationProxy.prototype, "postConstruct", null);
            PaginationProxy = __decorate([ context_1.Bean("paginationProxy") ], PaginationProxy);
            return PaginationProxy;
        }(beanStub_1.BeanStub);
        exports.PaginationProxy = PaginationProxy;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var rowNode_1 = __webpack_require__(14);
        var context_1 = __webpack_require__(0);
        var eventService_1 = __webpack_require__(3);
        var context_2 = __webpack_require__(0);
        var events_1 = __webpack_require__(5);
        var context_3 = __webpack_require__(0);
        var constants_1 = __webpack_require__(9);
        var utils_1 = __webpack_require__(1);
        var columnApi_1 = __webpack_require__(7);
        var gridApi_1 = __webpack_require__(6);
        var PinnedRowModel = function() {
            function PinnedRowModel() {}
            PinnedRowModel.prototype.init = function() {
                this.setPinnedTopRowData(this.gridOptionsWrapper.getPinnedTopRowData());
                this.setPinnedBottomRowData(this.gridOptionsWrapper.getPinnedBottomRowData());
            };
            PinnedRowModel.prototype.isEmpty = function(floating) {
                var rows = floating === constants_1.Constants.PINNED_TOP ? this.pinnedTopRows : this.pinnedBottomRows;
                return utils_1.Utils.missingOrEmpty(rows);
            };
            PinnedRowModel.prototype.isRowsToRender = function(floating) {
                return !this.isEmpty(floating);
            };
            PinnedRowModel.prototype.getRowAtPixel = function(pixel, floating) {
                var rows = floating === constants_1.Constants.PINNED_TOP ? this.pinnedTopRows : this.pinnedBottomRows;
                if (utils_1.Utils.missingOrEmpty(rows)) {
                    return 0;
                }
                for (var i = 0; i < rows.length; i++) {
                    var rowNode = rows[i];
                    var rowTopPixel = rowNode.rowTop + rowNode.rowHeight - 1;
                    if (rowTopPixel >= pixel) {
                        return i;
                    }
                }
                return rows.length - 1;
            };
            PinnedRowModel.prototype.setPinnedTopRowData = function(rowData) {
                this.pinnedTopRows = this.createNodesFromData(rowData, true);
                var event = {
                    type: events_1.Events.EVENT_PINNED_ROW_DATA_CHANGED,
                    api: this.gridApi,
                    columnApi: this.columnApi
                };
                this.eventService.dispatchEvent(event);
            };
            PinnedRowModel.prototype.setPinnedBottomRowData = function(rowData) {
                this.pinnedBottomRows = this.createNodesFromData(rowData, false);
                var event = {
                    type: events_1.Events.EVENT_PINNED_ROW_DATA_CHANGED,
                    api: this.gridApi,
                    columnApi: this.columnApi
                };
                this.eventService.dispatchEvent(event);
            };
            PinnedRowModel.prototype.createNodesFromData = function(allData, isTop) {
                var _this = this;
                var rowNodes = [];
                if (allData) {
                    var nextRowTop_1 = 0;
                    allData.forEach(function(dataItem, index) {
                        var rowNode = new rowNode_1.RowNode();
                        _this.context.wireBean(rowNode);
                        rowNode.data = dataItem;
                        rowNode.rowPinned = isTop ? constants_1.Constants.PINNED_TOP : constants_1.Constants.PINNED_BOTTOM;
                        rowNode.setRowTop(nextRowTop_1);
                        rowNode.setRowHeight(_this.gridOptionsWrapper.getRowHeightForNode(rowNode));
                        rowNode.setRowIndex(index);
                        nextRowTop_1 += rowNode.rowHeight;
                        rowNodes.push(rowNode);
                    });
                }
                return rowNodes;
            };
            PinnedRowModel.prototype.getPinnedTopRowData = function() {
                return this.pinnedTopRows;
            };
            PinnedRowModel.prototype.getPinnedBottomRowData = function() {
                return this.pinnedBottomRows;
            };
            PinnedRowModel.prototype.getPinnedTopTotalHeight = function() {
                return this.getTotalHeight(this.pinnedTopRows);
            };
            PinnedRowModel.prototype.getPinnedTopRowCount = function() {
                return this.pinnedTopRows ? this.pinnedTopRows.length : 0;
            };
            PinnedRowModel.prototype.getPinnedBottomRowCount = function() {
                return this.pinnedBottomRows ? this.pinnedBottomRows.length : 0;
            };
            PinnedRowModel.prototype.getPinnedTopRow = function(index) {
                return this.pinnedTopRows[index];
            };
            PinnedRowModel.prototype.getPinnedBottomRow = function(index) {
                return this.pinnedBottomRows[index];
            };
            PinnedRowModel.prototype.forEachPinnedTopRow = function(callback) {
                if (utils_1.Utils.missingOrEmpty(this.pinnedTopRows)) {
                    return;
                }
                this.pinnedTopRows.forEach(callback);
            };
            PinnedRowModel.prototype.forEachPinnedBottomRow = function(callback) {
                if (utils_1.Utils.missingOrEmpty(this.pinnedBottomRows)) {
                    return;
                }
                this.pinnedBottomRows.forEach(callback);
            };
            PinnedRowModel.prototype.getPinnedBottomTotalHeight = function() {
                return this.getTotalHeight(this.pinnedBottomRows);
            };
            PinnedRowModel.prototype.getTotalHeight = function(rowNodes) {
                if (!rowNodes || rowNodes.length === 0) {
                    return 0;
                } else {
                    var lastNode = rowNodes[rowNodes.length - 1];
                    return lastNode.rowTop + lastNode.rowHeight;
                }
            };
            __decorate([ context_2.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], PinnedRowModel.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_2.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], PinnedRowModel.prototype, "eventService", void 0);
            __decorate([ context_2.Autowired("context"), __metadata("design:type", context_1.Context) ], PinnedRowModel.prototype, "context", void 0);
            __decorate([ context_2.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], PinnedRowModel.prototype, "columnApi", void 0);
            __decorate([ context_2.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], PinnedRowModel.prototype, "gridApi", void 0);
            __decorate([ context_3.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], PinnedRowModel.prototype, "init", null);
            PinnedRowModel = __decorate([ context_1.Bean("pinnedRowModel") ], PinnedRowModel);
            return PinnedRowModel;
        }();
        exports.PinnedRowModel = PinnedRowModel;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var columnGroup_1 = __webpack_require__(26);
        var originalColumnGroup_1 = __webpack_require__(32);
        var context_1 = __webpack_require__(0);
        var context_2 = __webpack_require__(0);
        var ColumnUtils = function() {
            function ColumnUtils() {}
            ColumnUtils.prototype.calculateColInitialWidth = function(colDef) {
                if (!colDef.width) {
                    return this.gridOptionsWrapper.getColWidth();
                } else if (colDef.width < this.gridOptionsWrapper.getMinColWidth()) {
                    return this.gridOptionsWrapper.getMinColWidth();
                } else {
                    return colDef.width;
                }
            };
            ColumnUtils.prototype.getOriginalPathForColumn = function(column, originalBalancedTree) {
                var result = [];
                var found = false;
                recursePath(originalBalancedTree, 0);
                if (found) {
                    return result;
                } else {
                    return null;
                }
                function recursePath(balancedColumnTree, dept) {
                    for (var i = 0; i < balancedColumnTree.length; i++) {
                        if (found) {
                            return;
                        }
                        var node = balancedColumnTree[i];
                        if (node instanceof originalColumnGroup_1.OriginalColumnGroup) {
                            var nextNode = node;
                            recursePath(nextNode.getChildren(), dept + 1);
                            result[dept] = node;
                        } else {
                            if (node === column) {
                                found = true;
                            }
                        }
                    }
                }
            };
            ColumnUtils.prototype.depthFirstOriginalTreeSearch = function(tree, callback) {
                var _this = this;
                if (!tree) {
                    return;
                }
                tree.forEach(function(child) {
                    if (child instanceof originalColumnGroup_1.OriginalColumnGroup) {
                        _this.depthFirstOriginalTreeSearch(child.getChildren(), callback);
                    }
                    callback(child);
                });
            };
            ColumnUtils.prototype.depthFirstAllColumnTreeSearch = function(tree, callback) {
                var _this = this;
                if (!tree) {
                    return;
                }
                tree.forEach(function(child) {
                    if (child instanceof columnGroup_1.ColumnGroup) {
                        _this.depthFirstAllColumnTreeSearch(child.getChildren(), callback);
                    }
                    callback(child);
                });
            };
            ColumnUtils.prototype.depthFirstDisplayedColumnTreeSearch = function(tree, callback) {
                var _this = this;
                if (!tree) {
                    return;
                }
                tree.forEach(function(child) {
                    if (child instanceof columnGroup_1.ColumnGroup) {
                        _this.depthFirstDisplayedColumnTreeSearch(child.getDisplayedChildren(), callback);
                    }
                    callback(child);
                });
            };
            __decorate([ context_2.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], ColumnUtils.prototype, "gridOptionsWrapper", void 0);
            ColumnUtils = __decorate([ context_1.Bean("columnUtils") ], ColumnUtils);
            return ColumnUtils;
        }();
        exports.ColumnUtils = ColumnUtils;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var columnGroup_1 = __webpack_require__(26);
        var column_1 = __webpack_require__(10);
        var eventService_1 = __webpack_require__(3);
        var context_1 = __webpack_require__(0);
        var columnApi_1 = __webpack_require__(7);
        var gridApi_1 = __webpack_require__(6);
        var OriginalColumnGroup = function() {
            function OriginalColumnGroup(colGroupDef, groupId, padding, level) {
                this.localEventService = new eventService_1.EventService();
                this.expandable = false;
                this.colGroupDef = colGroupDef;
                this.groupId = groupId;
                this.expanded = colGroupDef && !!colGroupDef.openByDefault;
                this.padding = padding;
                this.level = level;
            }
            OriginalColumnGroup.prototype.getLevel = function() {
                return this.level;
            };
            OriginalColumnGroup.prototype.isVisible = function() {
                if (this.children) {
                    return this.children.some(function(child) {
                        return child.isVisible();
                    });
                } else {
                    return false;
                }
            };
            OriginalColumnGroup.prototype.isPadding = function() {
                return this.padding;
            };
            OriginalColumnGroup.prototype.setExpanded = function(expanded) {
                this.expanded = expanded;
                var event = {
                    type: OriginalColumnGroup.EVENT_EXPANDED_CHANGED
                };
                this.localEventService.dispatchEvent(event);
            };
            OriginalColumnGroup.prototype.isExpandable = function() {
                return this.expandable;
            };
            OriginalColumnGroup.prototype.isExpanded = function() {
                return this.expanded;
            };
            OriginalColumnGroup.prototype.getGroupId = function() {
                return this.groupId;
            };
            OriginalColumnGroup.prototype.getId = function() {
                return this.getGroupId();
            };
            OriginalColumnGroup.prototype.setChildren = function(children) {
                this.children = children;
            };
            OriginalColumnGroup.prototype.getChildren = function() {
                return this.children;
            };
            OriginalColumnGroup.prototype.getColGroupDef = function() {
                return this.colGroupDef;
            };
            OriginalColumnGroup.prototype.getLeafColumns = function() {
                var result = [];
                this.addLeafColumns(result);
                return result;
            };
            OriginalColumnGroup.prototype.addLeafColumns = function(leafColumns) {
                if (!this.children) {
                    return;
                }
                this.children.forEach(function(child) {
                    if (child instanceof column_1.Column) {
                        leafColumns.push(child);
                    } else if (child instanceof OriginalColumnGroup) {
                        child.addLeafColumns(leafColumns);
                    }
                });
            };
            OriginalColumnGroup.prototype.getColumnGroupShow = function() {
                if (!this.padding) {
                    return this.colGroupDef.columnGroupShow;
                } else {
                    return this.children[0].getColumnGroupShow();
                }
            };
            OriginalColumnGroup.prototype.setupExpandable = function() {
                var _this = this;
                this.setExpandable();
                this.getLeafColumns().forEach(function(col) {
                    return col.addEventListener(column_1.Column.EVENT_VISIBLE_CHANGED, _this.onColumnVisibilityChanged.bind(_this));
                });
            };
            OriginalColumnGroup.prototype.setExpandable = function() {
                var atLeastOneShowingWhenOpen = false;
                var atLeastOneShowingWhenClosed = false;
                var atLeastOneChangeable = false;
                for (var i = 0, j = this.children.length; i < j; i++) {
                    var abstractColumn = this.children[i];
                    if (!abstractColumn.isVisible()) {
                        continue;
                    }
                    var headerGroupShow = abstractColumn.getColumnGroupShow();
                    if (headerGroupShow === columnGroup_1.ColumnGroup.HEADER_GROUP_SHOW_OPEN) {
                        atLeastOneShowingWhenOpen = true;
                        atLeastOneChangeable = true;
                    } else if (headerGroupShow === columnGroup_1.ColumnGroup.HEADER_GROUP_SHOW_CLOSED) {
                        atLeastOneShowingWhenClosed = true;
                        atLeastOneChangeable = true;
                    } else {
                        atLeastOneShowingWhenOpen = true;
                        atLeastOneShowingWhenClosed = true;
                    }
                }
                var expandable = atLeastOneShowingWhenOpen && atLeastOneShowingWhenClosed && atLeastOneChangeable;
                if (this.expandable !== expandable) {
                    this.expandable = expandable;
                    var event_1 = {
                        type: OriginalColumnGroup.EVENT_EXPANDABLE_CHANGED
                    };
                    this.localEventService.dispatchEvent(event_1);
                }
            };
            OriginalColumnGroup.prototype.onColumnVisibilityChanged = function() {
                this.setExpandable();
            };
            OriginalColumnGroup.prototype.addEventListener = function(eventType, listener) {
                this.localEventService.addEventListener(eventType, listener);
            };
            OriginalColumnGroup.prototype.removeEventListener = function(eventType, listener) {
                this.localEventService.removeEventListener(eventType, listener);
            };
            OriginalColumnGroup.EVENT_EXPANDED_CHANGED = "expandedChanged";
            OriginalColumnGroup.EVENT_EXPANDABLE_CHANGED = "expandableChanged";
            __decorate([ context_1.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], OriginalColumnGroup.prototype, "columnApi", void 0);
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], OriginalColumnGroup.prototype, "gridApi", void 0);
            return OriginalColumnGroup;
        }();
        exports.OriginalColumnGroup = OriginalColumnGroup;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var ValueCache = function() {
            function ValueCache() {
                this.cacheVersion = 0;
            }
            ValueCache.prototype.init = function() {
                this.active = this.gridOptionsWrapper.isValueCache();
                this.neverExpires = this.gridOptionsWrapper.isValueCacheNeverExpires();
            };
            ValueCache.prototype.onDataChanged = function() {
                if (this.neverExpires) {
                    return;
                }
                this.expire();
            };
            ValueCache.prototype.expire = function() {
                this.cacheVersion++;
            };
            ValueCache.prototype.setValue = function(rowNode, colId, value) {
                if (this.active) {
                    if (rowNode.__cacheVersion !== this.cacheVersion) {
                        rowNode.__cacheVersion = this.cacheVersion;
                        rowNode.__cacheData = {};
                    }
                    rowNode.__cacheData[colId] = value;
                }
            };
            ValueCache.prototype.getValue = function(rowNode, colId) {
                var valueInCache = this.active && rowNode.__cacheVersion === this.cacheVersion && rowNode.__cacheData[colId] !== undefined;
                if (valueInCache) {
                    return rowNode.__cacheData[colId];
                } else {
                    return undefined;
                }
            };
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], ValueCache.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], ValueCache.prototype, "init", null);
            ValueCache = __decorate([ context_1.Bean("valueCache") ], ValueCache);
            return ValueCache;
        }();
        exports.ValueCache = ValueCache;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var column_1 = __webpack_require__(10);
        var rowNode_1 = __webpack_require__(14);
        var constants_1 = __webpack_require__(9);
        var events_1 = __webpack_require__(5);
        var gridCell_1 = __webpack_require__(23);
        var component_1 = __webpack_require__(8);
        var checkboxSelectionComponent_1 = __webpack_require__(65);
        var rowDragComp_1 = __webpack_require__(121);
        var CellComp = function(_super) {
            __extends(CellComp, _super);
            function CellComp(scope, beans, column, rowNode, rowComp, autoHeightCell) {
                var _this = _super.call(this) || this;
                _this.editingCell = false;
                _this.cellEditorVersion = 0;
                _this.cellRendererVersion = 0;
                _this.scope = scope;
                _this.beans = beans;
                _this.column = column;
                _this.rowNode = rowNode;
                _this.rowComp = rowComp;
                _this.autoHeightCell = autoHeightCell;
                _this.createGridCellVo();
                _this.rangeSelectionEnabled = beans.enterprise && beans.gridOptionsWrapper.isEnableRangeSelection();
                _this.cellFocused = _this.beans.focusedCellController.isCellFocused(_this.gridCell);
                _this.firstRightPinned = _this.column.isFirstRightPinned();
                _this.lastLeftPinned = _this.column.isLastLeftPinned();
                if (_this.rangeSelectionEnabled) {
                    _this.rangeCount = _this.beans.rangeController.getCellRangeCount(_this.gridCell);
                }
                _this.getValueAndFormat();
                _this.setUsingWrapper();
                _this.chooseCellRenderer();
                _this.setupColSpan();
                _this.rowSpan = _this.column.getRowSpan(_this.rowNode);
                return _this;
            }
            CellComp.prototype.getCreateTemplate = function() {
                var templateParts = [];
                var col = this.column;
                var width = this.getCellWidth();
                var left = col.getLeft();
                var valueToRender = this.getInitialValueToRender();
                var valueSanitised = utils_1._.get(this.column, "colDef.template", null) ? valueToRender : utils_1._.escape(valueToRender);
                this.tooltip = this.getToolTip();
                var tooltipSanitised = utils_1._.escape(this.tooltip);
                var colIdSanitised = utils_1._.escape(col.getId());
                var wrapperStartTemplate;
                var wrapperEndTemplate;
                var stylesFromColDef = this.preProcessStylesFromColDef();
                var cssClasses = this.getInitialCssClasses();
                var stylesForRowSpanning = this.getStylesForRowSpanning();
                if (this.usingWrapper) {
                    wrapperStartTemplate = '<span ref="eCellWrapper" class="ag-cell-wrapper"><span ref="eCellValue" class="ag-cell-value">';
                    wrapperEndTemplate = "</span></span>";
                }
                templateParts.push("<div");
                templateParts.push(' tabindex="-1"');
                templateParts.push(' role="gridcell"');
                templateParts.push(' comp-id="' + this.getCompId() + '" ');
                templateParts.push(' col-id="' + colIdSanitised + '"');
                templateParts.push(' class="' + cssClasses.join(" ") + '"');
                templateParts.push(tooltipSanitised ? ' title="' + tooltipSanitised + '"' : "");
                templateParts.push(' style="width: ' + width + "px; left: " + left + "px; " + stylesFromColDef + " " + stylesForRowSpanning + '" >');
                templateParts.push(wrapperStartTemplate);
                templateParts.push(valueSanitised);
                templateParts.push(wrapperEndTemplate);
                templateParts.push("</div>");
                return templateParts.join("");
            };
            CellComp.prototype.getStylesForRowSpanning = function() {
                if (this.rowSpan === 1) {
                    return "";
                }
                var singleRowHeight = this.beans.gridOptionsWrapper.getRowHeightAsNumber();
                var totalRowHeight = singleRowHeight * this.rowSpan;
                return "height: " + totalRowHeight + "px; z-index: 1;";
            };
            CellComp.prototype.afterAttached = function() {
                var querySelector = '[comp-id="' + this.getCompId() + '"]';
                var eGui = this.eParentRow.querySelector(querySelector);
                this.setGui(eGui);
                this.addDomData();
                this.populateTemplate();
                this.attachCellRenderer();
                this.angular1Compile();
                this.addDestroyableEventListener(this.beans.eventService, events_1.Events.EVENT_CELL_FOCUSED, this.onCellFocused.bind(this));
                this.addDestroyableEventListener(this.beans.eventService, events_1.Events.EVENT_FLASH_CELLS, this.onFlashCells.bind(this));
                this.addDestroyableEventListener(this.beans.eventService, events_1.Events.EVENT_COLUMN_HOVER_CHANGED, this.onColumnHover.bind(this));
                this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_ROW_INDEX_CHANGED, this.onRowIndexChanged.bind(this));
                this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_CELL_CHANGED, this.onCellChanged.bind(this));
                this.addDestroyableEventListener(this.column, column_1.Column.EVENT_LEFT_CHANGED, this.onLeftChanged.bind(this));
                this.addDestroyableEventListener(this.column, column_1.Column.EVENT_WIDTH_CHANGED, this.onWidthChanged.bind(this));
                this.addDestroyableEventListener(this.column, column_1.Column.EVENT_FIRST_RIGHT_PINNED_CHANGED, this.onFirstRightPinnedChanged.bind(this));
                this.addDestroyableEventListener(this.column, column_1.Column.EVENT_LAST_LEFT_PINNED_CHANGED, this.onLastLeftPinnedChanged.bind(this));
                if (this.rangeSelectionEnabled) {
                    this.addDestroyableEventListener(this.beans.eventService, events_1.Events.EVENT_RANGE_SELECTION_CHANGED, this.onRangeSelectionChanged.bind(this));
                }
            };
            CellComp.prototype.onColumnHover = function() {
                var isHovered = this.beans.columnHoverService.isHovered(this.column);
                utils_1._.addOrRemoveCssClass(this.getGui(), "ag-column-hover", isHovered);
            };
            CellComp.prototype.onCellChanged = function(event) {
                var eventImpactsThisCell = event.column === this.column;
                if (eventImpactsThisCell) {
                    this.refreshCell({});
                }
            };
            CellComp.prototype.getCellLeft = function() {
                var mostLeftCol;
                if (this.beans.gridOptionsWrapper.isEnableRtl() && this.colsSpanning) {
                    mostLeftCol = this.colsSpanning[this.colsSpanning.length - 1];
                } else {
                    mostLeftCol = this.column;
                }
                return mostLeftCol.getLeft();
            };
            CellComp.prototype.getCellWidth = function() {
                if (this.colsSpanning) {
                    var result_1 = 0;
                    this.colsSpanning.forEach(function(col) {
                        return result_1 += col.getActualWidth();
                    });
                    return result_1;
                } else {
                    return this.column.getActualWidth();
                }
            };
            CellComp.prototype.onFlashCells = function(event) {
                var cellId = this.gridCell.createId();
                var shouldFlash = event.cells[cellId];
                if (shouldFlash) {
                    this.animateCell("highlight");
                }
            };
            CellComp.prototype.setupColSpan = function() {
                if (utils_1._.missing(this.column.getColDef().colSpan)) {
                    return;
                }
                this.addDestroyableEventListener(this.beans.eventService, events_1.Events.EVENT_DISPLAYED_COLUMNS_CHANGED, this.onDisplayColumnsChanged.bind(this));
                this.addDestroyableEventListener(this.beans.eventService, events_1.Events.EVENT_DISPLAYED_COLUMNS_WIDTH_CHANGED, this.onWidthChanged.bind(this));
                this.colsSpanning = this.getColSpanningList();
            };
            CellComp.prototype.getColSpanningList = function() {
                var colSpan = this.column.getColSpan(this.rowNode);
                var colsSpanning = [];
                if (colSpan === 1) {
                    colsSpanning.push(this.column);
                } else {
                    var pointer = this.column;
                    var pinned = this.column.getPinned();
                    for (var i = 0; i < colSpan; i++) {
                        colsSpanning.push(pointer);
                        pointer = this.beans.columnController.getDisplayedColAfter(pointer);
                        if (utils_1._.missing(pointer)) {
                            break;
                        }
                        if (pinned !== pointer.getPinned()) {
                            break;
                        }
                    }
                }
                return colsSpanning;
            };
            CellComp.prototype.onDisplayColumnsChanged = function() {
                var colsSpanning = this.getColSpanningList();
                if (!utils_1._.compareArrays(this.colsSpanning, colsSpanning)) {
                    this.colsSpanning = colsSpanning;
                    this.onWidthChanged();
                    this.onLeftChanged();
                }
            };
            CellComp.prototype.getInitialCssClasses = function() {
                var cssClasses = [ "ag-cell", "ag-cell-not-inline-editing" ];
                if (!this.autoHeightCell) {
                    cssClasses.push("ag-cell-with-height");
                }
                var doingFocusCss = !this.beans.gridOptionsWrapper.isSuppressCellSelection();
                if (doingFocusCss) {
                    cssClasses.push(this.cellFocused ? "ag-cell-focus" : "ag-cell-no-focus");
                } else {
                    cssClasses.push("ag-cell-no-focus");
                }
                if (this.firstRightPinned) {
                    cssClasses.push("ag-cell-first-right-pinned");
                }
                if (this.lastLeftPinned) {
                    cssClasses.push("ag-cell-last-left-pinned");
                }
                if (this.beans.columnHoverService.isHovered(this.column)) {
                    cssClasses.push("ag-column-hover");
                }
                utils_1._.pushAll(cssClasses, this.preProcessClassesFromColDef());
                utils_1._.pushAll(cssClasses, this.preProcessCellClassRules());
                utils_1._.pushAll(cssClasses, this.getRangeClasses());
                if (!this.usingWrapper) {
                    cssClasses.push("ag-cell-value");
                }
                return cssClasses;
            };
            CellComp.prototype.getInitialValueToRender = function() {
                if (this.usingCellRenderer) {
                    if (typeof this.cellRendererGui === "string") {
                        return this.cellRendererGui;
                    } else {
                        return "";
                    }
                }
                var colDef = this.column.getColDef();
                if (colDef.template) {
                    return colDef.template;
                } else if (colDef.templateUrl) {
                    var template = this.beans.templateService.getTemplate(colDef.templateUrl, this.refreshCell.bind(this, true));
                    if (template) {
                        return template;
                    } else {
                        return "";
                    }
                } else {
                    return this.getValueToUse();
                }
            };
            CellComp.prototype.getRenderedRow = function() {
                return this.rowComp;
            };
            CellComp.prototype.isSuppressNavigable = function() {
                return this.column.isSuppressNavigable(this.rowNode);
            };
            CellComp.prototype.getCellRenderer = function() {
                return this.cellRenderer;
            };
            CellComp.prototype.getCellEditor = function() {
                return this.cellEditor;
            };
            CellComp.prototype.refreshCell = function(params) {
                if (this.editingCell) {
                    return;
                }
                var newData = params && params.newData;
                var suppressFlash = params && params.suppressFlash || this.column.getColDef().suppressCellFlash;
                var forceRefresh = params && params.forceRefresh;
                var oldValue = this.value;
                this.getValueAndFormat();
                var valuesDifferent = !this.valuesAreEqual(oldValue, this.value);
                var dataNeedsUpdating = forceRefresh || valuesDifferent;
                if (dataNeedsUpdating) {
                    var cellRendererRefreshed = void 0;
                    if (newData || suppressFlash) {
                        cellRendererRefreshed = false;
                    } else {
                        cellRendererRefreshed = this.attemptCellRendererRefresh();
                    }
                    if (!cellRendererRefreshed) {
                        this.replaceContentsAfterRefresh();
                    }
                    if (!suppressFlash) {
                        var flashCell = this.beans.gridOptionsWrapper.isEnableCellChangeFlash() || this.column.getColDef().enableCellChangeFlash;
                        if (flashCell) {
                            this.flashCell();
                        }
                    }
                    this.postProcessStylesFromColDef();
                    this.postProcessClassesFromColDef();
                }
                this.refreshToolTip();
                this.postProcessCellClassRules();
            };
            CellComp.prototype.flashCell = function() {
                this.animateCell("data-changed");
            };
            CellComp.prototype.animateCell = function(cssName) {
                var fullName = "ag-cell-" + cssName;
                var animationFullName = "ag-cell-" + cssName + "-animation";
                var element = this.getGui();
                utils_1._.addCssClass(element, fullName);
                utils_1._.removeCssClass(element, animationFullName);
                setTimeout(function() {
                    utils_1._.removeCssClass(element, fullName);
                    utils_1._.addCssClass(element, animationFullName);
                    setTimeout(function() {
                        utils_1._.removeCssClass(element, animationFullName);
                    }, 1e3);
                }, 500);
            };
            CellComp.prototype.replaceContentsAfterRefresh = function() {
                utils_1._.removeAllChildren(this.eParentOfValue);
                if (this.cellRenderer && this.cellRenderer.destroy) {
                    this.cellRenderer.destroy();
                }
                this.cellRenderer = null;
                this.cellRendererGui = null;
                this.putDataIntoCellAfterRefresh();
                this.angular1Compile();
            };
            CellComp.prototype.angular1Compile = function() {
                if (this.beans.gridOptionsWrapper.isAngularCompileRows()) {
                    var eGui = this.getGui();
                    var compiledElement_1 = this.beans.$compile(eGui)(this.scope);
                    this.addDestroyFunc(function() {
                        compiledElement_1.remove();
                    });
                }
            };
            CellComp.prototype.postProcessStylesFromColDef = function() {
                var stylesToUse = this.processStylesFromColDef();
                if (stylesToUse) {
                    utils_1._.addStylesToElement(this.getGui(), stylesToUse);
                }
            };
            CellComp.prototype.preProcessStylesFromColDef = function() {
                var stylesToUse = this.processStylesFromColDef();
                return utils_1._.cssStyleObjectToMarkup(stylesToUse);
            };
            CellComp.prototype.processStylesFromColDef = function() {
                var colDef = this.column.getColDef();
                if (colDef.cellStyle) {
                    var cssToUse = void 0;
                    if (typeof colDef.cellStyle === "function") {
                        var cellStyleParams = {
                            value: this.value,
                            data: this.rowNode.data,
                            node: this.rowNode,
                            colDef: colDef,
                            column: this.column,
                            $scope: this.scope,
                            context: this.beans.gridOptionsWrapper.getContext(),
                            api: this.beans.gridOptionsWrapper.getApi()
                        };
                        var cellStyleFunc = colDef.cellStyle;
                        cssToUse = cellStyleFunc(cellStyleParams);
                    } else {
                        cssToUse = colDef.cellStyle;
                    }
                    return cssToUse;
                }
            };
            CellComp.prototype.postProcessClassesFromColDef = function() {
                var _this = this;
                this.processClassesFromColDef(function(className) {
                    return utils_1._.addCssClass(_this.getGui(), className);
                });
            };
            CellComp.prototype.preProcessClassesFromColDef = function() {
                var res = [];
                this.processClassesFromColDef(function(className) {
                    return res.push(className);
                });
                return res;
            };
            CellComp.prototype.processClassesFromColDef = function(onApplicableClass) {
                this.beans.stylingService.processStaticCellClasses(this.column.getColDef(), {
                    value: this.value,
                    data: this.rowNode.data,
                    node: this.rowNode,
                    colDef: this.column.getColDef(),
                    rowIndex: this.rowNode.rowIndex,
                    $scope: this.scope,
                    api: this.beans.gridOptionsWrapper.getApi(),
                    context: this.beans.gridOptionsWrapper.getContext()
                }, onApplicableClass);
            };
            CellComp.prototype.putDataIntoCellAfterRefresh = function() {
                var colDef = this.column.getColDef();
                if (colDef.template) {
                    this.eParentOfValue.innerHTML = colDef.template;
                } else if (colDef.templateUrl) {
                    var template = this.beans.templateService.getTemplate(colDef.templateUrl, this.refreshCell.bind(this, true));
                    if (template) {
                        this.eParentOfValue.innerHTML = template;
                    }
                } else if (this.usingCellRenderer) {
                    this.attachCellRenderer();
                } else {
                    var valueToUse = this.getValueToUse();
                    if (valueToUse !== null && valueToUse !== undefined) {
                        this.eParentOfValue.innerText = valueToUse;
                    }
                }
            };
            CellComp.prototype.attemptCellRendererRefresh = function() {
                if (utils_1._.missing(this.cellRenderer) || utils_1._.missing(this.cellRenderer.refresh)) {
                    return false;
                }
                var params = this.createCellRendererParams();
                var result = this.cellRenderer.refresh(params);
                return result === true || result === undefined;
            };
            CellComp.prototype.refreshToolTip = function() {
                var newTooltip = this.getToolTip();
                if (this.tooltip !== newTooltip) {
                    this.tooltip = newTooltip;
                    if (utils_1._.exists(newTooltip)) {
                        var tooltipSanitised = utils_1._.escape(this.tooltip);
                        this.eParentOfValue.setAttribute("title", tooltipSanitised);
                    } else {
                        this.eParentOfValue.removeAttribute("title");
                    }
                }
            };
            CellComp.prototype.valuesAreEqual = function(val1, val2) {
                var colDef = this.column.getColDef();
                var equalsMethod = colDef ? colDef.equals : null;
                if (equalsMethod) {
                    return equalsMethod(val1, val2);
                } else {
                    return val1 === val2;
                }
            };
            CellComp.prototype.getToolTip = function() {
                var colDef = this.column.getColDef();
                var data = this.rowNode.data;
                if (colDef.tooltipField && utils_1._.exists(data)) {
                    return utils_1._.getValueUsingField(data, colDef.tooltipField, this.column.isTooltipFieldContainsDots());
                } else if (colDef.tooltip) {
                    return colDef.tooltip({
                        value: this.value,
                        valueFormatted: this.valueFormatted,
                        data: this.rowNode.data,
                        node: this.rowNode,
                        colDef: this.column.getColDef(),
                        api: this.beans.gridOptionsWrapper.getApi(),
                        $scope: this.scope,
                        context: this.beans.gridOptionsWrapper.getContext(),
                        rowIndex: this.gridCell.rowIndex
                    });
                } else {
                    return null;
                }
            };
            CellComp.prototype.processCellClassRules = function(onApplicableClass, onNotApplicableClass) {
                this.beans.stylingService.processClassRules(this.column.getColDef().cellClassRules, {
                    value: this.value,
                    data: this.rowNode.data,
                    node: this.rowNode,
                    colDef: this.column.getColDef(),
                    rowIndex: this.gridCell.rowIndex,
                    api: this.beans.gridOptionsWrapper.getApi(),
                    $scope: this.scope,
                    context: this.beans.gridOptionsWrapper.getContext()
                }, onApplicableClass, onNotApplicableClass);
            };
            CellComp.prototype.postProcessCellClassRules = function() {
                var _this = this;
                this.processCellClassRules(function(className) {
                    utils_1._.addCssClass(_this.getGui(), className);
                }, function(className) {
                    utils_1._.removeCssClass(_this.getGui(), className);
                });
            };
            CellComp.prototype.preProcessCellClassRules = function() {
                var res = [];
                this.processCellClassRules(function(className) {
                    res.push(className);
                }, function(className) {});
                return res;
            };
            CellComp.prototype.setUsingWrapper = function() {
                var colDef = this.column.getColDef();
                if (this.rowNode.rowPinned) {
                    this.usingWrapper = false;
                    this.includeSelectionComponent = false;
                    this.includeRowDraggingComponent = false;
                    return;
                }
                var cbSelectionIsFunc = typeof colDef.checkboxSelection === "function";
                var rowDraggableIsFunc = typeof colDef.rowDrag === "function";
                this.includeSelectionComponent = cbSelectionIsFunc || colDef.checkboxSelection === true;
                this.includeRowDraggingComponent = rowDraggableIsFunc || colDef.rowDrag === true;
                this.usingWrapper = this.includeRowDraggingComponent || this.includeSelectionComponent;
            };
            CellComp.prototype.chooseCellRenderer = function() {
                var colDef = this.column.getColDef();
                if (colDef.template || colDef.templateUrl) {
                    this.usingCellRenderer = false;
                    return;
                }
                var params = this.createCellRendererParams();
                var cellRenderer = this.beans.componentResolver.getComponentToUse(colDef, "cellRenderer", params, null);
                var pinnedRowCellRenderer = this.beans.componentResolver.getComponentToUse(colDef, "pinnedRowCellRenderer", params, null);
                if (pinnedRowCellRenderer && this.rowNode.rowPinned) {
                    this.cellRendererType = "pinnedRowCellRenderer";
                    this.usingCellRenderer = true;
                } else if (cellRenderer) {
                    this.cellRendererType = "cellRenderer";
                    this.usingCellRenderer = true;
                } else {
                    this.usingCellRenderer = false;
                }
            };
            CellComp.prototype.createCellRendererInstance = function() {
                var params = this.createCellRendererParams();
                this.cellRendererVersion++;
                var callback = this.afterCellRendererCreated.bind(this, this.cellRendererVersion);
                this.beans.componentResolver.createAgGridComponent(this.column.getColDef(), params, this.cellRendererType, params, null).then(callback);
            };
            CellComp.prototype.afterCellRendererCreated = function(cellRendererVersion, cellRenderer) {
                if (cellRendererVersion !== this.cellRendererVersion) {
                    if (cellRenderer.destroy) {
                        cellRenderer.destroy();
                    }
                    return;
                }
                this.cellRenderer = cellRenderer;
                this.cellRendererGui = this.cellRenderer.getGui();
                if (utils_1._.missing(this.cellRendererGui)) {
                    return;
                }
                if (!this.editingCell) {
                    this.eParentOfValue.appendChild(this.cellRendererGui);
                }
            };
            CellComp.prototype.attachCellRenderer = function() {
                if (!this.usingCellRenderer) {
                    return;
                }
                this.createCellRendererInstance();
            };
            CellComp.prototype.createCellRendererParams = function() {
                var _this = this;
                var params = {
                    value: this.value,
                    valueFormatted: this.valueFormatted,
                    getValue: this.getValue.bind(this),
                    setValue: function(value) {
                        _this.beans.valueService.setValue(_this.rowNode, _this.column, value);
                    },
                    formatValue: this.formatValue.bind(this),
                    data: this.rowNode.data,
                    node: this.rowNode,
                    colDef: this.column.getColDef(),
                    column: this.column,
                    $scope: this.scope,
                    rowIndex: this.gridCell.rowIndex,
                    api: this.beans.gridOptionsWrapper.getApi(),
                    columnApi: this.beans.gridOptionsWrapper.getColumnApi(),
                    context: this.beans.gridOptionsWrapper.getContext(),
                    refreshCell: this.refreshCell.bind(this),
                    eGridCell: this.getGui(),
                    eParentOfValue: this.eParentOfValue,
                    addRowCompListener: this.rowComp ? this.rowComp.addEventListener.bind(this.rowComp) : null,
                    addRenderedRowListener: function(eventType, listener) {
                        console.warn("ag-Grid: since ag-Grid .v11, params.addRenderedRowListener() is now params.addRowCompListener()");
                        if (_this.rowComp) {
                            _this.rowComp.addEventListener(eventType, listener);
                        }
                    }
                };
                return params;
            };
            CellComp.prototype.formatValue = function(value) {
                var valueFormatted = this.beans.valueFormatterService.formatValue(this.column, this.rowNode, this.scope, value);
                var valueFormattedExists = valueFormatted !== null && valueFormatted !== undefined;
                return valueFormattedExists ? valueFormatted : value;
            };
            CellComp.prototype.getValueToUse = function() {
                var valueFormattedExists = this.valueFormatted !== null && this.valueFormatted !== undefined;
                return valueFormattedExists ? this.valueFormatted : this.value;
            };
            CellComp.prototype.getValueAndFormat = function() {
                this.value = this.getValue();
                this.valueFormatted = this.beans.valueFormatterService.formatValue(this.column, this.rowNode, this.scope, this.value);
            };
            CellComp.prototype.getValue = function() {
                var lockedClosedGroup = this.rowNode.leafGroup && this.beans.columnController.isPivotMode();
                var isOpenGroup = this.rowNode.group && this.rowNode.expanded && !this.rowNode.footer && !lockedClosedGroup;
                if (isOpenGroup && this.beans.gridOptionsWrapper.isGroupIncludeFooter()) {
                    return this.beans.valueService.getValue(this.column, this.rowNode, false, true);
                } else {
                    return this.beans.valueService.getValue(this.column, this.rowNode);
                }
            };
            CellComp.prototype.onMouseEvent = function(eventName, mouseEvent) {
                if (utils_1._.isStopPropagationForAgGrid(mouseEvent)) {
                    return;
                }
                switch (eventName) {
                  case "click":
                    this.onCellClicked(mouseEvent);
                    break;

                  case "mousedown":
                    this.onMouseDown(mouseEvent);
                    break;

                  case "dblclick":
                    this.onCellDoubleClicked(mouseEvent);
                    break;

                  case "mouseout":
                    this.onMouseOut(mouseEvent);
                    break;

                  case "mouseover":
                    this.onMouseOver(mouseEvent);
                    break;
                }
            };
            CellComp.prototype.dispatchCellContextMenuEvent = function(event) {
                var colDef = this.column.getColDef();
                var cellContextMenuEvent = this.createEvent(event, events_1.Events.EVENT_CELL_CONTEXT_MENU);
                this.beans.eventService.dispatchEvent(cellContextMenuEvent);
                if (colDef.onCellContextMenu) {
                    setTimeout(function() {
                        return colDef.onCellContextMenu(cellContextMenuEvent);
                    }, 0);
                }
            };
            CellComp.prototype.createEvent = function(domEvent, eventType) {
                var event = {
                    node: this.rowNode,
                    data: this.rowNode.data,
                    value: this.value,
                    column: this.column,
                    colDef: this.column.getColDef(),
                    context: this.beans.gridOptionsWrapper.getContext(),
                    api: this.beans.gridApi,
                    columnApi: this.beans.columnApi,
                    rowPinned: this.rowNode.rowPinned,
                    event: domEvent,
                    type: eventType,
                    rowIndex: this.rowNode.rowIndex
                };
                if (this.scope) {
                    event.$scope = this.scope;
                }
                return event;
            };
            CellComp.prototype.onMouseOut = function(mouseEvent) {
                var cellMouseOutEvent = this.createEvent(mouseEvent, events_1.Events.EVENT_CELL_MOUSE_OUT);
                this.beans.eventService.dispatchEvent(cellMouseOutEvent);
                this.beans.columnHoverService.clearMouseOver();
            };
            CellComp.prototype.onMouseOver = function(mouseEvent) {
                var cellMouseOverEvent = this.createEvent(mouseEvent, events_1.Events.EVENT_CELL_MOUSE_OVER);
                this.beans.eventService.dispatchEvent(cellMouseOverEvent);
                this.beans.columnHoverService.setMouseOver([ this.column ]);
            };
            CellComp.prototype.onCellDoubleClicked = function(mouseEvent) {
                var colDef = this.column.getColDef();
                var cellDoubleClickedEvent = this.createEvent(mouseEvent, events_1.Events.EVENT_CELL_DOUBLE_CLICKED);
                this.beans.eventService.dispatchEvent(cellDoubleClickedEvent);
                if (typeof colDef.onCellDoubleClicked === "function") {
                    setTimeout(function() {
                        return colDef.onCellDoubleClicked(cellDoubleClickedEvent);
                    }, 0);
                }
                var editOnDoubleClick = !this.beans.gridOptionsWrapper.isSingleClickEdit() && !this.beans.gridOptionsWrapper.isSuppressClickEdit();
                if (editOnDoubleClick) {
                    this.startRowOrCellEdit();
                }
            };
            CellComp.prototype.startRowOrCellEdit = function(keyPress, charPress) {
                if (this.beans.gridOptionsWrapper.isFullRowEdit()) {
                    this.rowComp.startRowEditing(keyPress, charPress, this);
                } else {
                    this.startEditingIfEnabled(keyPress, charPress, true);
                }
            };
            CellComp.prototype.isCellEditable = function() {
                return this.column.isCellEditable(this.rowNode);
            };
            CellComp.prototype.startEditingIfEnabled = function(keyPress, charPress, cellStartedEdit) {
                if (keyPress === void 0) {
                    keyPress = null;
                }
                if (charPress === void 0) {
                    charPress = null;
                }
                if (cellStartedEdit === void 0) {
                    cellStartedEdit = false;
                }
                if (!this.isCellEditable()) {
                    return;
                }
                if (this.editingCell) {
                    return;
                }
                this.editingCell = true;
                this.cellEditorVersion++;
                var callback = this.afterCellEditorCreated.bind(this, this.cellEditorVersion);
                var params = this.createCellEditorParams(keyPress, charPress, cellStartedEdit);
                this.beans.cellEditorFactory.createCellEditor(this.column.getColDef(), params).then(callback);
                var cellEditorAsync = utils_1._.missing(this.cellEditor);
                if (cellEditorAsync && cellStartedEdit) {
                    this.focusCell(true);
                }
            };
            CellComp.prototype.afterCellEditorCreated = function(cellEditorVersion, cellEditor) {
                var versionMismatch = cellEditorVersion !== this.cellEditorVersion;
                if (versionMismatch || !this.editingCell) {
                    if (cellEditor.destroy) {
                        cellEditor.destroy();
                    }
                    return;
                }
                if (cellEditor.isCancelBeforeStart && cellEditor.isCancelBeforeStart()) {
                    if (cellEditor.destroy) {
                        cellEditor.destroy();
                    }
                    this.editingCell = false;
                    return;
                }
                if (!cellEditor.getGui) {
                    console.warn("ag-Grid: cellEditor for column " + this.column.getId() + " is missing getGui() method");
                    if (cellEditor.render) {
                        console.warn("ag-Grid: we found 'render' on the component, are you trying to set a React renderer but added it as colDef.cellEditor instead of colDef.cellEditorFmk?");
                    }
                    if (cellEditor.destroy) {
                        cellEditor.destroy();
                    }
                    this.editingCell = false;
                    return;
                }
                this.cellEditor = cellEditor;
                this.cellEditorInPopup = cellEditor.isPopup && cellEditor.isPopup();
                this.setInlineEditingClass();
                if (this.cellEditorInPopup) {
                    this.addPopupCellEditor();
                } else {
                    this.addInCellEditor();
                }
                if (cellEditor.afterGuiAttached) {
                    cellEditor.afterGuiAttached();
                }
                var event = this.createEvent(null, events_1.Events.EVENT_CELL_EDITING_STARTED);
                this.beans.eventService.dispatchEvent(event);
            };
            CellComp.prototype.addInCellEditor = function() {
                utils_1._.removeAllChildren(this.getGui());
                this.getGui().appendChild(this.cellEditor.getGui());
                this.angular1Compile();
            };
            CellComp.prototype.addPopupCellEditor = function() {
                var _this = this;
                var ePopupGui = this.cellEditor.getGui();
                this.hideEditorPopup = this.beans.popupService.addAsModalPopup(ePopupGui, true, function() {
                    _this.onPopupEditorClosed();
                });
                this.beans.popupService.positionPopupOverComponent({
                    column: this.column,
                    rowNode: this.rowNode,
                    type: "popupCellEditor",
                    eventSource: this.getGui(),
                    ePopup: ePopupGui,
                    keepWithinBounds: true
                });
                this.angular1Compile();
            };
            CellComp.prototype.onPopupEditorClosed = function() {
                if (this.editingCell) {
                    this.stopRowOrCellEdit();
                    if (this.beans.focusedCellController.isCellFocused(this.gridCell)) {
                        this.focusCell(true);
                    }
                }
            };
            CellComp.prototype.setInlineEditingClass = function() {
                var editingInline = this.editingCell && !this.cellEditorInPopup;
                var popupEditorShowing = this.editingCell && this.cellEditorInPopup;
                utils_1._.addOrRemoveCssClass(this.getGui(), "ag-cell-inline-editing", editingInline);
                utils_1._.addOrRemoveCssClass(this.getGui(), "ag-cell-not-inline-editing", !editingInline);
                utils_1._.addOrRemoveCssClass(this.getGui(), "ag-cell-popup-editing", popupEditorShowing);
                utils_1._.addOrRemoveCssClass(this.getGui().parentNode, "ag-row-inline-editing", editingInline);
                utils_1._.addOrRemoveCssClass(this.getGui().parentNode, "ag-row-not-inline-editing", !editingInline);
            };
            CellComp.prototype.createCellEditorParams = function(keyPress, charPress, cellStartedEdit) {
                var params = {
                    value: this.getValue(),
                    keyPress: keyPress,
                    charPress: charPress,
                    column: this.column,
                    rowIndex: this.gridCell.rowIndex,
                    node: this.rowNode,
                    api: this.beans.gridOptionsWrapper.getApi(),
                    cellStartedEdit: cellStartedEdit,
                    columnApi: this.beans.gridOptionsWrapper.getColumnApi(),
                    context: this.beans.gridOptionsWrapper.getContext(),
                    $scope: this.scope,
                    onKeyDown: this.onKeyDown.bind(this),
                    stopEditing: this.stopEditingAndFocus.bind(this),
                    eGridCell: this.getGui(),
                    parseValue: this.parseValue.bind(this),
                    formatValue: this.formatValue.bind(this)
                };
                return params;
            };
            CellComp.prototype.stopEditingAndFocus = function(suppressNavigateAfterEdit) {
                if (suppressNavigateAfterEdit === void 0) {
                    suppressNavigateAfterEdit = false;
                }
                this.stopRowOrCellEdit();
                this.focusCell(true);
                if (!suppressNavigateAfterEdit) {
                    this.navigateAfterEdit();
                }
            };
            CellComp.prototype.parseValue = function(newValue) {
                var params = {
                    node: this.rowNode,
                    data: this.rowNode.data,
                    oldValue: this.value,
                    newValue: newValue,
                    colDef: this.column.getColDef(),
                    column: this.column,
                    api: this.beans.gridOptionsWrapper.getApi(),
                    columnApi: this.beans.gridOptionsWrapper.getColumnApi(),
                    context: this.beans.gridOptionsWrapper.getContext()
                };
                var valueParser = this.column.getColDef().valueParser;
                return utils_1._.exists(valueParser) ? this.beans.expressionService.evaluate(valueParser, params) : newValue;
            };
            CellComp.prototype.focusCell = function(forceBrowserFocus) {
                if (forceBrowserFocus === void 0) {
                    forceBrowserFocus = false;
                }
                this.beans.focusedCellController.setFocusedCell(this.gridCell.rowIndex, this.column, this.rowNode.rowPinned, forceBrowserFocus);
            };
            CellComp.prototype.setFocusInOnEditor = function() {
                if (this.editingCell) {
                    if (this.cellEditor && this.cellEditor.focusIn) {
                        this.cellEditor.focusIn();
                    } else {
                        this.focusCell(true);
                    }
                }
            };
            CellComp.prototype.isEditing = function() {
                return this.editingCell;
            };
            CellComp.prototype.onKeyDown = function(event) {
                var key = event.which || event.keyCode;
                if (this.doesUserWantToCancelKeyboardEvent(event)) {
                    return;
                }
                switch (key) {
                  case constants_1.Constants.KEY_ENTER:
                    this.onEnterKeyDown();
                    break;

                  case constants_1.Constants.KEY_F2:
                    this.onF2KeyDown();
                    break;

                  case constants_1.Constants.KEY_ESCAPE:
                    this.onEscapeKeyDown();
                    break;

                  case constants_1.Constants.KEY_TAB:
                    this.onTabKeyDown(event);
                    break;

                  case constants_1.Constants.KEY_BACKSPACE:
                  case constants_1.Constants.KEY_DELETE:
                    this.onBackspaceOrDeleteKeyPressed(key);
                    break;

                  case constants_1.Constants.KEY_DOWN:
                  case constants_1.Constants.KEY_UP:
                  case constants_1.Constants.KEY_RIGHT:
                  case constants_1.Constants.KEY_LEFT:
                    this.onNavigationKeyPressed(event, key);
                    break;
                }
            };
            CellComp.prototype.doesUserWantToCancelKeyboardEvent = function(event) {
                var callback = this.column.getColDef().suppressKeyboardEvent;
                if (utils_1._.missing(callback)) {
                    return false;
                } else {
                    var params = {
                        event: event,
                        editing: this.editingCell,
                        column: this.column,
                        api: this.beans.gridOptionsWrapper.getApi(),
                        node: this.rowNode,
                        data: this.rowNode.data,
                        colDef: this.column.getColDef(),
                        context: this.beans.gridOptionsWrapper.getContext(),
                        columnApi: this.beans.gridOptionsWrapper.getColumnApi()
                    };
                    return callback(params);
                }
            };
            CellComp.prototype.setFocusOutOnEditor = function() {
                if (this.editingCell && this.cellEditor && this.cellEditor.focusOut) {
                    this.cellEditor.focusOut();
                }
            };
            CellComp.prototype.onNavigationKeyPressed = function(event, key) {
                if (this.editingCell) {
                    this.stopRowOrCellEdit();
                }
                if (event.shiftKey && this.rangeSelectionEnabled) {
                    this.onShiftRangeSelect(key);
                } else {
                    this.beans.rowRenderer.navigateToNextCell(event, key, this.gridCell, true);
                }
                event.preventDefault();
            };
            CellComp.prototype.onShiftRangeSelect = function(key) {
                var success = this.beans.rangeController.extendRangeInDirection(this.gridCell, key);
                if (!success) {
                    return;
                }
                var ranges = this.beans.rangeController.getCellRanges();
                if (utils_1._.missing(ranges) || ranges.length !== 1) {
                    return;
                }
                var endCell = ranges[0].end;
                this.beans.rowRenderer.ensureCellVisible(endCell);
            };
            CellComp.prototype.onTabKeyDown = function(event) {
                if (this.beans.gridOptionsWrapper.isSuppressTabbing()) {
                    return;
                }
                this.beans.rowRenderer.onTabKeyDown(this, event);
            };
            CellComp.prototype.onBackspaceOrDeleteKeyPressed = function(key) {
                if (!this.editingCell) {
                    this.startRowOrCellEdit(key);
                }
            };
            CellComp.prototype.onEnterKeyDown = function() {
                if (this.editingCell || this.rowComp.isEditing()) {
                    this.stopEditingAndFocus();
                } else {
                    if (this.beans.gridOptionsWrapper.isEnterMovesDown()) {
                        this.beans.rowRenderer.navigateToNextCell(null, constants_1.Constants.KEY_DOWN, this.gridCell, false);
                    } else {
                        this.startRowOrCellEdit(constants_1.Constants.KEY_ENTER);
                    }
                }
            };
            CellComp.prototype.navigateAfterEdit = function() {
                var fullRowEdit = this.beans.gridOptionsWrapper.isFullRowEdit();
                if (fullRowEdit) {
                    return;
                }
                var enterMovesDownAfterEdit = this.beans.gridOptionsWrapper.isEnterMovesDownAfterEdit();
                if (enterMovesDownAfterEdit) {
                    this.beans.rowRenderer.navigateToNextCell(null, constants_1.Constants.KEY_DOWN, this.gridCell, false);
                }
            };
            CellComp.prototype.onF2KeyDown = function() {
                if (!this.editingCell) {
                    this.startRowOrCellEdit(constants_1.Constants.KEY_F2);
                }
            };
            CellComp.prototype.onEscapeKeyDown = function() {
                if (this.editingCell) {
                    this.stopRowOrCellEdit(true);
                    this.focusCell(true);
                }
            };
            CellComp.prototype.onKeyPress = function(event) {
                var eventTarget = utils_1._.getTarget(event);
                var eventOnChildComponent = eventTarget !== this.getGui();
                if (eventOnChildComponent) {
                    return;
                }
                if (!this.editingCell) {
                    var pressedChar = String.fromCharCode(event.charCode);
                    if (pressedChar === " ") {
                        this.onSpaceKeyPressed(event);
                    } else {
                        if (utils_1._.isEventFromPrintableCharacter(event)) {
                            this.startRowOrCellEdit(null, pressedChar);
                            event.preventDefault();
                        }
                    }
                }
            };
            CellComp.prototype.onSpaceKeyPressed = function(event) {
                if (!this.editingCell && this.beans.gridOptionsWrapper.isRowSelection()) {
                    var selected = this.rowNode.isSelected();
                    this.rowNode.setSelected(!selected);
                }
                event.preventDefault();
            };
            CellComp.prototype.onMouseDown = function(mouseEvent) {
                this.focusCell(false);
                if (this.beans.rangeController) {
                    var thisCell = this.gridCell;
                    if (mouseEvent.shiftKey) {
                        this.beans.rangeController.extendRangeToCell(thisCell);
                    } else {
                        var cellAlreadyInRange = this.beans.rangeController.isCellInAnyRange(thisCell);
                        if (!cellAlreadyInRange) {
                            var ctrlKeyPressed = mouseEvent.ctrlKey || mouseEvent.metaKey;
                            this.beans.rangeController.setRangeToCell(thisCell, ctrlKeyPressed);
                        }
                    }
                }
                var cellMouseDownEvent = this.createEvent(mouseEvent, events_1.Events.EVENT_CELL_MOUSE_DOWN);
                this.beans.eventService.dispatchEvent(cellMouseDownEvent);
            };
            CellComp.prototype.isDoubleClickOnIPad = function() {
                if (!utils_1._.isUserAgentIPad()) {
                    return false;
                }
                var nowMillis = new Date().getTime();
                var res = nowMillis - this.lastIPadMouseClickEvent < 200;
                this.lastIPadMouseClickEvent = nowMillis;
                return res;
            };
            CellComp.prototype.onCellClicked = function(mouseEvent) {
                if (this.isDoubleClickOnIPad()) {
                    this.onCellDoubleClicked(mouseEvent);
                    mouseEvent.preventDefault();
                    return;
                }
                var cellClickedEvent = this.createEvent(mouseEvent, events_1.Events.EVENT_CELL_CLICKED);
                this.beans.eventService.dispatchEvent(cellClickedEvent);
                var colDef = this.column.getColDef();
                if (colDef.onCellClicked) {
                    setTimeout(function() {
                        return colDef.onCellClicked(cellClickedEvent);
                    }, 0);
                }
                var editOnSingleClick = this.beans.gridOptionsWrapper.isSingleClickEdit() && !this.beans.gridOptionsWrapper.isSuppressClickEdit();
                if (editOnSingleClick) {
                    this.startRowOrCellEdit();
                }
                this.doIeFocusHack();
            };
            CellComp.prototype.doIeFocusHack = function() {
                if (utils_1._.isBrowserIE() || utils_1._.isBrowserEdge()) {
                    if (utils_1._.missing(document.activeElement) || document.activeElement === document.body) {
                        this.getGui().focus();
                    }
                }
            };
            CellComp.prototype.createGridCellVo = function() {
                var gridCellDef = {
                    rowIndex: this.rowNode.rowIndex,
                    floating: this.rowNode.rowPinned,
                    column: this.column
                };
                this.gridCell = new gridCell_1.GridCell(gridCellDef);
            };
            CellComp.prototype.getGridCell = function() {
                return this.gridCell;
            };
            CellComp.prototype.getParentRow = function() {
                return this.eParentRow;
            };
            CellComp.prototype.setParentRow = function(eParentRow) {
                this.eParentRow = eParentRow;
            };
            CellComp.prototype.getColumn = function() {
                return this.column;
            };
            CellComp.prototype.detach = function() {
                this.eParentRow.removeChild(this.getGui());
            };
            CellComp.prototype.destroy = function() {
                _super.prototype.destroy.call(this);
                if (this.cellEditor && this.cellEditor.destroy) {
                    this.cellEditor.destroy();
                    this.cellEditor = null;
                }
                if (this.cellRenderer && this.cellRenderer.destroy) {
                    this.cellRenderer.destroy();
                    this.cellRenderer = null;
                }
            };
            CellComp.prototype.onLeftChanged = function() {
                var left = this.getCellLeft();
                this.getGui().style.left = left + "px";
            };
            CellComp.prototype.onWidthChanged = function() {
                var width = this.getCellWidth();
                this.getGui().style.width = width + "px";
            };
            CellComp.prototype.getRangeClasses = function() {
                var res = [];
                if (!this.rangeSelectionEnabled) {
                    return res;
                }
                if (this.rangeCount !== 0) {
                    res.push("ag-cell-range-selected");
                }
                if (this.rangeCount === 1) {
                    res.push("ag-cell-range-selected-1");
                }
                if (this.rangeCount === 2) {
                    res.push("ag-cell-range-selected-2");
                }
                if (this.rangeCount === 3) {
                    res.push("ag-cell-range-selected-3");
                }
                if (this.rangeCount >= 4) {
                    res.push("ag-cell-range-selected-4");
                }
                return res;
            };
            CellComp.prototype.onRowIndexChanged = function() {
                this.createGridCellVo();
                this.onCellFocused();
                this.onRangeSelectionChanged();
            };
            CellComp.prototype.onRangeSelectionChanged = function() {
                if (!this.beans.enterprise) {
                    return;
                }
                var newRangeCount = this.beans.rangeController.getCellRangeCount(this.gridCell);
                var element = this.getGui();
                if (this.rangeCount !== newRangeCount) {
                    utils_1._.addOrRemoveCssClass(element, "ag-cell-range-selected", newRangeCount !== 0);
                    utils_1._.addOrRemoveCssClass(element, "ag-cell-range-selected-1", newRangeCount === 1);
                    utils_1._.addOrRemoveCssClass(element, "ag-cell-range-selected-2", newRangeCount === 2);
                    utils_1._.addOrRemoveCssClass(element, "ag-cell-range-selected-3", newRangeCount === 3);
                    utils_1._.addOrRemoveCssClass(element, "ag-cell-range-selected-4", newRangeCount >= 4);
                    this.rangeCount = newRangeCount;
                }
            };
            CellComp.prototype.onFirstRightPinnedChanged = function() {
                var firstRightPinned = this.column.isFirstRightPinned();
                if (this.firstRightPinned !== firstRightPinned) {
                    this.firstRightPinned = firstRightPinned;
                    utils_1._.addOrRemoveCssClass(this.getGui(), "ag-cell-first-right-pinned", firstRightPinned);
                }
            };
            CellComp.prototype.onLastLeftPinnedChanged = function() {
                var lastLeftPinned = this.column.isLastLeftPinned();
                if (this.lastLeftPinned !== lastLeftPinned) {
                    this.lastLeftPinned = lastLeftPinned;
                    utils_1._.addOrRemoveCssClass(this.getGui(), "ag-cell-last-left-pinned", lastLeftPinned);
                }
            };
            CellComp.prototype.populateTemplate = function() {
                if (this.usingWrapper) {
                    this.eParentOfValue = this.getRefElement("eCellValue");
                    this.eCellWrapper = this.getRefElement("eCellWrapper");
                    if (this.includeRowDraggingComponent) {
                        this.addRowDragging();
                    }
                    if (this.includeSelectionComponent) {
                        this.addSelectionCheckbox();
                    }
                } else {
                    this.eParentOfValue = this.getGui();
                }
            };
            CellComp.prototype.addRowDragging = function() {
                if (!this.beans.gridOptionsWrapper.isRowModelDefault()) {
                    utils_1._.doOnce(function() {
                        return console.warn("ag-Grid: row dragging is only allowed in the In Memory Row Model");
                    }, "CellComp.addRowDragging");
                    return;
                }
                if (this.beans.gridOptionsWrapper.isPagination()) {
                    utils_1._.doOnce(function() {
                        return console.warn("ag-Grid: row dragging is not possible when doing pagination");
                    }, "CellComp.addRowDragging");
                    return;
                }
                var rowDraggingComp = new rowDragComp_1.RowDragComp(this.rowNode, this.column, this.getValueToUse(), this.beans);
                this.addFeature(this.beans.context, rowDraggingComp);
                this.eCellWrapper.insertBefore(rowDraggingComp.getGui(), this.eParentOfValue);
            };
            CellComp.prototype.addSelectionCheckbox = function() {
                var cbSelectionComponent = new checkboxSelectionComponent_1.CheckboxSelectionComponent();
                this.beans.context.wireBean(cbSelectionComponent);
                var visibleFunc = this.column.getColDef().checkboxSelection;
                visibleFunc = typeof visibleFunc === "function" ? visibleFunc : null;
                cbSelectionComponent.init({
                    rowNode: this.rowNode,
                    column: this.column,
                    visibleFunc: visibleFunc
                });
                this.addDestroyFunc(function() {
                    return cbSelectionComponent.destroy();
                });
                this.eCellWrapper.insertBefore(cbSelectionComponent.getGui(), this.eParentOfValue);
            };
            CellComp.prototype.addDomData = function() {
                var _this = this;
                var element = this.getGui();
                this.beans.gridOptionsWrapper.setDomData(element, CellComp.DOM_DATA_KEY_CELL_COMP, this);
                this.addDestroyFunc(function() {
                    return _this.beans.gridOptionsWrapper.setDomData(element, CellComp.DOM_DATA_KEY_CELL_COMP, null);
                });
            };
            CellComp.prototype.onCellFocused = function(event) {
                var cellFocused = this.beans.focusedCellController.isCellFocused(this.gridCell);
                if (cellFocused !== this.cellFocused) {
                    var doingFocusCss = !this.beans.gridOptionsWrapper.isSuppressCellSelection();
                    if (doingFocusCss) {
                        utils_1._.addOrRemoveCssClass(this.getGui(), "ag-cell-focus", cellFocused);
                        utils_1._.addOrRemoveCssClass(this.getGui(), "ag-cell-no-focus", !cellFocused);
                    }
                    this.cellFocused = cellFocused;
                }
                if (cellFocused && event && event.forceBrowserFocus) {
                    this.getGui().focus();
                }
                var fullRowEdit = this.beans.gridOptionsWrapper.isFullRowEdit();
                if (!cellFocused && !fullRowEdit && this.editingCell) {
                    this.stopRowOrCellEdit();
                }
            };
            CellComp.prototype.stopRowOrCellEdit = function(cancel) {
                if (cancel === void 0) {
                    cancel = false;
                }
                if (this.beans.gridOptionsWrapper.isFullRowEdit()) {
                    this.rowComp.stopRowEditing(cancel);
                } else {
                    this.stopEditing(cancel);
                }
            };
            CellComp.prototype.stopEditing = function(cancel) {
                if (cancel === void 0) {
                    cancel = false;
                }
                if (!this.editingCell) {
                    return;
                }
                if (!this.cellEditor) {
                    this.editingCell = false;
                    return;
                }
                var newValueExists = false;
                var newValue;
                if (!cancel) {
                    var userWantsToCancel = this.cellEditor.isCancelAfterEnd && this.cellEditor.isCancelAfterEnd();
                    if (!userWantsToCancel) {
                        newValue = this.cellEditor.getValue();
                        newValueExists = true;
                    }
                }
                this.editingCell = false;
                if (this.cellEditor.destroy) {
                    this.cellEditor.destroy();
                }
                this.cellEditor = null;
                if (this.cellEditorInPopup) {
                    this.hideEditorPopup();
                    this.hideEditorPopup = null;
                } else {
                    utils_1._.removeAllChildren(this.getGui());
                    if (this.usingWrapper) {
                        this.getGui().appendChild(this.eCellWrapper);
                    } else {
                        if (this.cellRenderer) {
                            var eCell = this.cellRendererGui;
                            if (eCell) {
                                this.getGui().appendChild(eCell);
                            }
                        }
                    }
                }
                this.setInlineEditingClass();
                if (newValueExists) {
                    this.rowNode.setDataValue(this.column, newValue);
                    this.getValueAndFormat();
                }
                this.refreshCell({
                    forceRefresh: true,
                    suppressFlash: true
                });
                var event = this.createEvent(null, events_1.Events.EVENT_CELL_EDITING_STOPPED);
                this.beans.eventService.dispatchEvent(event);
            };
            CellComp.DOM_DATA_KEY_CELL_COMP = "cellComp";
            return CellComp;
        }(component_1.Component);
        exports.CellComp = CellComp;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var constants_1 = __webpack_require__(9);
        var context_1 = __webpack_require__(0);
        var gridCore_1 = __webpack_require__(42);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var environment_1 = __webpack_require__(41);
        var PopupService = function() {
            function PopupService() {
                this.activePopupElements = [];
            }
            PopupService.prototype.getPopupParent = function() {
                var ePopupParent = this.gridOptionsWrapper.getPopupParent();
                if (ePopupParent) {
                    return ePopupParent;
                } else {
                    return this.gridCore.getRootGui();
                }
            };
            PopupService.prototype.positionPopupForMenu = function(params) {
                var sourceRect = params.eventSource.getBoundingClientRect();
                var parentRect = this.getPopupParent().getBoundingClientRect();
                var y = sourceRect.top - parentRect.top;
                y = this.keepYWithinBounds(params, y);
                var minWidth = params.ePopup.clientWidth > 0 ? params.ePopup.clientWidth : 200;
                var widthOfParent = parentRect.right - parentRect.left;
                var maxX = widthOfParent - minWidth;
                var x;
                if (this.gridOptionsWrapper.isEnableRtl()) {
                    x = xLeftPosition();
                    if (x < 0) {
                        x = xRightPosition();
                    }
                    if (x > maxX) {
                        x = 0;
                    }
                } else {
                    x = xRightPosition();
                    if (x > maxX) {
                        x = xLeftPosition();
                    }
                    if (x < 0) {
                        x = 0;
                    }
                }
                params.ePopup.style.left = x + "px";
                params.ePopup.style.top = y + "px";
                function xRightPosition() {
                    return sourceRect.right - parentRect.left - 2;
                }
                function xLeftPosition() {
                    return sourceRect.left - parentRect.left - minWidth;
                }
            };
            PopupService.prototype.positionPopupUnderMouseEvent = function(params) {
                var parentRect = this.getPopupParent().getBoundingClientRect();
                this.positionPopup({
                    ePopup: params.ePopup,
                    x: params.mouseEvent.clientX - parentRect.left,
                    y: params.mouseEvent.clientY - parentRect.top,
                    keepWithinBounds: true
                });
                this.callPostProcessPopup(params.ePopup, null, params.mouseEvent, params.type, params.column, params.rowNode);
            };
            PopupService.prototype.positionPopupUnderComponent = function(params) {
                var sourceRect = params.eventSource.getBoundingClientRect();
                var parentRect = this.getPopupParent().getBoundingClientRect();
                this.positionPopup({
                    ePopup: params.ePopup,
                    minWidth: params.minWidth,
                    nudgeX: params.nudgeX,
                    nudgeY: params.nudgeY,
                    x: sourceRect.left - parentRect.left,
                    y: sourceRect.top - parentRect.top + sourceRect.height,
                    keepWithinBounds: params.keepWithinBounds
                });
                this.callPostProcessPopup(params.ePopup, params.eventSource, null, params.type, params.column, params.rowNode);
            };
            PopupService.prototype.callPostProcessPopup = function(ePopup, eventSource, mouseEvent, type, column, rowNode) {
                var callback = this.gridOptionsWrapper.getPostProcessPopupFunc();
                if (callback) {
                    var params = {
                        column: column,
                        rowNode: rowNode,
                        ePopup: ePopup,
                        type: type,
                        eventSource: eventSource,
                        mouseEvent: mouseEvent
                    };
                    callback(params);
                }
            };
            PopupService.prototype.positionPopupOverComponent = function(params) {
                var sourceRect = params.eventSource.getBoundingClientRect();
                var parentRect = this.getPopupParent().getBoundingClientRect();
                this.positionPopup({
                    ePopup: params.ePopup,
                    minWidth: params.minWidth,
                    nudgeX: params.nudgeX,
                    nudgeY: params.nudgeY,
                    x: sourceRect.left - parentRect.left,
                    y: sourceRect.top - parentRect.top,
                    keepWithinBounds: params.keepWithinBounds
                });
                this.callPostProcessPopup(params.ePopup, params.eventSource, null, params.type, params.column, params.rowNode);
            };
            PopupService.prototype.positionPopup = function(params) {
                var x = params.x;
                var y = params.y;
                if (params.nudgeX) {
                    x += params.nudgeX;
                }
                if (params.nudgeY) {
                    y += params.nudgeY;
                }
                if (params.keepWithinBounds) {
                    x = this.keepXWithinBounds(params, x);
                    y = this.keepYWithinBounds(params, y);
                }
                params.ePopup.style.left = x + "px";
                params.ePopup.style.top = y + "px";
            };
            PopupService.prototype.keepYWithinBounds = function(params, y) {
                var parentRect = this.getPopupParent().getBoundingClientRect();
                var minHeight;
                if (params.ePopup.clientHeight > 0) {
                    minHeight = params.ePopup.clientHeight;
                } else {
                    minHeight = 200;
                }
                var heightOfParent = parentRect.bottom - parentRect.top;
                var maxY = heightOfParent - minHeight - 5;
                if (y > maxY) {
                    return maxY;
                } else if (y < 0) {
                    return 0;
                } else {
                    return y;
                }
            };
            PopupService.prototype.keepXWithinBounds = function(params, x) {
                var parentRect = this.getPopupParent().getBoundingClientRect();
                var minWidth;
                if (params.minWidth > 0) {
                    minWidth = params.minWidth;
                } else if (params.ePopup.clientWidth > 0) {
                    minWidth = params.ePopup.clientWidth;
                } else {
                    minWidth = 200;
                }
                var widthOfParent = parentRect.right - parentRect.left;
                var maxX = widthOfParent - minWidth - 5;
                if (x > maxX) {
                    return maxX;
                } else if (x < 0) {
                    return 0;
                } else {
                    return x;
                }
            };
            PopupService.prototype.addAsModalPopup = function(eChild, closeOnEsc, closedCallback, click) {
                var _this = this;
                var eBody = this.gridOptionsWrapper.getDocument();
                if (!eBody) {
                    console.warn("ag-grid: could not find the body of the document, document.body is empty");
                    return;
                }
                eChild.style.top = "0px";
                eChild.style.left = "0px";
                var popupAlreadyShown = utils_1.Utils.isVisible(eChild);
                if (popupAlreadyShown) {
                    return;
                }
                var ePopupParent = this.getPopupParent();
                var eWrapper = document.createElement("div");
                utils_1.Utils.addCssClass(eWrapper, this.environment.getTheme());
                eWrapper.appendChild(eChild);
                ePopupParent.appendChild(eWrapper);
                this.activePopupElements.push(eChild);
                var popupHidden = false;
                var hidePopupOnKeyboardEvent = function(event) {
                    var key = event.which || event.keyCode;
                    if (key === constants_1.Constants.KEY_ESCAPE) {
                        hidePopup(null);
                    }
                };
                var hidePopupOnMouseEvent = function(event) {
                    hidePopup(event);
                };
                var hidePopupOnTouchEvent = function(event) {
                    hidePopup(null, event);
                };
                var hidePopup = function(mouseEvent, touchEvent) {
                    if (_this.isEventFromCurrentPopup(mouseEvent, touchEvent, eChild)) {
                        return;
                    }
                    if (_this.isEventSameChainAsOriginalEvent(click, mouseEvent, touchEvent)) {
                        return;
                    }
                    if (popupHidden) {
                        return;
                    }
                    popupHidden = true;
                    ePopupParent.removeChild(eWrapper);
                    utils_1.Utils.removeFromArray(_this.activePopupElements, eChild);
                    eBody.removeEventListener("keydown", hidePopupOnKeyboardEvent);
                    eBody.removeEventListener("click", hidePopupOnMouseEvent);
                    eBody.removeEventListener("touchstart", hidePopupOnTouchEvent);
                    eBody.removeEventListener("contextmenu", hidePopupOnMouseEvent);
                    if (closedCallback) {
                        closedCallback();
                    }
                };
                setTimeout(function() {
                    if (closeOnEsc) {
                        eBody.addEventListener("keydown", hidePopupOnKeyboardEvent);
                    }
                    eBody.addEventListener("click", hidePopupOnMouseEvent);
                    eBody.addEventListener("touchstart", hidePopupOnTouchEvent);
                    eBody.addEventListener("contextmenu", hidePopupOnMouseEvent);
                }, 0);
                return hidePopup;
            };
            PopupService.prototype.isEventFromCurrentPopup = function(mouseEvent, touchEvent, eChild) {
                var event = mouseEvent ? mouseEvent : touchEvent;
                if (event) {
                    var indexOfThisChild = this.activePopupElements.indexOf(eChild);
                    for (var i = indexOfThisChild; i < this.activePopupElements.length; i++) {
                        var element = this.activePopupElements[i];
                        if (utils_1.Utils.isElementInEventPath(element, event)) {
                            return true;
                        }
                    }
                }
                return false;
            };
            PopupService.prototype.isEventSameChainAsOriginalEvent = function(originalClick, mouseEvent, touchEvent) {
                var mouseEventOrTouch;
                if (mouseEvent) {
                    mouseEventOrTouch = mouseEvent;
                } else if (touchEvent) {
                    mouseEventOrTouch = touchEvent.touches[0];
                }
                if (mouseEventOrTouch && originalClick) {
                    var xMatch = Math.abs(originalClick.screenX - mouseEvent.screenX) < 5;
                    var yMatch = Math.abs(originalClick.screenY - mouseEvent.screenY) < 5;
                    if (xMatch && yMatch) {
                        return true;
                    }
                }
                return false;
            };
            __decorate([ context_1.Autowired("gridCore"), __metadata("design:type", gridCore_1.GridCore) ], PopupService.prototype, "gridCore", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], PopupService.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("environment"), __metadata("design:type", environment_1.Environment) ], PopupService.prototype, "environment", void 0);
            PopupService = __decorate([ context_1.Bean("popupService") ], PopupService);
            return PopupService;
        }();
        exports.PopupService = PopupService;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var eventService_1 = __webpack_require__(3);
        var events_1 = __webpack_require__(5);
        var columnController_1 = __webpack_require__(4);
        var columnApi_1 = __webpack_require__(7);
        var gridApi_1 = __webpack_require__(6);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var ScrollVisibleService = function() {
            function ScrollVisibleService() {}
            ScrollVisibleService.prototype.setScrollsVisible = function(params) {
                var atLeastOneDifferent = this.bodyHorizontalScrollShowing !== params.bodyHorizontalScrollShowing || this.leftVerticalScrollShowing !== params.leftVerticalScrollShowing || this.rightVerticalScrollShowing !== params.rightVerticalScrollShowing;
                if (atLeastOneDifferent) {
                    this.bodyHorizontalScrollShowing = params.bodyHorizontalScrollShowing;
                    this.leftVerticalScrollShowing = params.leftVerticalScrollShowing;
                    this.rightVerticalScrollShowing = params.rightVerticalScrollShowing;
                    var event_1 = {
                        type: events_1.Events.EVENT_SCROLL_VISIBILITY_CHANGED,
                        api: this.gridApi,
                        columnApi: this.columnApi
                    };
                    this.eventService.dispatchEvent(event_1);
                }
            };
            ScrollVisibleService.prototype.isBodyHorizontalScrollShowing = function() {
                return this.bodyHorizontalScrollShowing;
            };
            ScrollVisibleService.prototype.isLeftVerticalScrollShowing = function() {
                return this.leftVerticalScrollShowing;
            };
            ScrollVisibleService.prototype.isRightVerticalScrollShowing = function() {
                return this.rightVerticalScrollShowing;
            };
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], ScrollVisibleService.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], ScrollVisibleService.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], ScrollVisibleService.prototype, "columnApi", void 0);
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], ScrollVisibleService.prototype, "gridApi", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], ScrollVisibleService.prototype, "gridOptionsWrapper", void 0);
            ScrollVisibleService = __decorate([ context_1.Bean("scrollVisibleService") ], ScrollVisibleService);
            return ScrollVisibleService;
        }();
        exports.ScrollVisibleService = ScrollVisibleService;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var linkedList_1 = __webpack_require__(123);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var eventKeys_1 = __webpack_require__(25);
        var eventService_1 = __webpack_require__(3);
        var AnimationFrameService = function() {
            function AnimationFrameService() {
                this.p1Tasks = new linkedList_1.LinkedList();
                this.p2Tasks = new linkedList_1.LinkedList();
                this.ticking = false;
            }
            AnimationFrameService.prototype.registerGridComp = function(gridPanel) {
                this.gridPanel = gridPanel;
            };
            AnimationFrameService.prototype.init = function() {
                this.useAnimationFrame = !this.gridOptionsWrapper.isSuppressAnimationFrame();
            };
            AnimationFrameService.prototype.verifyAnimationFrameOn = function(methodName) {
                if (this.useAnimationFrame === false) {
                    console.warn("ag-Grid: AnimationFrameService." + methodName + " called but animation frames are off");
                }
            };
            AnimationFrameService.prototype.addP1Task = function(task) {
                this.verifyAnimationFrameOn("addP1Task");
                this.p1Tasks.add(task);
                this.schedule();
            };
            AnimationFrameService.prototype.addP2Task = function(task) {
                this.verifyAnimationFrameOn("addP2Task");
                this.p2Tasks.add(task);
                this.schedule();
            };
            AnimationFrameService.prototype.executeFrame = function(millis) {
                this.verifyAnimationFrameOn("executeFrame");
                var frameStart = new Date().getTime();
                var duration = new Date().getTime() - frameStart;
                var gridPanelNeedsAFrame = true;
                var noMaxMillis = millis <= 0;
                while (noMaxMillis || duration < millis) {
                    if (gridPanelNeedsAFrame) {
                        gridPanelNeedsAFrame = this.gridPanel.executeFrame();
                    } else if (!this.p1Tasks.isEmpty()) {
                        var task = this.p1Tasks.remove();
                        task();
                    } else if (!this.p2Tasks.isEmpty()) {
                        var task = this.p2Tasks.remove();
                        task();
                    } else {
                        break;
                    }
                    duration = new Date().getTime() - frameStart;
                }
                if (gridPanelNeedsAFrame || !this.p1Tasks.isEmpty() || !this.p2Tasks.isEmpty()) {
                    this.requestFrame();
                } else {
                    this.stopTicking();
                }
            };
            AnimationFrameService.prototype.stopTicking = function() {
                this.ticking = false;
                var event = {
                    type: eventKeys_1.Events.EVENT_ANIMATION_QUEUE_EMPTY,
                    columnApi: this.gridOptionsWrapper.getColumnApi(),
                    api: this.gridOptionsWrapper.getApi()
                };
                this.eventService.dispatchEvent(event);
            };
            AnimationFrameService.prototype.flushAllFrames = function() {
                if (!this.useAnimationFrame) {
                    return;
                }
                this.executeFrame(-1);
            };
            AnimationFrameService.prototype.schedule = function() {
                if (!this.useAnimationFrame) {
                    return;
                }
                if (!this.ticking) {
                    this.ticking = true;
                    this.requestFrame();
                }
            };
            AnimationFrameService.prototype.requestFrame = function() {
                var callback = this.executeFrame.bind(this, 60);
                if (window.requestAnimationFrame) {
                    window.requestAnimationFrame(callback);
                } else if (window.webkitRequestAnimationFrame) {
                    window.webkitRequestAnimationFrame(callback);
                } else {
                    setTimeout(callback, 0);
                }
            };
            AnimationFrameService.prototype.isQueueEmpty = function() {
                return this.ticking;
            };
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], AnimationFrameService.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], AnimationFrameService.prototype, "eventService", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], AnimationFrameService.prototype, "init", null);
            AnimationFrameService = __decorate([ context_1.Bean("animationFrameService") ], AnimationFrameService);
            return AnimationFrameService;
        }();
        exports.AnimationFrameService = AnimationFrameService;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        var __param = this && this.__param || function(paramIndex, decorator) {
            return function(target, key) {
                decorator(target, key, paramIndex);
            };
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var logger_1 = __webpack_require__(12);
        var columnUtils_1 = __webpack_require__(31);
        var columnKeyCreator_1 = __webpack_require__(107);
        var originalColumnGroup_1 = __webpack_require__(32);
        var column_1 = __webpack_require__(10);
        var context_1 = __webpack_require__(0);
        var utils_1 = __webpack_require__(1);
        var defaultColumnTypes_1 = __webpack_require__(134);
        var BalancedColumnTreeBuilder = function() {
            function BalancedColumnTreeBuilder() {}
            BalancedColumnTreeBuilder.prototype.setBeans = function(loggerFactory) {
                this.logger = loggerFactory.create("BalancedColumnTreeBuilder");
            };
            BalancedColumnTreeBuilder.prototype.createForAutoGroups = function(autoGroupCols, gridBalancedTree) {
                var _this = this;
                var autoColBalancedTree = [];
                autoGroupCols.forEach(function(col) {
                    var fakeTreeItem = _this.createAutoGroupTreeItem(gridBalancedTree, col);
                    autoColBalancedTree.push(fakeTreeItem);
                });
                return autoColBalancedTree;
            };
            BalancedColumnTreeBuilder.prototype.createAutoGroupTreeItem = function(balancedColumnTree, column) {
                var dept = this.findDept(balancedColumnTree);
                var nextChild = column;
                for (var i = dept - 1; i >= 0; i--) {
                    var autoGroup = new originalColumnGroup_1.OriginalColumnGroup(null, "FAKE_PATH_" + column.getId() + "}_" + i, true, i);
                    this.context.wireBean(autoGroup);
                    autoGroup.setChildren([ nextChild ]);
                    nextChild = autoGroup;
                }
                return nextChild;
            };
            BalancedColumnTreeBuilder.prototype.findDept = function(balancedColumnTree) {
                var dept = 0;
                var pointer = balancedColumnTree;
                while (pointer && pointer[0] && pointer[0] instanceof originalColumnGroup_1.OriginalColumnGroup) {
                    dept++;
                    pointer = pointer[0].getChildren();
                }
                return dept;
            };
            BalancedColumnTreeBuilder.prototype.createBalancedColumnGroups = function(abstractColDefs, primaryColumns) {
                var columnKeyCreator = new columnKeyCreator_1.ColumnKeyCreator();
                var unbalancedTree = this.recursivelyCreateColumns(abstractColDefs, 0, columnKeyCreator, primaryColumns);
                var treeDept = this.findMaxDept(unbalancedTree, 0);
                this.logger.log("Number of levels for grouped columns is " + treeDept);
                var balancedTree = this.balanceColumnTree(unbalancedTree, 0, treeDept, columnKeyCreator);
                this.columnUtils.depthFirstOriginalTreeSearch(balancedTree, function(child) {
                    if (child instanceof originalColumnGroup_1.OriginalColumnGroup) {
                        child.setupExpandable();
                    }
                });
                return {
                    balancedTree: balancedTree,
                    treeDept: treeDept
                };
            };
            BalancedColumnTreeBuilder.prototype.balanceColumnTree = function(unbalancedTree, currentDept, columnDept, columnKeyCreator) {
                var _this = this;
                var result = [];
                unbalancedTree.forEach(function(child) {
                    if (child instanceof originalColumnGroup_1.OriginalColumnGroup) {
                        var originalGroup = child;
                        var newChildren = _this.balanceColumnTree(originalGroup.getChildren(), currentDept + 1, columnDept, columnKeyCreator);
                        originalGroup.setChildren(newChildren);
                        result.push(originalGroup);
                    } else {
                        var newChild = child;
                        for (var i = columnDept - 1; i >= currentDept; i--) {
                            var newColId = columnKeyCreator.getUniqueKey(null, null);
                            var colGroupDefMerged = _this.createMergedColGroupDef(null);
                            var paddedGroup = new originalColumnGroup_1.OriginalColumnGroup(colGroupDefMerged, newColId, true, currentDept);
                            _this.context.wireBean(paddedGroup);
                            paddedGroup.setChildren([ newChild ]);
                            newChild = paddedGroup;
                        }
                        result.push(newChild);
                    }
                });
                return result;
            };
            BalancedColumnTreeBuilder.prototype.findMaxDept = function(treeChildren, dept) {
                var maxDeptThisLevel = dept;
                for (var i = 0; i < treeChildren.length; i++) {
                    var abstractColumn = treeChildren[i];
                    if (abstractColumn instanceof originalColumnGroup_1.OriginalColumnGroup) {
                        var originalGroup = abstractColumn;
                        var newDept = this.findMaxDept(originalGroup.getChildren(), dept + 1);
                        if (maxDeptThisLevel < newDept) {
                            maxDeptThisLevel = newDept;
                        }
                    }
                }
                return maxDeptThisLevel;
            };
            BalancedColumnTreeBuilder.prototype.recursivelyCreateColumns = function(abstractColDefs, level, columnKeyCreator, primaryColumns) {
                var _this = this;
                var result = [];
                if (!abstractColDefs) {
                    return result;
                }
                abstractColDefs.forEach(function(abstractColDef) {
                    var newGroupOrColumn;
                    if (_this.isColumnGroup(abstractColDef)) {
                        newGroupOrColumn = _this.createColumnGroup(columnKeyCreator, primaryColumns, abstractColDef, level);
                    } else {
                        newGroupOrColumn = _this.createColumn(columnKeyCreator, primaryColumns, abstractColDef);
                    }
                    result.push(newGroupOrColumn);
                });
                return result;
            };
            BalancedColumnTreeBuilder.prototype.createColumnGroup = function(columnKeyCreator, primaryColumns, colGroupDef, level) {
                var colGroupDefMerged = this.createMergedColGroupDef(colGroupDef);
                var groupId = columnKeyCreator.getUniqueKey(colGroupDefMerged.groupId, null);
                var originalGroup = new originalColumnGroup_1.OriginalColumnGroup(colGroupDefMerged, groupId, false, level);
                this.context.wireBean(originalGroup);
                var children = this.recursivelyCreateColumns(colGroupDefMerged.children, level + 1, columnKeyCreator, primaryColumns);
                originalGroup.setChildren(children);
                return originalGroup;
            };
            BalancedColumnTreeBuilder.prototype.createMergedColGroupDef = function(colGroupDef) {
                var colGroupDefMerged = {};
                utils_1.Utils.assign(colGroupDefMerged, this.gridOptionsWrapper.getDefaultColGroupDef());
                utils_1.Utils.assign(colGroupDefMerged, colGroupDef);
                this.checkForDeprecatedItems(colGroupDefMerged);
                return colGroupDefMerged;
            };
            BalancedColumnTreeBuilder.prototype.createColumn = function(columnKeyCreator, primaryColumns, colDef) {
                var colDefMerged = this.mergeColDefs(colDef);
                this.checkForDeprecatedItems(colDefMerged);
                var colId = columnKeyCreator.getUniqueKey(colDefMerged.colId, colDefMerged.field);
                var column = new column_1.Column(colDefMerged, colId, primaryColumns);
                this.context.wireBean(column);
                return column;
            };
            BalancedColumnTreeBuilder.prototype.mergeColDefs = function(colDef) {
                var colDefMerged = {};
                utils_1.Utils.assign(colDefMerged, this.gridOptionsWrapper.getDefaultColDef());
                if (colDef.type) {
                    this.assignColumnTypes(colDef, colDefMerged);
                }
                utils_1.Utils.assign(colDefMerged, colDef);
                return colDefMerged;
            };
            BalancedColumnTreeBuilder.prototype.assignColumnTypes = function(colDef, colDefMerged) {
                var typeKeys;
                if (colDef.type instanceof Array) {
                    var invalidArray = colDef.type.some(function(a) {
                        return typeof a !== "string";
                    });
                    if (invalidArray) {
                        console.warn("ag-grid: if colDef.type is supplied an array it should be of type 'string[]'");
                    } else {
                        typeKeys = colDef.type;
                    }
                } else if (typeof colDef.type === "string") {
                    typeKeys = colDef.type.split(",");
                } else {
                    console.warn("ag-grid: colDef.type should be of type 'string' | 'string[]'");
                    return;
                }
                var allColumnTypes = utils_1.Utils.assign({}, this.gridOptionsWrapper.getColumnTypes(), defaultColumnTypes_1.DefaultColumnTypes);
                typeKeys.forEach(function(t) {
                    var typeColDef = allColumnTypes[t.trim()];
                    if (typeColDef) {
                        utils_1.Utils.assign(colDefMerged, typeColDef);
                    } else {
                        console.warn("ag-grid: colDef.type '" + t + "' does not correspond to defined gridOptions.columnTypes");
                    }
                });
            };
            BalancedColumnTreeBuilder.prototype.checkForDeprecatedItems = function(colDef) {
                if (colDef) {
                    var colDefNoType = colDef;
                    if (colDefNoType.group !== undefined) {
                        console.warn("ag-grid: colDef.group is invalid, please check documentation on how to do grouping as it changed in version 3");
                    }
                    if (colDefNoType.headerGroup !== undefined) {
                        console.warn("ag-grid: colDef.headerGroup is invalid, please check documentation on how to do grouping as it changed in version 3");
                    }
                    if (colDefNoType.headerGroupShow !== undefined) {
                        console.warn("ag-grid: colDef.headerGroupShow is invalid, should be columnGroupShow, please check documentation on how to do grouping as it changed in version 3");
                    }
                    if (colDefNoType.suppressRowGroup !== undefined) {
                        console.warn("ag-grid: colDef.suppressRowGroup is deprecated, please use colDef.type instead");
                    }
                    if (colDefNoType.suppressAggregation !== undefined) {
                        console.warn("ag-grid: colDef.suppressAggregation is deprecated, please use colDef.type instead");
                    }
                    if (colDefNoType.suppressRowGroup || colDefNoType.suppressAggregation) {
                        console.warn("ag-grid: colDef.suppressAggregation and colDef.suppressRowGroup are deprecated, use allowRowGroup, allowPivot and allowValue instead");
                    }
                    if (colDefNoType.displayName) {
                        console.warn("ag-grid: Found displayName " + colDefNoType.displayName + ", please use headerName instead, displayName is deprecated.");
                        colDefNoType.headerName = colDefNoType.displayName;
                    }
                }
            };
            BalancedColumnTreeBuilder.prototype.isColumnGroup = function(abstractColDef) {
                return abstractColDef.children !== undefined;
            };
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], BalancedColumnTreeBuilder.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("columnUtils"), __metadata("design:type", columnUtils_1.ColumnUtils) ], BalancedColumnTreeBuilder.prototype, "columnUtils", void 0);
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], BalancedColumnTreeBuilder.prototype, "context", void 0);
            __decorate([ __param(0, context_1.Qualifier("loggerFactory")), __metadata("design:type", Function), __metadata("design:paramtypes", [ logger_1.LoggerFactory ]), __metadata("design:returntype", void 0) ], BalancedColumnTreeBuilder.prototype, "setBeans", null);
            BalancedColumnTreeBuilder = __decorate([ context_1.Bean("balancedColumnTreeBuilder") ], BalancedColumnTreeBuilder);
            return BalancedColumnTreeBuilder;
        }();
        exports.BalancedColumnTreeBuilder = BalancedColumnTreeBuilder;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var rowRenderer_1 = __webpack_require__(20);
        var context_1 = __webpack_require__(0);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var headerWrapperComp_1 = __webpack_require__(100);
        var AutoWidthCalculator = function() {
            function AutoWidthCalculator() {}
            AutoWidthCalculator.prototype.registerGridComp = function(gridPanel) {
                this.gridPanel = gridPanel;
            };
            AutoWidthCalculator.prototype.registerHeaderRootComp = function(headerRootComp) {
                this.headerRootComp = headerRootComp;
            };
            AutoWidthCalculator.prototype.getPreferredWidthForColumn = function(column) {
                var eHeaderCell = this.getHeaderCellForColumn(column);
                if (!eHeaderCell) {
                    return -1;
                }
                var eDummyContainer = document.createElement("span");
                eDummyContainer.style.position = "fixed";
                var eBodyContainer = this.gridPanel.getBodyContainer();
                eBodyContainer.appendChild(eDummyContainer);
                this.putRowCellsIntoDummyContainer(column, eDummyContainer);
                this.cloneItemIntoDummy(eHeaderCell, eDummyContainer);
                var dummyContainerWidth = eDummyContainer.offsetWidth;
                eBodyContainer.removeChild(eDummyContainer);
                var autoSizePadding = this.gridOptionsWrapper.getAutoSizePadding();
                return dummyContainerWidth + autoSizePadding;
            };
            AutoWidthCalculator.prototype.getHeaderCellForColumn = function(column) {
                var comp = null;
                this.headerRootComp.forEachHeaderElement(function(headerElement) {
                    if (headerElement instanceof headerWrapperComp_1.HeaderWrapperComp) {
                        var headerWrapperComp = headerElement;
                        if (headerWrapperComp.getColumn() === column) {
                            comp = headerWrapperComp;
                        }
                    }
                });
                return comp ? comp.getGui() : null;
            };
            AutoWidthCalculator.prototype.putRowCellsIntoDummyContainer = function(column, eDummyContainer) {
                var _this = this;
                var eCells = this.rowRenderer.getAllCellsForColumn(column);
                eCells.forEach(function(eCell) {
                    return _this.cloneItemIntoDummy(eCell, eDummyContainer);
                });
            };
            AutoWidthCalculator.prototype.cloneItemIntoDummy = function(eCell, eDummyContainer) {
                var eCellClone = eCell.cloneNode(true);
                eCellClone.style.width = "";
                eCellClone.style.position = "static";
                eCellClone.style.left = "";
                var eCloneParent = document.createElement("div");
                eCloneParent.style.display = "table-row";
                eCloneParent.appendChild(eCellClone);
                eDummyContainer.appendChild(eCloneParent);
            };
            __decorate([ context_1.Autowired("rowRenderer"), __metadata("design:type", rowRenderer_1.RowRenderer) ], AutoWidthCalculator.prototype, "rowRenderer", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], AutoWidthCalculator.prototype, "gridOptionsWrapper", void 0);
            AutoWidthCalculator = __decorate([ context_1.Bean("autoWidthCalculator") ], AutoWidthCalculator);
            return AutoWidthCalculator;
        }();
        exports.AutoWidthCalculator = AutoWidthCalculator;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var logger_1 = __webpack_require__(12);
        var utils_1 = __webpack_require__(1);
        var eventService_1 = __webpack_require__(3);
        var events_1 = __webpack_require__(5);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var columnApi_1 = __webpack_require__(7);
        var gridApi_1 = __webpack_require__(6);
        var DragService = function() {
            function DragService() {
                this.onMouseUpListener = this.onMouseUp.bind(this);
                this.onMouseMoveListener = this.onMouseMove.bind(this);
                this.onTouchEndListener = this.onTouchUp.bind(this);
                this.onTouchMoveListener = this.onTouchMove.bind(this);
                this.dragEndFunctions = [];
                this.dragSources = [];
            }
            DragService.prototype.init = function() {
                this.logger = this.loggerFactory.create("DragService");
            };
            DragService.prototype.destroy = function() {
                this.dragSources.forEach(this.removeListener.bind(this));
                this.dragSources.length = 0;
            };
            DragService.prototype.removeListener = function(dragSourceAndListener) {
                var element = dragSourceAndListener.dragSource.eElement;
                var mouseDownListener = dragSourceAndListener.mouseDownListener;
                element.removeEventListener("mousedown", mouseDownListener);
                if (dragSourceAndListener.touchEnabled) {
                    var touchStartListener = dragSourceAndListener.touchStartListener;
                    element.removeEventListener("touchstart", touchStartListener, {
                        passive: true
                    });
                }
            };
            DragService.prototype.removeDragSource = function(params) {
                var dragSourceAndListener = utils_1.Utils.find(this.dragSources, function(item) {
                    return item.dragSource === params;
                });
                if (!dragSourceAndListener) {
                    return;
                }
                this.removeListener(dragSourceAndListener);
                utils_1.Utils.removeFromArray(this.dragSources, dragSourceAndListener);
            };
            DragService.prototype.setNoSelectToBody = function(noSelect) {
                var usrDocument = this.gridOptionsWrapper.getDocument();
                var eBody = usrDocument.querySelector("body");
                if (utils_1.Utils.exists(eBody)) {
                    utils_1.Utils.addOrRemoveCssClass(eBody, "ag-body-no-select", noSelect);
                }
            };
            DragService.prototype.addDragSource = function(params, includeTouch) {
                if (includeTouch === void 0) {
                    includeTouch = false;
                }
                var mouseListener = this.onMouseDown.bind(this, params);
                params.eElement.addEventListener("mousedown", mouseListener);
                var touchListener = null;
                var suppressTouch = this.gridOptionsWrapper.isSuppressTouch();
                var reallyIncludeTouch = includeTouch && !suppressTouch;
                if (reallyIncludeTouch) {
                    touchListener = this.onTouchStart.bind(this, params);
                    params.eElement.addEventListener("touchstart", touchListener, {
                        passive: false
                    });
                }
                this.dragSources.push({
                    dragSource: params,
                    mouseDownListener: mouseListener,
                    touchStartListener: touchListener,
                    touchEnabled: includeTouch
                });
            };
            DragService.prototype.onTouchStart = function(params, touchEvent) {
                var _this = this;
                this.currentDragParams = params;
                this.dragging = false;
                var touch = touchEvent.touches[0];
                this.touchLastTime = touch;
                this.touchStart = touch;
                touchEvent.preventDefault();
                params.eElement.addEventListener("touchmove", this.onTouchMoveListener, {
                    passive: true
                });
                params.eElement.addEventListener("touchend", this.onTouchEndListener, {
                    passive: true
                });
                params.eElement.addEventListener("touchcancel", this.onTouchEndListener, {
                    passive: true
                });
                this.dragEndFunctions.push(function() {
                    params.eElement.removeEventListener("touchmove", _this.onTouchMoveListener, {
                        passive: true
                    });
                    params.eElement.removeEventListener("touchend", _this.onTouchEndListener, {
                        passive: true
                    });
                    params.eElement.removeEventListener("touchcancel", _this.onTouchEndListener, {
                        passive: true
                    });
                });
                if (params.dragStartPixels === 0) {
                    this.onCommonMove(touch, this.touchStart);
                }
            };
            DragService.prototype.onMouseDown = function(params, mouseEvent) {
                var _this = this;
                if (params.skipMouseEvent) {
                    if (params.skipMouseEvent(mouseEvent)) {
                        return;
                    }
                }
                if (mouseEvent._alreadyProcessedByDragService) {
                    return;
                }
                mouseEvent._alreadyProcessedByDragService = true;
                if (mouseEvent.button !== 0) {
                    return;
                }
                this.currentDragParams = params;
                this.dragging = false;
                this.mouseEventLastTime = mouseEvent;
                this.mouseStartEvent = mouseEvent;
                var usrDocument = this.gridOptionsWrapper.getDocument();
                usrDocument.addEventListener("mousemove", this.onMouseMoveListener);
                usrDocument.addEventListener("mouseup", this.onMouseUpListener);
                this.dragEndFunctions.push(function() {
                    usrDocument.removeEventListener("mousemove", _this.onMouseMoveListener);
                    usrDocument.removeEventListener("mouseup", _this.onMouseUpListener);
                });
                if (params.dragStartPixels === 0) {
                    this.onMouseMove(mouseEvent);
                }
            };
            DragService.prototype.isEventNearStartEvent = function(currentEvent, startEvent) {
                var requiredPixelDiff = utils_1.Utils.exists(this.currentDragParams.dragStartPixels) ? this.currentDragParams.dragStartPixels : 4;
                return utils_1.Utils.areEventsNear(currentEvent, startEvent, requiredPixelDiff);
            };
            DragService.prototype.getFirstActiveTouch = function(touchList) {
                for (var i = 0; i < touchList.length; i++) {
                    var matches = touchList[i].identifier === this.touchStart.identifier;
                    if (matches) {
                        return touchList[i];
                    }
                }
                return null;
            };
            DragService.prototype.onCommonMove = function(currentEvent, startEvent) {
                if (!this.dragging) {
                    var toEarlyToDrag = !this.dragging && this.isEventNearStartEvent(currentEvent, startEvent);
                    if (toEarlyToDrag) {
                        return;
                    } else {
                        this.dragging = true;
                        var event_1 = {
                            type: events_1.Events.EVENT_DRAG_STARTED,
                            api: this.gridApi,
                            columnApi: this.columnApi
                        };
                        this.eventService.dispatchEvent(event_1);
                        this.currentDragParams.onDragStart(startEvent);
                        this.setNoSelectToBody(true);
                    }
                }
                this.currentDragParams.onDragging(currentEvent);
            };
            DragService.prototype.onTouchMove = function(touchEvent) {
                var touch = this.getFirstActiveTouch(touchEvent.touches);
                if (!touch) {
                    return;
                }
                this.onCommonMove(touch, this.touchStart);
            };
            DragService.prototype.onMouseMove = function(mouseEvent) {
                this.onCommonMove(mouseEvent, this.mouseStartEvent);
            };
            DragService.prototype.onTouchUp = function(touchEvent) {
                var touch = this.getFirstActiveTouch(touchEvent.changedTouches);
                if (!touch) {
                    touch = this.touchLastTime;
                }
                this.onUpCommon(touch);
            };
            DragService.prototype.onMouseUp = function(mouseEvent) {
                this.onUpCommon(mouseEvent);
            };
            DragService.prototype.onUpCommon = function(eventOrTouch) {
                if (this.dragging) {
                    this.dragging = false;
                    this.currentDragParams.onDragStop(eventOrTouch);
                    var event_2 = {
                        type: events_1.Events.EVENT_DRAG_STOPPED,
                        api: this.gridApi,
                        columnApi: this.columnApi
                    };
                    this.eventService.dispatchEvent(event_2);
                }
                this.setNoSelectToBody(false);
                this.mouseStartEvent = null;
                this.mouseEventLastTime = null;
                this.touchStart = null;
                this.touchLastTime = null;
                this.currentDragParams = null;
                this.dragEndFunctions.forEach(function(func) {
                    return func();
                });
                this.dragEndFunctions.length = 0;
            };
            __decorate([ context_1.Autowired("loggerFactory"), __metadata("design:type", logger_1.LoggerFactory) ], DragService.prototype, "loggerFactory", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], DragService.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], DragService.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], DragService.prototype, "columnApi", void 0);
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], DragService.prototype, "gridApi", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], DragService.prototype, "init", null);
            __decorate([ context_1.PreDestroy, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], DragService.prototype, "destroy", null);
            DragService = __decorate([ context_1.Bean("dragService") ], DragService);
            return DragService;
        }();
        exports.DragService = DragService;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var themeNames = [ "fresh", "dark", "blue", "bootstrap", "material", "balham-dark", "balham" ];
        var themes = themeNames.concat(themeNames.map(function(name) {
            return "theme-" + name;
        }));
        var themeClass = new RegExp("ag-(" + themes.join("|") + ")");
        var matGridSize = 8;
        var freshGridSize = 4;
        var balhamGridSize = 4;
        var HARD_CODED_SIZES = {
            "ag-theme-material": {
                headerHeight: matGridSize * 7,
                virtualItemHeight: matGridSize * 5,
                rowHeight: matGridSize * 6
            },
            "ag-theme-classic": {
                headerHeight: 25,
                virtualItemHeight: freshGridSize * 5,
                rowHeight: 25
            },
            "ag-theme-balham": {
                headerHeight: balhamGridSize * 8,
                virtualItemHeight: balhamGridSize * 7,
                rowHeight: balhamGridSize * 7
            }
        };
        var Environment = function() {
            function Environment() {
                this.sassVariables = {};
            }
            Environment.prototype.loadSassVariables = function() {};
            Environment.prototype.getSassVariable = function(theme, key) {
                if (theme == "ag-theme-material") {
                    return HARD_CODED_SIZES["ag-theme-material"][key];
                } else if (theme == "ag-theme-balham" || theme == "ag-theme-balham-dark") {
                    return HARD_CODED_SIZES["ag-theme-balham"][key];
                }
                return HARD_CODED_SIZES["ag-theme-classic"][key];
            };
            Environment.prototype.getTheme = function() {
                var themeMatch;
                var element = this.eGridDiv;
                while (element != document.documentElement && themeMatch == null) {
                    themeMatch = element.className.match(themeClass);
                    element = element.parentElement;
                    if (element == null) {
                        break;
                    }
                }
                if (themeMatch) {
                    return themeMatch[0];
                } else {
                    return "ag-fresh";
                }
            };
            __decorate([ context_1.Autowired("eGridDiv"), __metadata("design:type", HTMLElement) ], Environment.prototype, "eGridDiv", void 0);
            Environment = __decorate([ context_1.Bean("environment") ], Environment);
            return Environment;
        }();
        exports.Environment = Environment;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var columnApi_1 = __webpack_require__(7);
        var columnController_1 = __webpack_require__(4);
        var rowRenderer_1 = __webpack_require__(20);
        var filterManager_1 = __webpack_require__(18);
        var eventService_1 = __webpack_require__(3);
        var gridPanel_1 = __webpack_require__(78);
        var logger_1 = __webpack_require__(12);
        var popupService_1 = __webpack_require__(35);
        var utils_1 = __webpack_require__(1);
        var context_1 = __webpack_require__(0);
        var focusedCellController_1 = __webpack_require__(22);
        var component_1 = __webpack_require__(8);
        var gridApi_1 = __webpack_require__(6);
        var componentAnnotations_1 = __webpack_require__(11);
        var GridCore = function(_super) {
            __extends(GridCore, _super);
            function GridCore() {
                return _super.call(this) || this;
            }
            GridCore_1 = GridCore;
            GridCore.prototype.init = function() {
                var _this = this;
                this.logger = this.loggerFactory.create("GridCore");
                var template = this.enterprise ? GridCore_1.TEMPLATE_ENTERPRISE : GridCore_1.TEMPLATE_NORMAL;
                this.setTemplate(template);
                this.instantiate(this.context);
                if (this.enterprise) {
                    this.toolPanelComp.registerGridComp(this.gridPanel);
                    this.statusBar.registerGridPanel(this.gridPanel);
                }
                this.gridOptionsWrapper.addEventListener(gridOptionsWrapper_1.GridOptionsWrapper.PROP_GRID_AUTO_HEIGHT, this.addLayoutClass.bind(this));
                this.addLayoutClass();
                this.showToolPanel(this.gridOptionsWrapper.isShowToolPanel());
                this.eGridDiv.appendChild(this.getGui());
                this.addDestroyFunc(function() {
                    _this.eGridDiv.removeChild(_this.getGui());
                });
                if (this.$scope) {
                    var quickFilterUnregisterFn = this.$scope.$watch(this.quickFilterOnScope, function(newFilter) {
                        return _this.filterManager.setQuickFilter(newFilter);
                    });
                    this.addDestroyFunc(quickFilterUnregisterFn);
                }
                this.addRtlSupport();
                this.finished = false;
                this.addDestroyFunc(function() {
                    return _this.finished = true;
                });
                this.logger.log("ready");
            };
            GridCore.prototype.addLayoutClass = function() {
                var autoHeight = this.gridOptionsWrapper.isGridAutoHeight();
                this.addOrRemoveCssClass("ag-layout-auto-height", autoHeight);
                this.addOrRemoveCssClass("ag-layout-normal", !autoHeight);
                this.addOrRemoveCssClass("ag-scrolls", !autoHeight);
            };
            GridCore.prototype.getPreferredWidth = function() {
                var widthForCols = this.columnController.getBodyContainerWidth() + this.columnController.getPinnedLeftContainerWidth() + this.columnController.getPinnedRightContainerWidth();
                var widthForToolpanel = this.toolPanelComp ? this.toolPanelComp.getPreferredWidth() : 0;
                return widthForCols + widthForToolpanel;
            };
            GridCore.prototype.addRtlSupport = function() {
                var cssClass = this.gridOptionsWrapper.isEnableRtl() ? "ag-rtl" : "ag-ltr";
                utils_1.Utils.addCssClass(this.getGui(), cssClass);
            };
            GridCore.prototype.getRootGui = function() {
                return this.getGui();
            };
            GridCore.prototype.showToolPanel = function(show) {
                if (!this.toolPanelComp) {
                    if (show) {
                        console.warn("ag-Grid: toolPanel is only available in ag-Grid Enterprise");
                    }
                    return;
                }
                this.toolPanelComp.showToolPanel(show);
            };
            GridCore.prototype.isToolPanelShowing = function() {
                return this.toolPanelComp.isToolPanelShowing();
            };
            GridCore.prototype.destroy = function() {
                _super.prototype.destroy.call(this);
                this.logger.log("Grid DOM removed");
            };
            GridCore.prototype.ensureNodeVisible = function(comparator, position) {
                if (position === void 0) {
                    position = "top";
                }
                if (this.doingVirtualPaging) {
                    throw "Cannot use ensureNodeVisible when doing virtual paging, as we cannot check rows that are not in memory";
                }
                var rowCount = this.rowModel.getPageLastRow() + 1;
                var comparatorIsAFunction = typeof comparator === "function";
                var indexToSelect = -1;
                for (var i = 0; i < rowCount; i++) {
                    var node = this.rowModel.getRow(i);
                    if (comparatorIsAFunction) {
                        if (comparator(node)) {
                            indexToSelect = i;
                            break;
                        }
                    } else {
                        if (comparator === node || comparator === node.data) {
                            indexToSelect = i;
                            break;
                        }
                    }
                }
                if (indexToSelect >= 0) {
                    this.gridPanel.ensureIndexVisible(indexToSelect, position);
                }
            };
            GridCore.TEMPLATE_NORMAL = '<div class="ag-root-wrapper">\n            <div class="ag-root-wrapper-body">\n                <ag-grid-comp ref="gridPanel"></ag-grid-comp>\n            </div>\n            <ag-pagination></ag-pagination>\n        </div>';
            GridCore.TEMPLATE_ENTERPRISE = '<div class="ag-root-wrapper">\n            <ag-header-column-drop></ag-header-column-drop>\n            <div class="ag-root-wrapper-body">\n                <ag-grid-comp ref="gridPanel"></ag-grid-comp>\n                <ag-tool-panel ref="toolPanel"></ag-tool-panel>\n            </div>\n            <ag-status-bar ref="statusBar"></ag-status-bar>\n            <ag-pagination></ag-pagination>\n        </div>';
            __decorate([ context_1.Autowired("enterprise"), __metadata("design:type", Boolean) ], GridCore.prototype, "enterprise", void 0);
            __decorate([ context_1.Autowired("gridOptions"), __metadata("design:type", Object) ], GridCore.prototype, "gridOptions", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], GridCore.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("rowModel"), __metadata("design:type", Object) ], GridCore.prototype, "rowModel", void 0);
            __decorate([ context_1.Autowired("frameworkFactory"), __metadata("design:type", Object) ], GridCore.prototype, "frameworkFactory", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], GridCore.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("rowRenderer"), __metadata("design:type", rowRenderer_1.RowRenderer) ], GridCore.prototype, "rowRenderer", void 0);
            __decorate([ context_1.Autowired("filterManager"), __metadata("design:type", filterManager_1.FilterManager) ], GridCore.prototype, "filterManager", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], GridCore.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("eGridDiv"), __metadata("design:type", HTMLElement) ], GridCore.prototype, "eGridDiv", void 0);
            __decorate([ context_1.Autowired("$scope"), __metadata("design:type", Object) ], GridCore.prototype, "$scope", void 0);
            __decorate([ context_1.Autowired("quickFilterOnScope"), __metadata("design:type", String) ], GridCore.prototype, "quickFilterOnScope", void 0);
            __decorate([ context_1.Autowired("popupService"), __metadata("design:type", popupService_1.PopupService) ], GridCore.prototype, "popupService", void 0);
            __decorate([ context_1.Autowired("focusedCellController"), __metadata("design:type", focusedCellController_1.FocusedCellController) ], GridCore.prototype, "focusedCellController", void 0);
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], GridCore.prototype, "context", void 0);
            __decorate([ context_1.Autowired("loggerFactory"), __metadata("design:type", logger_1.LoggerFactory) ], GridCore.prototype, "loggerFactory", void 0);
            __decorate([ context_1.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], GridCore.prototype, "columnApi", void 0);
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], GridCore.prototype, "gridApi", void 0);
            __decorate([ context_1.Optional("rowGroupCompFactory"), __metadata("design:type", Object) ], GridCore.prototype, "rowGroupCompFactory", void 0);
            __decorate([ context_1.Optional("pivotCompFactory"), __metadata("design:type", Object) ], GridCore.prototype, "pivotCompFactory", void 0);
            __decorate([ componentAnnotations_1.RefSelector("statusBar"), __metadata("design:type", Object) ], GridCore.prototype, "statusBar", void 0);
            __decorate([ componentAnnotations_1.RefSelector("gridPanel"), __metadata("design:type", gridPanel_1.GridPanel) ], GridCore.prototype, "gridPanel", void 0);
            __decorate([ componentAnnotations_1.RefSelector("toolPanel"), __metadata("design:type", Object) ], GridCore.prototype, "toolPanelComp", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], GridCore.prototype, "init", null);
            __decorate([ context_1.PreDestroy, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], GridCore.prototype, "destroy", null);
            GridCore = GridCore_1 = __decorate([ context_1.Bean("gridCore"), __metadata("design:paramtypes", []) ], GridCore);
            return GridCore;
            var GridCore_1;
        }(component_1.Component);
        exports.GridCore = GridCore;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var expressionService_1 = __webpack_require__(19);
        var ValueFormatterService = function() {
            function ValueFormatterService() {}
            ValueFormatterService.prototype.formatValue = function(column, rowNode, $scope, value) {
                var formatter;
                var colDef = column.getColDef();
                if (rowNode && rowNode.rowPinned) {
                    formatter = colDef.pinnedRowValueFormatter ? colDef.pinnedRowValueFormatter : colDef.valueFormatter;
                } else {
                    formatter = colDef.valueFormatter;
                }
                var result = null;
                if (formatter) {
                    var params = {
                        value: value,
                        node: rowNode,
                        data: rowNode ? rowNode.data : null,
                        colDef: column.getColDef(),
                        column: column,
                        api: this.gridOptionsWrapper.getApi(),
                        columnApi: this.gridOptionsWrapper.getColumnApi(),
                        context: this.gridOptionsWrapper.getContext()
                    };
                    params.$scope = $scope;
                    result = this.expressionService.evaluate(formatter, params);
                } else if (colDef.refData) {
                    return colDef.refData[value];
                }
                if ((result === null || result === undefined) && Array.isArray(value)) {
                    result = value.join(", ");
                }
                return result;
            };
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], ValueFormatterService.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("expressionService"), __metadata("design:type", expressionService_1.ExpressionService) ], ValueFormatterService.prototype, "expressionService", void 0);
            ValueFormatterService = __decorate([ context_1.Bean("valueFormatterService") ], ValueFormatterService);
            return ValueFormatterService;
        }();
        exports.ValueFormatterService = ValueFormatterService;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var context_2 = __webpack_require__(0);
        var utils_1 = __webpack_require__(1);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var cellComp_1 = __webpack_require__(34);
        var MouseEventService = function() {
            function MouseEventService() {
                this.gridInstanceId = MouseEventService_1.gridInstanceSequence.next();
            }
            MouseEventService_1 = MouseEventService;
            MouseEventService.prototype.init = function() {
                this.stampDomElementWithGridInstance();
            };
            MouseEventService.prototype.stampDomElementWithGridInstance = function() {
                this.eGridDiv[MouseEventService_1.GRID_DOM_KEY] = this.gridInstanceId;
            };
            MouseEventService.prototype.getRenderedCellForEvent = function(event) {
                var sourceElement = utils_1.Utils.getTarget(event);
                while (sourceElement) {
                    var renderedCell = this.gridOptionsWrapper.getDomData(sourceElement, cellComp_1.CellComp.DOM_DATA_KEY_CELL_COMP);
                    if (renderedCell) {
                        return renderedCell;
                    }
                    sourceElement = sourceElement.parentElement;
                }
                return null;
            };
            MouseEventService.prototype.isEventFromThisGrid = function(event) {
                var path = utils_1.Utils.getEventPath(event);
                for (var i = 0; i < path.length; i++) {
                    var element = path[i];
                    var instanceId = element[MouseEventService_1.GRID_DOM_KEY];
                    if (utils_1.Utils.exists(instanceId)) {
                        var eventFromThisGrid = instanceId === this.gridInstanceId;
                        return eventFromThisGrid;
                    }
                }
                return false;
            };
            MouseEventService.prototype.getGridCellForEvent = function(event) {
                var cellComp = this.getRenderedCellForEvent(event);
                return cellComp ? cellComp.getGridCell() : null;
            };
            MouseEventService.gridInstanceSequence = new utils_1.NumberSequence();
            MouseEventService.GRID_DOM_KEY = "__ag_grid_instance";
            __decorate([ context_2.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], MouseEventService.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_2.Autowired("eGridDiv"), __metadata("design:type", HTMLElement) ], MouseEventService.prototype, "eGridDiv", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], MouseEventService.prototype, "init", null);
            MouseEventService = MouseEventService_1 = __decorate([ context_1.Bean("mouseEventService") ], MouseEventService);
            return MouseEventService;
            var MouseEventService_1;
        }();
        exports.MouseEventService = MouseEventService;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var eventService_1 = __webpack_require__(3);
        var context_1 = __webpack_require__(0);
        var events_1 = __webpack_require__(5);
        var beanStub_1 = __webpack_require__(13);
        var columnApi_1 = __webpack_require__(7);
        var gridApi_1 = __webpack_require__(6);
        var ColumnHoverService = function(_super) {
            __extends(ColumnHoverService, _super);
            function ColumnHoverService() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            ColumnHoverService.prototype.setMouseOver = function(columns) {
                this.selectedColumns = columns;
                var event = {
                    type: events_1.Events.EVENT_COLUMN_HOVER_CHANGED,
                    api: this.gridApi,
                    columnApi: this.columnApi
                };
                this.eventService.dispatchEvent(event);
            };
            ColumnHoverService.prototype.clearMouseOver = function() {
                this.selectedColumns = null;
                var event = {
                    type: events_1.Events.EVENT_COLUMN_HOVER_CHANGED,
                    api: this.gridApi,
                    columnApi: this.columnApi
                };
                this.eventService.dispatchEvent(event);
            };
            ColumnHoverService.prototype.isHovered = function(column) {
                return this.selectedColumns && this.selectedColumns.indexOf(column) >= 0;
            };
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], ColumnHoverService.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], ColumnHoverService.prototype, "columnApi", void 0);
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], ColumnHoverService.prototype, "gridApi", void 0);
            ColumnHoverService = __decorate([ context_1.Bean("columnHoverService") ], ColumnHoverService);
            return ColumnHoverService;
        }(beanStub_1.BeanStub);
        exports.ColumnHoverService = ColumnHoverService;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var eventService_1 = __webpack_require__(3);
        var utils_1 = __webpack_require__(1);
        var TouchListener = function() {
            function TouchListener(eElement, preventMouseClick) {
                if (preventMouseClick === void 0) {
                    preventMouseClick = false;
                }
                var _this = this;
                this.destroyFuncs = [];
                this.touching = false;
                this.eventService = new eventService_1.EventService();
                this.eElement = eElement;
                this.preventMouseClick = preventMouseClick;
                var startListener = this.onTouchStart.bind(this);
                var moveListener = this.onTouchMove.bind(this);
                var endListener = this.onTouchEnd.bind(this);
                this.eElement.addEventListener("touchstart", startListener, {
                    passive: true
                });
                this.eElement.addEventListener("touchmove", moveListener, {
                    passive: true
                });
                this.eElement.addEventListener("touchend", endListener, {
                    passive: false
                });
                this.destroyFuncs.push(function() {
                    _this.eElement.addEventListener("touchstart", startListener, {
                        passive: true
                    });
                    _this.eElement.addEventListener("touchmove", moveListener, {
                        passive: true
                    });
                    _this.eElement.addEventListener("touchend", endListener, {
                        passive: false
                    });
                });
            }
            TouchListener.prototype.getActiveTouch = function(touchList) {
                for (var i = 0; i < touchList.length; i++) {
                    var matches = touchList[i].identifier === this.touchStart.identifier;
                    if (matches) {
                        return touchList[i];
                    }
                }
                return null;
            };
            TouchListener.prototype.addEventListener = function(eventType, listener) {
                this.eventService.addEventListener(eventType, listener);
            };
            TouchListener.prototype.removeEventListener = function(eventType, listener) {
                this.eventService.removeEventListener(eventType, listener);
            };
            TouchListener.prototype.onTouchStart = function(touchEvent) {
                var _this = this;
                if (this.touching) {
                    return;
                }
                this.touchStart = touchEvent.touches[0];
                this.touching = true;
                this.moved = false;
                var touchStartCopy = this.touchStart;
                setTimeout(function() {
                    var touchesMatch = _this.touchStart === touchStartCopy;
                    if (_this.touching && touchesMatch && !_this.moved) {
                        _this.moved = true;
                        var event_1 = {
                            type: TouchListener.EVENT_LONG_TAP,
                            touchStart: _this.touchStart,
                            touchEvent: touchEvent
                        };
                        _this.eventService.dispatchEvent(event_1);
                    }
                }, 500);
            };
            TouchListener.prototype.onTouchMove = function(touchEvent) {
                if (!this.touching) {
                    return;
                }
                var touch = this.getActiveTouch(touchEvent.touches);
                if (!touch) {
                    return;
                }
                var eventIsFarAway = !utils_1.Utils.areEventsNear(touch, this.touchStart, 4);
                if (eventIsFarAway) {
                    this.moved = true;
                }
            };
            TouchListener.prototype.onTouchEnd = function(touchEvent) {
                if (!this.touching) {
                    return;
                }
                if (!this.moved) {
                    var event_2 = {
                        type: TouchListener.EVENT_TAP,
                        touchStart: this.touchStart
                    };
                    this.eventService.dispatchEvent(event_2);
                    this.checkForDoubleTap();
                    if (this.preventMouseClick) {
                        touchEvent.preventDefault();
                    }
                }
                this.touching = false;
            };
            TouchListener.prototype.checkForDoubleTap = function() {
                var now = new Date().getTime();
                if (this.lastTapTime > 0) {
                    var interval = now - this.lastTapTime;
                    if (interval > TouchListener.DOUBLE_TAP_MILLIS) {
                        var event_3 = {
                            type: TouchListener.EVENT_DOUBLE_TAP,
                            touchStart: this.touchStart
                        };
                        this.eventService.dispatchEvent(event_3);
                        this.lastTapTime = null;
                    } else {
                        this.lastTapTime = now;
                    }
                } else {
                    this.lastTapTime = now;
                }
            };
            TouchListener.prototype.destroy = function() {
                this.destroyFuncs.forEach(function(func) {
                    return func();
                });
            };
            TouchListener.EVENT_TAP = "tap";
            TouchListener.EVENT_DOUBLE_TAP = "doubleTap";
            TouchListener.EVENT_LONG_TAP = "longTap";
            TouchListener.DOUBLE_TAP_MILLIS = 500;
            return TouchListener;
        }();
        exports.TouchListener = TouchListener;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var gridSerializer_1 = __webpack_require__(63);
        var downloader_1 = __webpack_require__(84);
        var columnController_1 = __webpack_require__(4);
        var valueService_1 = __webpack_require__(16);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var constants_1 = __webpack_require__(9);
        var utils_1 = __webpack_require__(1);
        var LINE_SEPARATOR = "\r\n";
        var CsvSerializingSession = function(_super) {
            __extends(CsvSerializingSession, _super);
            function CsvSerializingSession(columnController, valueService, gridOptionsWrapper, processCellCallback, processHeaderCallback, suppressQuotes, columnSeparator) {
                var _this = _super.call(this, columnController, valueService, gridOptionsWrapper, processCellCallback, processHeaderCallback) || this;
                _this.suppressQuotes = suppressQuotes;
                _this.columnSeparator = columnSeparator;
                _this.result = "";
                _this.lineOpened = false;
                return _this;
            }
            CsvSerializingSession.prototype.prepare = function(columnsToExport) {};
            CsvSerializingSession.prototype.addCustomHeader = function(customHeader) {
                if (!customHeader) return;
                this.result += customHeader + LINE_SEPARATOR;
            };
            CsvSerializingSession.prototype.addCustomFooter = function(customFooter) {
                if (!customFooter) return;
                this.result += customFooter + LINE_SEPARATOR;
            };
            CsvSerializingSession.prototype.onNewHeaderGroupingRow = function() {
                if (this.lineOpened) this.result += LINE_SEPARATOR;
                return {
                    onColumn: this.onNewHeaderGroupingRowColumn.bind(this)
                };
            };
            CsvSerializingSession.prototype.onNewHeaderGroupingRowColumn = function(header, index, span) {
                if (index != 0) {
                    this.result += this.columnSeparator;
                }
                this.result += header;
                for (var i = 1; i <= span; i++) {
                    this.result += this.columnSeparator + this.putInQuotes("", this.suppressQuotes);
                }
                this.lineOpened = true;
            };
            CsvSerializingSession.prototype.onNewHeaderRow = function() {
                if (this.lineOpened) this.result += LINE_SEPARATOR;
                return {
                    onColumn: this.onNewHeaderRowColumn.bind(this)
                };
            };
            CsvSerializingSession.prototype.onNewHeaderRowColumn = function(column, index, node) {
                if (index != 0) {
                    this.result += this.columnSeparator;
                }
                this.result += this.putInQuotes(this.extractHeaderValue(column), this.suppressQuotes);
                this.lineOpened = true;
            };
            CsvSerializingSession.prototype.onNewBodyRow = function() {
                if (this.lineOpened) this.result += LINE_SEPARATOR;
                return {
                    onColumn: this.onNewBodyRowColumn.bind(this)
                };
            };
            CsvSerializingSession.prototype.onNewBodyRowColumn = function(column, index, node) {
                if (index != 0) {
                    this.result += this.columnSeparator;
                }
                this.result += this.putInQuotes(this.extractRowCellValue(column, index, constants_1.Constants.EXPORT_TYPE_CSV, node), this.suppressQuotes);
                this.lineOpened = true;
            };
            CsvSerializingSession.prototype.putInQuotes = function(value, suppressQuotes) {
                if (suppressQuotes) {
                    return value;
                }
                if (value === null || value === undefined) {
                    return '""';
                }
                var stringValue;
                if (typeof value === "string") {
                    stringValue = value;
                } else if (typeof value.toString === "function") {
                    stringValue = value.toString();
                } else {
                    console.warn("unknown value type during csv conversion");
                    stringValue = "";
                }
                var valueEscaped = stringValue.replace(/"/g, '""');
                return '"' + valueEscaped + '"';
            };
            CsvSerializingSession.prototype.parse = function() {
                return this.result;
            };
            return CsvSerializingSession;
        }(gridSerializer_1.BaseGridSerializingSession);
        exports.CsvSerializingSession = CsvSerializingSession;
        var BaseCreator = function() {
            function BaseCreator() {}
            BaseCreator.prototype.setBeans = function(beans) {
                this.beans = beans;
            };
            BaseCreator.prototype.export = function(userParams) {
                if (this.isExportSuppressed()) {
                    console.warn("ag-grid: Export canceled. Export is not allowed as per your configuration.");
                    return "";
                }
                var _a = this.getMergedParamsAndData(userParams), mergedParams = _a.mergedParams, data = _a.data;
                var fileNamePresent = mergedParams && mergedParams.fileName && mergedParams.fileName.length !== 0;
                var fileName = fileNamePresent ? mergedParams.fileName : this.getDefaultFileName();
                if (fileName.indexOf(".") === -1) {
                    fileName = fileName + "." + this.getDefaultFileExtension();
                }
                this.beans.downloader.download(fileName, data, this.getMimeType());
                return data;
            };
            BaseCreator.prototype.getData = function(params) {
                return this.getMergedParamsAndData(params).data;
            };
            BaseCreator.prototype.getMergedParamsAndData = function(userParams) {
                var mergedParams = this.mergeDefaultParams(userParams);
                var data = this.beans.gridSerializer.serialize(this.createSerializingSession(mergedParams), mergedParams);
                return {
                    mergedParams: mergedParams,
                    data: data
                };
            };
            BaseCreator.prototype.mergeDefaultParams = function(userParams) {
                var baseParams = this.beans.gridOptionsWrapper.getDefaultExportParams();
                var params = {};
                utils_1._.assign(params, baseParams);
                utils_1._.assign(params, userParams);
                return params;
            };
            return BaseCreator;
        }();
        exports.BaseCreator = BaseCreator;
        var CsvCreator = function(_super) {
            __extends(CsvCreator, _super);
            function CsvCreator() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            CsvCreator.prototype.postConstruct = function() {
                this.setBeans({
                    downloader: this.downloader,
                    gridSerializer: this.gridSerializer,
                    gridOptionsWrapper: this.gridOptionsWrapper
                });
            };
            CsvCreator.prototype.exportDataAsCsv = function(params) {
                return this.export(params);
            };
            CsvCreator.prototype.getDataAsCsv = function(params) {
                return this.getData(params);
            };
            CsvCreator.prototype.getMimeType = function() {
                return "text/csv;charset=utf-8;";
            };
            CsvCreator.prototype.getDefaultFileName = function() {
                return "export.csv";
            };
            CsvCreator.prototype.getDefaultFileExtension = function() {
                return "csv";
            };
            CsvCreator.prototype.createSerializingSession = function(params) {
                return new CsvSerializingSession(this.columnController, this.valueService, this.gridOptionsWrapper, params ? params.processCellCallback : null, params ? params.processHeaderCallback : null, params && params.suppressQuotes, params && params.columnSeparator || ",");
            };
            CsvCreator.prototype.isExportSuppressed = function() {
                return this.gridOptionsWrapper.isSuppressCsvExport();
            };
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], CsvCreator.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("valueService"), __metadata("design:type", valueService_1.ValueService) ], CsvCreator.prototype, "valueService", void 0);
            __decorate([ context_1.Autowired("downloader"), __metadata("design:type", downloader_1.Downloader) ], CsvCreator.prototype, "downloader", void 0);
            __decorate([ context_1.Autowired("gridSerializer"), __metadata("design:type", gridSerializer_1.GridSerializer) ], CsvCreator.prototype, "gridSerializer", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], CsvCreator.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], CsvCreator.prototype, "postConstruct", null);
            CsvCreator = __decorate([ context_1.Bean("csvCreator") ], CsvCreator);
            return CsvCreator;
        }(BaseCreator);
        exports.CsvCreator = CsvCreator;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var columnUtils_1 = __webpack_require__(31);
        var columnGroup_1 = __webpack_require__(26);
        var originalColumnGroup_1 = __webpack_require__(32);
        var context_1 = __webpack_require__(0);
        var utils_1 = __webpack_require__(1);
        var context_2 = __webpack_require__(0);
        var DisplayedGroupCreator = function() {
            function DisplayedGroupCreator() {}
            DisplayedGroupCreator.prototype.createDisplayedGroups = function(sortedVisibleColumns, balancedColumnTree, groupInstanceIdCreator, oldDisplayedGroups) {
                var _this = this;
                var result = [];
                var previousRealPath;
                var previousOriginalPath;
                var oldColumnsMapped = this.mapOldGroupsById(oldDisplayedGroups);
                sortedVisibleColumns.forEach(function(currentColumn) {
                    var currentOriginalPath = _this.getOriginalPathForColumn(balancedColumnTree, currentColumn);
                    var currentRealPath = [];
                    var firstColumn = !previousOriginalPath;
                    for (var i = 0; i < currentOriginalPath.length; i++) {
                        if (firstColumn || currentOriginalPath[i] !== previousOriginalPath[i]) {
                            var newGroup = _this.createColumnGroup(currentOriginalPath[i], groupInstanceIdCreator, oldColumnsMapped);
                            currentRealPath[i] = newGroup;
                            if (i == 0) {
                                result.push(newGroup);
                            } else {
                                currentRealPath[i - 1].addChild(newGroup);
                            }
                        } else {
                            currentRealPath[i] = previousRealPath[i];
                        }
                    }
                    var noColumnGroups = currentRealPath.length === 0;
                    if (noColumnGroups) {
                        result.push(currentColumn);
                    } else {
                        var leafGroup = currentRealPath[currentRealPath.length - 1];
                        leafGroup.addChild(currentColumn);
                    }
                    previousRealPath = currentRealPath;
                    previousOriginalPath = currentOriginalPath;
                });
                this.setupParentsIntoColumns(result, null);
                return result;
            };
            DisplayedGroupCreator.prototype.createColumnGroup = function(originalGroup, groupInstanceIdCreator, oldColumnsMapped) {
                var groupId = originalGroup.getGroupId();
                var instanceId = groupInstanceIdCreator.getInstanceIdForKey(groupId);
                var uniqueId = columnGroup_1.ColumnGroup.createUniqueId(groupId, instanceId);
                var columnGroup = oldColumnsMapped[uniqueId];
                if (columnGroup && columnGroup.getOriginalColumnGroup() !== originalGroup) {
                    columnGroup = null;
                }
                if (utils_1.Utils.exists(columnGroup)) {
                    columnGroup.reset();
                } else {
                    columnGroup = new columnGroup_1.ColumnGroup(originalGroup, groupId, instanceId);
                    this.context.wireBean(columnGroup);
                }
                return columnGroup;
            };
            DisplayedGroupCreator.prototype.mapOldGroupsById = function(displayedGroups) {
                var result = {};
                var recursive = function(columnsOrGroups) {
                    columnsOrGroups.forEach(function(columnOrGroup) {
                        if (columnOrGroup instanceof columnGroup_1.ColumnGroup) {
                            var columnGroup = columnOrGroup;
                            result[columnOrGroup.getUniqueId()] = columnGroup;
                            recursive(columnGroup.getChildren());
                        }
                    });
                };
                if (displayedGroups) {
                    recursive(displayedGroups);
                }
                return result;
            };
            DisplayedGroupCreator.prototype.setupParentsIntoColumns = function(columnsOrGroups, parent) {
                var _this = this;
                columnsOrGroups.forEach(function(columnsOrGroup) {
                    columnsOrGroup.setParent(parent);
                    if (columnsOrGroup instanceof columnGroup_1.ColumnGroup) {
                        var columnGroup = columnsOrGroup;
                        _this.setupParentsIntoColumns(columnGroup.getChildren(), columnGroup);
                    }
                });
            };
            DisplayedGroupCreator.prototype.getOriginalPathForColumn = function(balancedColumnTree, column) {
                var result = [];
                var found = false;
                recursePath(balancedColumnTree, 0);
                if (found) {
                    return result;
                } else {
                    console.log("could not get path");
                    return null;
                }
                function recursePath(balancedColumnTree, dept) {
                    for (var i = 0; i < balancedColumnTree.length; i++) {
                        if (found) {
                            return;
                        }
                        var node = balancedColumnTree[i];
                        if (node instanceof originalColumnGroup_1.OriginalColumnGroup) {
                            var nextNode = node;
                            recursePath(nextNode.getChildren(), dept + 1);
                            result[dept] = node;
                        } else {
                            if (node === column) {
                                found = true;
                            }
                        }
                    }
                }
            };
            __decorate([ context_2.Autowired("columnUtils"), __metadata("design:type", columnUtils_1.ColumnUtils) ], DisplayedGroupCreator.prototype, "columnUtils", void 0);
            __decorate([ context_2.Autowired("context"), __metadata("design:type", context_1.Context) ], DisplayedGroupCreator.prototype, "context", void 0);
            DisplayedGroupCreator = __decorate([ context_1.Bean("displayedGroupCreator") ], DisplayedGroupCreator);
            return DisplayedGroupCreator;
        }();
        exports.DisplayedGroupCreator = DisplayedGroupCreator;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var context_2 = __webpack_require__(0);
        var TemplateService = function() {
            function TemplateService() {
                this.templateCache = {};
                this.waitingCallbacks = {};
            }
            TemplateService.prototype.getTemplate = function(url, callback) {
                var templateFromCache = this.templateCache[url];
                if (templateFromCache) {
                    return templateFromCache;
                }
                var callbackList = this.waitingCallbacks[url];
                var that = this;
                if (!callbackList) {
                    callbackList = [];
                    this.waitingCallbacks[url] = callbackList;
                    var client = new XMLHttpRequest();
                    client.onload = function() {
                        that.handleHttpResult(this, url);
                    };
                    client.open("GET", url);
                    client.send();
                }
                if (callback) {
                    callbackList.push(callback);
                }
                return null;
            };
            TemplateService.prototype.handleHttpResult = function(httpResult, url) {
                if (httpResult.status !== 200 || httpResult.response === null) {
                    console.warn("Unable to get template error " + httpResult.status + " - " + url);
                    return;
                }
                this.templateCache[url] = httpResult.response || httpResult.responseText;
                var callbacks = this.waitingCallbacks[url];
                for (var i = 0; i < callbacks.length; i++) {
                    var callback = callbacks[i];
                    callback();
                }
                if (this.$scope) {
                    var that_1 = this;
                    setTimeout(function() {
                        that_1.$scope.$apply();
                    }, 0);
                }
            };
            __decorate([ context_2.Autowired("$scope"), __metadata("design:type", Object) ], TemplateService.prototype, "$scope", void 0);
            TemplateService = __decorate([ context_1.Bean("templateService") ], TemplateService);
            return TemplateService;
        }();
        exports.TemplateService = TemplateService;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var cellComp_1 = __webpack_require__(34);
        var rowNode_1 = __webpack_require__(14);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var column_1 = __webpack_require__(10);
        var events_1 = __webpack_require__(5);
        var context_1 = __webpack_require__(0);
        var component_1 = __webpack_require__(8);
        var componentAnnotations_1 = __webpack_require__(11);
        var LoadingCellRenderer = function(_super) {
            __extends(LoadingCellRenderer, _super);
            function LoadingCellRenderer() {
                return _super.call(this, LoadingCellRenderer.TEMPLATE) || this;
            }
            LoadingCellRenderer.prototype.init = function(params) {
                var eLoadingIcon = utils_1._.createIconNoSpan("groupLoading", this.gridOptionsWrapper, null);
                this.eLoadingIcon.appendChild(eLoadingIcon);
                var localeTextFunc = this.gridOptionsWrapper.getLocaleTextFunc();
                this.eLoadingText.innerText = localeTextFunc("loadingOoo", "Loading");
            };
            LoadingCellRenderer.prototype.refresh = function(params) {
                return false;
            };
            LoadingCellRenderer.TEMPLATE = '<div class="ag-stub-cell">\n            <span class="ag-loading-icon" ref="eLoadingIcon"></span>\n            <span class="ag-loading-text" ref="eLoadingText"></span>\n        </div>';
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], LoadingCellRenderer.prototype, "gridOptionsWrapper", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eLoadingIcon"), __metadata("design:type", HTMLElement) ], LoadingCellRenderer.prototype, "eLoadingIcon", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eLoadingText"), __metadata("design:type", HTMLElement) ], LoadingCellRenderer.prototype, "eLoadingText", void 0);
            return LoadingCellRenderer;
        }(component_1.Component);
        exports.LoadingCellRenderer = LoadingCellRenderer;
        var RowComp = function(_super) {
            __extends(RowComp, _super);
            function RowComp(parentScope, bodyContainerComp, pinnedLeftContainerComp, pinnedRightContainerComp, fullWidthContainerComp, rowNode, beans, animateIn, useAnimationFrameForCreate) {
                var _this = _super.call(this) || this;
                _this.eAllRowContainers = [];
                _this.active = true;
                _this.columnRefreshPending = false;
                _this.cellComps = {};
                _this.createSecondPassFuncs = [];
                _this.removeFirstPassFuncs = [];
                _this.removeSecondPassFuncs = [];
                _this.initialised = false;
                _this.parentScope = parentScope;
                _this.beans = beans;
                _this.bodyContainerComp = bodyContainerComp;
                _this.pinnedLeftContainerComp = pinnedLeftContainerComp;
                _this.pinnedRightContainerComp = pinnedRightContainerComp;
                _this.fullWidthContainerComp = fullWidthContainerComp;
                _this.rowNode = rowNode;
                _this.rowIsEven = _this.rowNode.rowIndex % 2 === 0;
                _this.paginationPage = _this.beans.paginationProxy.getCurrentPage();
                _this.useAnimationFrameForCreate = useAnimationFrameForCreate;
                _this.setAnimateFlags(animateIn);
                return _this;
            }
            RowComp.prototype.init = function() {
                var _this = this;
                this.rowFocused = this.beans.focusedCellController.isRowFocused(this.rowNode.rowIndex, this.rowNode.rowPinned);
                this.scope = this.createChildScopeOrNull(this.rowNode.data);
                this.setupRowContainers();
                this.addListeners();
                if (this.slideRowIn) {
                    this.createSecondPassFuncs.push(function() {
                        _this.onTopChanged();
                    });
                }
                if (this.fadeRowIn) {
                    this.createSecondPassFuncs.push(function() {
                        _this.eAllRowContainers.forEach(function(eRow) {
                            return utils_1._.removeCssClass(eRow, "ag-opacity-zero");
                        });
                    });
                }
            };
            RowComp.prototype.createTemplate = function(contents, extraCssClass) {
                if (extraCssClass === void 0) {
                    extraCssClass = null;
                }
                var templateParts = [];
                var rowHeight = this.rowNode.rowHeight;
                var rowClasses = this.getInitialRowClasses(extraCssClass).join(" ");
                var rowIdSanitised = utils_1._.escape(this.rowNode.id);
                var userRowStyles = this.preProcessStylesFromGridOptions();
                var businessKey = this.getRowBusinessKey();
                var businessKeySanitised = utils_1._.escape(businessKey);
                var rowTopStyle = this.getInitialRowTopStyle();
                templateParts.push("<div");
                templateParts.push(' role="row"');
                templateParts.push(' row-index="' + this.rowNode.getRowIndexString() + '"');
                templateParts.push(rowIdSanitised ? ' row-id="' + rowIdSanitised + '"' : "");
                templateParts.push(businessKey ? ' row-business-key="' + businessKeySanitised + '"' : "");
                templateParts.push(' comp-id="' + this.getCompId() + '"');
                templateParts.push(' class="' + rowClasses + '"');
                templateParts.push(' style="height: ' + rowHeight + "px; " + rowTopStyle + " " + userRowStyles + '">');
                templateParts.push(contents);
                templateParts.push("</div>");
                return templateParts.join("");
            };
            RowComp.prototype.getCellForCol = function(column) {
                var cellComp = this.cellComps[column.getColId()];
                if (cellComp) {
                    return cellComp.getGui();
                } else {
                    return null;
                }
            };
            RowComp.prototype.afterFlush = function() {
                if (!this.initialised) {
                    this.initialised = true;
                    this.executeProcessRowPostCreateFunc();
                }
            };
            RowComp.prototype.executeProcessRowPostCreateFunc = function() {
                var func = this.beans.gridOptionsWrapper.getProcessRowPostCreateFunc();
                if (func) {
                    var params = {
                        eRow: this.eBodyRow,
                        ePinnedLeftRow: this.ePinnedLeftRow,
                        ePinnedRightRow: this.ePinnedRightRow,
                        node: this.rowNode,
                        api: this.beans.gridOptionsWrapper.getApi(),
                        rowIndex: this.rowNode.rowIndex,
                        addRenderedRowListener: this.addEventListener.bind(this),
                        columnApi: this.beans.gridOptionsWrapper.getColumnApi(),
                        context: this.beans.gridOptionsWrapper.getContext()
                    };
                    func(params);
                }
            };
            RowComp.prototype.getInitialRowTopStyle = function() {
                var pixels = this.slideRowIn ? this.roundRowTopToBounds(this.rowNode.oldRowTop) : this.rowNode.rowTop;
                var afterPaginationPixels = this.applyPaginationOffset(pixels);
                var afterScalingPixels = this.beans.heightScaler.getRealPixelPosition(afterPaginationPixels);
                if (this.beans.gridOptionsWrapper.isSuppressRowTransform()) {
                    return "top: " + afterScalingPixels + "px; ";
                } else {
                    return "transform: translateY(" + afterScalingPixels + "px); ";
                }
            };
            RowComp.prototype.getRowBusinessKey = function() {
                if (typeof this.beans.gridOptionsWrapper.getBusinessKeyForNodeFunc() === "function") {
                    var businessKey = this.beans.gridOptionsWrapper.getBusinessKeyForNodeFunc()(this.rowNode);
                    return businessKey;
                }
            };
            RowComp.prototype.lazyCreateCells = function(cols, eRow) {
                if (this.active) {
                    var cellTemplatesAndComps = this.createCells(cols);
                    eRow.innerHTML = cellTemplatesAndComps.template;
                    this.callAfterRowAttachedOnCells(cellTemplatesAndComps.cellComps, eRow);
                }
            };
            RowComp.prototype.createRowContainer = function(rowContainerComp, cols, callback) {
                var _this = this;
                var cellTemplatesAndComps;
                if (this.useAnimationFrameForCreate) {
                    cellTemplatesAndComps = {
                        cellComps: [],
                        template: ""
                    };
                } else {
                    cellTemplatesAndComps = this.createCells(cols);
                }
                var rowTemplate = this.createTemplate(cellTemplatesAndComps.template);
                rowContainerComp.appendRowTemplate(rowTemplate, function() {
                    var eRow = rowContainerComp.getRowElement(_this.getCompId());
                    _this.afterRowAttached(rowContainerComp, eRow);
                    callback(eRow);
                    if (_this.useAnimationFrameForCreate) {
                        _this.beans.taskQueue.addP1Task(_this.lazyCreateCells.bind(_this, cols, eRow));
                    } else {
                        _this.callAfterRowAttachedOnCells(cellTemplatesAndComps.cellComps, eRow);
                    }
                });
            };
            RowComp.prototype.createChildScopeOrNull = function(data) {
                if (this.beans.gridOptionsWrapper.isAngularCompileRows()) {
                    var newChildScope_1 = this.parentScope.$new();
                    newChildScope_1.data = data;
                    newChildScope_1.rowNode = this.rowNode;
                    newChildScope_1.context = this.beans.gridOptionsWrapper.getContext();
                    this.addDestroyFunc(function() {
                        newChildScope_1.$destroy();
                        newChildScope_1.data = null;
                        newChildScope_1.rowNode = null;
                        newChildScope_1.context = null;
                    });
                    return newChildScope_1;
                } else {
                    return null;
                }
            };
            RowComp.prototype.setupRowContainers = function() {
                var isFullWidthCellFunc = this.beans.gridOptionsWrapper.getIsFullWidthCellFunc();
                var isFullWidthCell = isFullWidthCellFunc ? isFullWidthCellFunc(this.rowNode) : false;
                var isDetailCell = this.beans.doingMasterDetail && this.rowNode.detail;
                var isGroupSpanningRow = this.rowNode.group && this.beans.gridOptionsWrapper.isGroupUseEntireRow();
                if (this.rowNode.stub) {
                    this.createFullWidthRows(RowComp.LOADING_CELL_RENDERER, RowComp.LOADING_CELL_RENDERER_COMP_NAME);
                } else if (isDetailCell) {
                    this.createFullWidthRows(RowComp.DETAIL_CELL_RENDERER, RowComp.DETAIL_CELL_RENDERER_COMP_NAME);
                } else if (isFullWidthCell) {
                    this.createFullWidthRows(RowComp.FULL_WIDTH_CELL_RENDERER, null);
                } else if (isGroupSpanningRow) {
                    this.createFullWidthRows(RowComp.GROUP_ROW_RENDERER, RowComp.GROUP_ROW_RENDERER_COMP_NAME);
                } else {
                    this.setupNormalRowContainers();
                }
            };
            RowComp.prototype.setupNormalRowContainers = function() {
                var _this = this;
                var centerCols = this.beans.columnController.getAllDisplayedCenterVirtualColumnsForRow(this.rowNode);
                this.createRowContainer(this.bodyContainerComp, centerCols, function(eRow) {
                    return _this.eBodyRow = eRow;
                });
                var leftCols = this.beans.columnController.getDisplayedLeftColumnsForRow(this.rowNode);
                var rightCols = this.beans.columnController.getDisplayedRightColumnsForRow(this.rowNode);
                this.createRowContainer(this.pinnedRightContainerComp, rightCols, function(eRow) {
                    return _this.ePinnedRightRow = eRow;
                });
                this.createRowContainer(this.pinnedLeftContainerComp, leftCols, function(eRow) {
                    return _this.ePinnedLeftRow = eRow;
                });
            };
            RowComp.prototype.createFullWidthRows = function(type, name) {
                var _this = this;
                this.fullWidthRow = true;
                this.fullWidthRowEmbedded = this.beans.gridOptionsWrapper.isEmbedFullWidthRows();
                if (this.fullWidthRowEmbedded) {
                    this.createFullWidthRowContainer(this.bodyContainerComp, null, null, type, name, function(eRow) {
                        _this.eFullWidthRowBody = eRow;
                    }, function(cellRenderer) {
                        _this.fullWidthRowComponentBody = cellRenderer;
                    });
                    this.createFullWidthRowContainer(this.pinnedLeftContainerComp, column_1.Column.PINNED_LEFT, "ag-cell-last-left-pinned", type, name, function(eRow) {
                        _this.eFullWidthRowLeft = eRow;
                    }, function(cellRenderer) {
                        _this.fullWidthRowComponentLeft = cellRenderer;
                    });
                    this.createFullWidthRowContainer(this.pinnedRightContainerComp, column_1.Column.PINNED_RIGHT, "ag-cell-first-right-pinned", type, name, function(eRow) {
                        _this.eFullWidthRowRight = eRow;
                    }, function(cellRenderer) {
                        _this.fullWidthRowComponentRight = cellRenderer;
                    });
                } else {
                    this.createFullWidthRowContainer(this.fullWidthContainerComp, null, null, type, name, function(eRow) {
                        _this.eFullWidthRow = eRow;
                    }, function(cellRenderer) {
                        _this.fullWidthRowComponent = cellRenderer;
                    });
                }
            };
            RowComp.prototype.setAnimateFlags = function(animateIn) {
                if (animateIn) {
                    var oldRowTopExists = utils_1._.exists(this.rowNode.oldRowTop);
                    this.slideRowIn = oldRowTopExists;
                    this.fadeRowIn = !oldRowTopExists;
                } else {
                    this.slideRowIn = false;
                    this.fadeRowIn = false;
                }
            };
            RowComp.prototype.isEditing = function() {
                return this.editingRow;
            };
            RowComp.prototype.stopRowEditing = function(cancel) {
                this.stopEditing(cancel);
            };
            RowComp.prototype.isFullWidth = function() {
                return this.fullWidthRow;
            };
            RowComp.prototype.addListeners = function() {
                this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_HEIGHT_CHANGED, this.onRowHeightChanged.bind(this));
                this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_ROW_SELECTED, this.onRowSelected.bind(this));
                this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_ROW_INDEX_CHANGED, this.onRowIndexChanged.bind(this));
                this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_TOP_CHANGED, this.onTopChanged.bind(this));
                this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_EXPANDED_CHANGED, this.onExpandedChanged.bind(this));
                this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_DATA_CHANGED, this.onRowNodeDataChanged.bind(this));
                this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_CELL_CHANGED, this.onRowNodeCellChanged.bind(this));
                this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_DRAGGING_CHANGED, this.onRowNodeDraggingChanged.bind(this));
                var eventService = this.beans.eventService;
                this.addDestroyableEventListener(eventService, events_1.Events.EVENT_HEIGHT_SCALE_CHANGED, this.onTopChanged.bind(this));
                this.addDestroyableEventListener(eventService, events_1.Events.EVENT_DISPLAYED_COLUMNS_CHANGED, this.onDisplayedColumnsChanged.bind(this));
                this.addDestroyableEventListener(eventService, events_1.Events.EVENT_VIRTUAL_COLUMNS_CHANGED, this.onVirtualColumnsChanged.bind(this));
                this.addDestroyableEventListener(eventService, events_1.Events.EVENT_COLUMN_RESIZED, this.onColumnResized.bind(this));
                this.addDestroyableEventListener(eventService, events_1.Events.EVENT_CELL_FOCUSED, this.onCellFocusChanged.bind(this));
                this.addDestroyableEventListener(eventService, events_1.Events.EVENT_PAGINATION_CHANGED, this.onPaginationChanged.bind(this));
                this.addDestroyableEventListener(eventService, events_1.Events.EVENT_GRID_COLUMNS_CHANGED, this.onGridColumnsChanged.bind(this));
            };
            RowComp.prototype.onGridColumnsChanged = function() {
                var allRenderedCellIds = Object.keys(this.cellComps);
                this.removeRenderedCells(allRenderedCellIds);
            };
            RowComp.prototype.onRowNodeDataChanged = function(event) {
                this.forEachCellComp(function(cellComp) {
                    return cellComp.refreshCell({
                        suppressFlash: !event.update,
                        newData: !event.update
                    });
                });
                this.onRowSelected();
                this.postProcessCss();
            };
            RowComp.prototype.onRowNodeCellChanged = function(event) {
                this.postProcessCss();
            };
            RowComp.prototype.postProcessCss = function() {
                this.postProcessStylesFromGridOptions();
                this.postProcessClassesFromGridOptions();
                this.postProcessRowClassRules();
                this.postProcessRowDragging();
            };
            RowComp.prototype.onRowNodeDraggingChanged = function() {
                this.postProcessRowDragging();
            };
            RowComp.prototype.postProcessRowDragging = function() {
                var dragging = this.rowNode.dragging;
                this.eAllRowContainers.forEach(function(row) {
                    return utils_1._.addOrRemoveCssClass(row, "ag-row-dragging", dragging);
                });
            };
            RowComp.prototype.onExpandedChanged = function() {
                if (this.rowNode.group && !this.rowNode.footer) {
                    var expanded_1 = this.rowNode.expanded;
                    this.eAllRowContainers.forEach(function(row) {
                        return utils_1._.addOrRemoveCssClass(row, "ag-row-group-expanded", expanded_1);
                    });
                    this.eAllRowContainers.forEach(function(row) {
                        return utils_1._.addOrRemoveCssClass(row, "ag-row-group-contracted", !expanded_1);
                    });
                }
            };
            RowComp.prototype.onDisplayedColumnsChanged = function() {
                if (!this.fullWidthRow) {
                    this.refreshCells();
                }
            };
            RowComp.prototype.destroyFullWidthComponents = function() {
                if (this.fullWidthRowComponent) {
                    if (this.fullWidthRowComponent.destroy) {
                        this.fullWidthRowComponent.destroy();
                    }
                    this.fullWidthRowComponent = null;
                }
                if (this.fullWidthRowComponentBody) {
                    if (this.fullWidthRowComponentBody.destroy) {
                        this.fullWidthRowComponentBody.destroy();
                    }
                    this.fullWidthRowComponent = null;
                }
                if (this.fullWidthRowComponentLeft) {
                    if (this.fullWidthRowComponentLeft.destroy) {
                        this.fullWidthRowComponentLeft.destroy();
                    }
                    this.fullWidthRowComponentLeft = null;
                }
                if (this.fullWidthRowComponentRight) {
                    if (this.fullWidthRowComponentRight.destroy) {
                        this.fullWidthRowComponentRight.destroy();
                    }
                    this.fullWidthRowComponent = null;
                }
            };
            RowComp.prototype.getContainerForCell = function(pinnedType) {
                switch (pinnedType) {
                  case column_1.Column.PINNED_LEFT:
                    return this.ePinnedLeftRow;

                  case column_1.Column.PINNED_RIGHT:
                    return this.ePinnedRightRow;

                  default:
                    return this.eBodyRow;
                }
            };
            RowComp.prototype.onVirtualColumnsChanged = function() {
                if (!this.fullWidthRow) {
                    this.refreshCells();
                }
            };
            RowComp.prototype.onColumnResized = function() {
                if (!this.fullWidthRow) {
                    this.refreshCells();
                }
            };
            RowComp.prototype.refreshCells = function() {
                if (this.beans.gridOptionsWrapper.isSuppressAnimationFrame()) {
                    this.refreshCellsInAnimationFrame();
                } else {
                    if (this.columnRefreshPending) {
                        return;
                    }
                    this.beans.taskQueue.addP1Task(this.refreshCellsInAnimationFrame.bind(this));
                }
            };
            RowComp.prototype.refreshCellsInAnimationFrame = function() {
                if (!this.active) {
                    return;
                }
                this.columnRefreshPending = false;
                var centerCols = this.beans.columnController.getAllDisplayedCenterVirtualColumnsForRow(this.rowNode);
                var leftCols = this.beans.columnController.getDisplayedLeftColumnsForRow(this.rowNode);
                var rightCols = this.beans.columnController.getDisplayedRightColumnsForRow(this.rowNode);
                this.insertCellsIntoContainer(this.eBodyRow, centerCols);
                this.insertCellsIntoContainer(this.ePinnedLeftRow, leftCols);
                this.insertCellsIntoContainer(this.ePinnedRightRow, rightCols);
                var colIdsToRemove = Object.keys(this.cellComps);
                centerCols.forEach(function(col) {
                    return utils_1._.removeFromArray(colIdsToRemove, col.getId());
                });
                leftCols.forEach(function(col) {
                    return utils_1._.removeFromArray(colIdsToRemove, col.getId());
                });
                rightCols.forEach(function(col) {
                    return utils_1._.removeFromArray(colIdsToRemove, col.getId());
                });
                colIdsToRemove = utils_1._.filter(colIdsToRemove, this.isCellEligibleToBeRemoved.bind(this));
                this.removeRenderedCells(colIdsToRemove);
            };
            RowComp.prototype.removeRenderedCells = function(colIds) {
                var _this = this;
                colIds.forEach(function(key) {
                    var cellComp = _this.cellComps[key];
                    if (utils_1._.missing(cellComp)) {
                        return;
                    }
                    cellComp.detach();
                    cellComp.destroy();
                    _this.cellComps[key] = null;
                });
            };
            RowComp.prototype.isCellEligibleToBeRemoved = function(indexStr) {
                var displayedColumns = this.beans.columnController.getAllDisplayedColumns();
                var REMOVE_CELL = true;
                var KEEP_CELL = false;
                var renderedCell = this.cellComps[indexStr];
                if (!renderedCell) {
                    return REMOVE_CELL;
                }
                if (this.isCellInWrongRow(renderedCell)) {
                    return REMOVE_CELL;
                }
                var editing = renderedCell.isEditing();
                var focused = this.beans.focusedCellController.isCellFocused(renderedCell.getGridCell());
                var mightWantToKeepCell = editing || focused;
                if (mightWantToKeepCell) {
                    var column = renderedCell.getColumn();
                    var cellStillDisplayed = displayedColumns.indexOf(column) >= 0;
                    return cellStillDisplayed ? KEEP_CELL : REMOVE_CELL;
                } else {
                    return REMOVE_CELL;
                }
            };
            RowComp.prototype.ensureCellInCorrectContainer = function(cellComp) {
                var element = cellComp.getGui();
                var column = cellComp.getColumn();
                var pinnedType = column.getPinned();
                var eContainer = this.getContainerForCell(pinnedType);
                var eOldContainer = cellComp.getParentRow();
                var inWrongRow = eOldContainer !== eContainer;
                if (inWrongRow) {
                    if (eOldContainer) {
                        eOldContainer.removeChild(element);
                    }
                    eContainer.appendChild(element);
                    cellComp.setParentRow(eContainer);
                }
            };
            RowComp.prototype.isCellInWrongRow = function(cellComp) {
                var column = cellComp.getColumn();
                var rowWeWant = this.getContainerForCell(column.getPinned());
                var oldRow = cellComp.getParentRow();
                return oldRow !== rowWeWant;
            };
            RowComp.prototype.insertCellsIntoContainer = function(eRow, cols) {
                var _this = this;
                if (!eRow) {
                    return;
                }
                var cellTemplates = [];
                var newCellComps = [];
                cols.forEach(function(col) {
                    var colId = col.getId();
                    var oldCell = _this.cellComps[colId];
                    if (oldCell) {
                        _this.ensureCellInCorrectContainer(oldCell);
                    } else {
                        _this.createNewCell(col, eRow, cellTemplates, newCellComps);
                    }
                });
                if (cellTemplates.length > 0) {
                    utils_1._.appendHtml(eRow, cellTemplates.join(""));
                    this.callAfterRowAttachedOnCells(newCellComps, eRow);
                }
            };
            RowComp.prototype.addDomData = function(eRowContainer) {
                var gow = this.beans.gridOptionsWrapper;
                gow.setDomData(eRowContainer, RowComp.DOM_DATA_KEY_RENDERED_ROW, this);
                this.addDestroyFunc(function() {
                    gow.setDomData(eRowContainer, RowComp.DOM_DATA_KEY_RENDERED_ROW, null);
                });
            };
            RowComp.prototype.createNewCell = function(col, eContainer, cellTemplates, newCellComps) {
                var newCellComp = new cellComp_1.CellComp(this.scope, this.beans, col, this.rowNode, this, false);
                var cellTemplate = newCellComp.getCreateTemplate();
                cellTemplates.push(cellTemplate);
                newCellComps.push(newCellComp);
                this.cellComps[col.getId()] = newCellComp;
                newCellComp.setParentRow(eContainer);
            };
            RowComp.prototype.onMouseEvent = function(eventName, mouseEvent) {
                switch (eventName) {
                  case "dblclick":
                    this.onRowDblClick(mouseEvent);
                    break;

                  case "click":
                    this.onRowClick(mouseEvent);
                    break;
                }
            };
            RowComp.prototype.createRowEvent = function(type, domEvent) {
                return {
                    type: type,
                    node: this.rowNode,
                    data: this.rowNode.data,
                    rowIndex: this.rowNode.rowIndex,
                    rowPinned: this.rowNode.rowPinned,
                    context: this.beans.gridOptionsWrapper.getContext(),
                    api: this.beans.gridOptionsWrapper.getApi(),
                    columnApi: this.beans.gridOptionsWrapper.getColumnApi(),
                    event: domEvent
                };
            };
            RowComp.prototype.createRowEventWithSource = function(type, domEvent) {
                var event = this.createRowEvent(type, domEvent);
                event.source = this;
                return event;
            };
            RowComp.prototype.onRowDblClick = function(mouseEvent) {
                if (utils_1._.isStopPropagationForAgGrid(mouseEvent)) {
                    return;
                }
                var agEvent = this.createRowEventWithSource(events_1.Events.EVENT_ROW_DOUBLE_CLICKED, mouseEvent);
                this.beans.eventService.dispatchEvent(agEvent);
            };
            RowComp.prototype.onRowClick = function(mouseEvent) {
                var stop = utils_1._.isStopPropagationForAgGrid(mouseEvent);
                if (stop) {
                    return;
                }
                var agEvent = this.createRowEventWithSource(events_1.Events.EVENT_ROW_CLICKED, mouseEvent);
                this.beans.eventService.dispatchEvent(agEvent);
                var multiSelectKeyPressed = mouseEvent.ctrlKey || mouseEvent.metaKey;
                var shiftKeyPressed = mouseEvent.shiftKey;
                if (this.rowNode.group) {
                    return;
                }
                if (this.rowNode.rowPinned) {
                    return;
                }
                if (!this.beans.gridOptionsWrapper.isRowSelection()) {
                    return;
                }
                if (this.beans.gridOptionsWrapper.isSuppressRowClickSelection()) {
                    return;
                }
                var multiSelectOnClick = this.beans.gridOptionsWrapper.isRowMultiSelectWithClick();
                var rowDeselectionWithCtrl = this.beans.gridOptionsWrapper.isRowDeselection();
                if (this.rowNode.isSelected()) {
                    if (multiSelectOnClick) {
                        this.rowNode.setSelectedParams({
                            newValue: false
                        });
                    } else if (multiSelectKeyPressed) {
                        if (rowDeselectionWithCtrl) {
                            this.rowNode.setSelectedParams({
                                newValue: false
                            });
                        }
                    } else {
                        this.rowNode.setSelectedParams({
                            newValue: true,
                            clearSelection: true
                        });
                    }
                } else {
                    var clearSelection = multiSelectOnClick ? false : !multiSelectKeyPressed;
                    this.rowNode.setSelectedParams({
                        newValue: true,
                        clearSelection: clearSelection,
                        rangeSelect: shiftKeyPressed
                    });
                }
            };
            RowComp.prototype.createFullWidthRowContainer = function(rowContainerComp, pinned, extraCssClass, cellRendererType, cellRendererName, eRowCallback, cellRendererCallback) {
                var _this = this;
                var rowTemplate = this.createTemplate("", extraCssClass);
                rowContainerComp.appendRowTemplate(rowTemplate, function() {
                    var eRow = rowContainerComp.getRowElement(_this.getCompId());
                    var params = _this.createFullWidthParams(eRow, pinned);
                    var callback = function(cellRenderer) {
                        if (_this.isAlive()) {
                            var gui = cellRenderer.getGui();
                            eRow.appendChild(gui);
                            cellRendererCallback(cellRenderer);
                        } else {
                            if (cellRenderer.destroy) {
                                cellRenderer.destroy();
                            }
                        }
                    };
                    _this.beans.componentResolver.createAgGridComponent(null, params, cellRendererType, params, cellRendererName).then(callback);
                    _this.afterRowAttached(rowContainerComp, eRow);
                    eRowCallback(eRow);
                    _this.angular1Compile(eRow);
                });
            };
            RowComp.prototype.angular1Compile = function(element) {
                if (this.scope) {
                    this.beans.$compile(element)(this.scope);
                }
            };
            RowComp.prototype.createFullWidthParams = function(eRow, pinned) {
                var params = {
                    fullWidth: true,
                    data: this.rowNode.data,
                    node: this.rowNode,
                    value: this.rowNode.key,
                    $scope: this.scope,
                    rowIndex: this.rowNode.rowIndex,
                    api: this.beans.gridOptionsWrapper.getApi(),
                    columnApi: this.beans.gridOptionsWrapper.getColumnApi(),
                    context: this.beans.gridOptionsWrapper.getContext(),
                    eGridCell: eRow,
                    eParentOfValue: eRow,
                    pinned: pinned,
                    addRenderedRowListener: this.addEventListener.bind(this)
                };
                return params;
            };
            RowComp.prototype.getInitialRowClasses = function(extraCssClass) {
                var classes = [];
                if (utils_1._.exists(extraCssClass)) {
                    classes.push(extraCssClass);
                }
                classes.push("ag-row");
                classes.push(this.rowFocused ? "ag-row-focus" : "ag-row-no-focus");
                if (this.fadeRowIn) {
                    classes.push("ag-opacity-zero");
                }
                if (this.rowIsEven) {
                    classes.push("ag-row-even");
                } else {
                    classes.push("ag-row-odd");
                }
                if (this.rowNode.isSelected()) {
                    classes.push("ag-row-selected");
                }
                if (this.rowNode.group) {
                    classes.push("ag-row-group");
                    classes.push("ag-row-level-" + this.rowNode.level);
                    if (this.rowNode.footer) {
                        classes.push("ag-row-footer");
                    }
                } else {
                    if (this.rowNode.parent) {
                        classes.push("ag-row-level-" + (this.rowNode.parent.level + 1));
                    } else {
                        classes.push("ag-row-level-0");
                    }
                }
                if (this.rowNode.stub) {
                    classes.push("ag-row-stub");
                }
                if (this.fullWidthRow) {
                    classes.push("ag-full-width-row");
                }
                if (this.rowNode.group && !this.rowNode.footer) {
                    classes.push(this.rowNode.expanded ? "ag-row-group-expanded" : "ag-row-group-contracted");
                }
                if (this.rowNode.dragging) {
                    classes.push("ag-row-dragging");
                }
                utils_1._.pushAll(classes, this.processClassesFromGridOptions());
                utils_1._.pushAll(classes, this.preProcessRowClassRules());
                return classes;
            };
            RowComp.prototype.preProcessRowClassRules = function() {
                var res = [];
                this.processRowClassRules(function(className) {
                    res.push(className);
                }, function(className) {});
                return res;
            };
            RowComp.prototype.processRowClassRules = function(onApplicableClass, onNotApplicableClass) {
                this.beans.stylingService.processClassRules(this.beans.gridOptionsWrapper.rowClassRules(), {
                    value: undefined,
                    colDef: undefined,
                    data: this.rowNode.data,
                    node: this.rowNode,
                    rowIndex: this.rowNode.rowIndex,
                    api: this.beans.gridOptionsWrapper.getApi(),
                    $scope: this.scope,
                    context: this.beans.gridOptionsWrapper.getContext()
                }, onApplicableClass, onNotApplicableClass);
            };
            RowComp.prototype.stopEditing = function(cancel) {
                if (cancel === void 0) {
                    cancel = false;
                }
                this.forEachCellComp(function(renderedCell) {
                    renderedCell.stopEditing(cancel);
                });
                if (this.editingRow) {
                    if (!cancel) {
                        var event_1 = this.createRowEvent(events_1.Events.EVENT_ROW_VALUE_CHANGED);
                        this.beans.eventService.dispatchEvent(event_1);
                    }
                    this.setEditingRow(false);
                }
            };
            RowComp.prototype.setEditingRow = function(value) {
                this.editingRow = value;
                this.eAllRowContainers.forEach(function(row) {
                    return utils_1._.addOrRemoveCssClass(row, "ag-row-editing", value);
                });
                var event = value ? this.createRowEvent(events_1.Events.EVENT_ROW_EDITING_STARTED) : this.createRowEvent(events_1.Events.EVENT_ROW_EDITING_STOPPED);
                this.beans.eventService.dispatchEvent(event);
            };
            RowComp.prototype.startRowEditing = function(keyPress, charPress, sourceRenderedCell) {
                if (keyPress === void 0) {
                    keyPress = null;
                }
                if (charPress === void 0) {
                    charPress = null;
                }
                if (sourceRenderedCell === void 0) {
                    sourceRenderedCell = null;
                }
                if (this.editingRow) {
                    return;
                }
                this.forEachCellComp(function(renderedCell) {
                    var cellStartedEdit = renderedCell === sourceRenderedCell;
                    if (cellStartedEdit) {
                        renderedCell.startEditingIfEnabled(keyPress, charPress, cellStartedEdit);
                    } else {
                        renderedCell.startEditingIfEnabled(null, null, cellStartedEdit);
                    }
                });
                this.setEditingRow(true);
            };
            RowComp.prototype.forEachCellComp = function(callback) {
                utils_1._.iterateObject(this.cellComps, function(key, cellComp) {
                    if (cellComp) {
                        callback(cellComp);
                    }
                });
            };
            RowComp.prototype.postProcessClassesFromGridOptions = function() {
                var _this = this;
                var cssClasses = this.processClassesFromGridOptions();
                if (cssClasses) {
                    cssClasses.forEach(function(classStr) {
                        _this.eAllRowContainers.forEach(function(row) {
                            return utils_1._.addCssClass(row, classStr);
                        });
                    });
                }
            };
            RowComp.prototype.postProcessRowClassRules = function() {
                var _this = this;
                this.processRowClassRules(function(className) {
                    _this.eAllRowContainers.forEach(function(row) {
                        return utils_1._.addCssClass(row, className);
                    });
                }, function(className) {
                    _this.eAllRowContainers.forEach(function(row) {
                        return utils_1._.removeCssClass(row, className);
                    });
                });
            };
            RowComp.prototype.processClassesFromGridOptions = function() {
                var res = [];
                var process = function(rowClass) {
                    if (typeof rowClass === "string") {
                        res.push(rowClass);
                    } else if (Array.isArray(rowClass)) {
                        rowClass.forEach(function(e) {
                            return res.push(e);
                        });
                    }
                };
                var rowClass = this.beans.gridOptionsWrapper.getRowClass();
                if (rowClass) {
                    if (typeof rowClass === "function") {
                        console.warn("ag-Grid: rowClass should not be a function, please use getRowClass instead");
                        return;
                    }
                    process(rowClass);
                }
                var rowClassFunc = this.beans.gridOptionsWrapper.getRowClassFunc();
                if (rowClassFunc) {
                    var params = {
                        node: this.rowNode,
                        data: this.rowNode.data,
                        rowIndex: this.rowNode.rowIndex,
                        context: this.beans.gridOptionsWrapper.getContext(),
                        api: this.beans.gridOptionsWrapper.getApi()
                    };
                    var rowClassFuncResult = rowClassFunc(params);
                    process(rowClassFuncResult);
                }
                return res;
            };
            RowComp.prototype.preProcessStylesFromGridOptions = function() {
                var rowStyles = this.processStylesFromGridOptions();
                return utils_1._.cssStyleObjectToMarkup(rowStyles);
            };
            RowComp.prototype.postProcessStylesFromGridOptions = function() {
                var rowStyles = this.processStylesFromGridOptions();
                this.eAllRowContainers.forEach(function(row) {
                    return utils_1._.addStylesToElement(row, rowStyles);
                });
            };
            RowComp.prototype.processStylesFromGridOptions = function() {
                var rowStyle = this.beans.gridOptionsWrapper.getRowStyle();
                if (rowStyle && typeof rowStyle === "function") {
                    console.log("ag-Grid: rowStyle should be an object of key/value styles, not be a function, use getRowStyle() instead");
                    return;
                }
                var rowStyleFunc = this.beans.gridOptionsWrapper.getRowStyleFunc();
                var rowStyleFuncResult;
                if (rowStyleFunc) {
                    var params = {
                        data: this.rowNode.data,
                        node: this.rowNode,
                        api: this.beans.gridOptionsWrapper.getApi(),
                        context: this.beans.gridOptionsWrapper.getContext(),
                        $scope: this.scope
                    };
                    rowStyleFuncResult = rowStyleFunc(params);
                }
                return utils_1._.assign({}, rowStyle, rowStyleFuncResult);
            };
            RowComp.prototype.createCells = function(cols) {
                var _this = this;
                var templateParts = [];
                var newCellComps = [];
                cols.forEach(function(col) {
                    var newCellComp = new cellComp_1.CellComp(_this.scope, _this.beans, col, _this.rowNode, _this, false);
                    var cellTemplate = newCellComp.getCreateTemplate();
                    templateParts.push(cellTemplate);
                    newCellComps.push(newCellComp);
                    _this.cellComps[col.getId()] = newCellComp;
                });
                var templateAndComps = {
                    template: templateParts.join(""),
                    cellComps: newCellComps
                };
                return templateAndComps;
            };
            RowComp.prototype.onRowSelected = function() {
                var selected = this.rowNode.isSelected();
                this.eAllRowContainers.forEach(function(row) {
                    return utils_1._.addOrRemoveCssClass(row, "ag-row-selected", selected);
                });
            };
            RowComp.prototype.callAfterRowAttachedOnCells = function(newCellComps, eRow) {
                var _this = this;
                newCellComps.forEach(function(cellComp) {
                    cellComp.setParentRow(eRow);
                    cellComp.afterAttached();
                    if (_this.editingRow) {
                        cellComp.startEditingIfEnabled();
                    }
                });
            };
            RowComp.prototype.afterRowAttached = function(rowContainerComp, eRow) {
                var _this = this;
                this.addDomData(eRow);
                this.removeSecondPassFuncs.push(function() {
                    rowContainerComp.removeRowElement(eRow);
                });
                this.removeFirstPassFuncs.push(function() {
                    if (utils_1._.exists(_this.rowNode.rowTop)) {
                        var rowTop = _this.roundRowTopToBounds(_this.rowNode.rowTop);
                        _this.setRowTop(rowTop);
                    } else {
                        utils_1._.addCssClass(eRow, "ag-opacity-zero");
                    }
                });
                this.eAllRowContainers.push(eRow);
                if (this.useAnimationFrameForCreate) {
                    this.beans.taskQueue.addP1Task(this.addHoverFunctionality.bind(this, eRow));
                } else {
                    this.addHoverFunctionality(eRow);
                }
            };
            RowComp.prototype.addHoverFunctionality = function(eRow) {
                var _this = this;
                if (!this.active) {
                    return;
                }
                this.addDestroyableEventListener(eRow, "mouseenter", function() {
                    return _this.rowNode.onMouseEnter();
                });
                this.addDestroyableEventListener(eRow, "mouseleave", function() {
                    return _this.rowNode.onMouseLeave();
                });
                this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_MOUSE_ENTER, function() {
                    if (!_this.beans.gridOptionsWrapper.isSuppressRowHoverHighlight()) {
                        utils_1._.addCssClass(eRow, "ag-row-hover");
                    }
                });
                this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_MOUSE_LEAVE, function() {
                    utils_1._.removeCssClass(eRow, "ag-row-hover");
                });
            };
            RowComp.prototype.roundRowTopToBounds = function(rowTop) {
                var range = this.beans.gridPanel.getVScrollPosition();
                var minPixel = this.applyPaginationOffset(range.top, true) - 100;
                var maxPixel = this.applyPaginationOffset(range.bottom, true) + 100;
                if (rowTop < minPixel) {
                    return minPixel;
                } else if (rowTop > maxPixel) {
                    return maxPixel;
                } else {
                    return rowTop;
                }
            };
            RowComp.prototype.onRowHeightChanged = function() {
                if (utils_1._.exists(this.rowNode.rowHeight)) {
                    var heightPx_1 = this.rowNode.rowHeight + "px";
                    this.eAllRowContainers.forEach(function(row) {
                        return row.style.height = heightPx_1;
                    });
                }
            };
            RowComp.prototype.addEventListener = function(eventType, listener) {
                if (eventType === "renderedRowRemoved" || eventType === "rowRemoved") {
                    eventType = events_1.Events.EVENT_VIRTUAL_ROW_REMOVED;
                    console.warn("ag-Grid: Since version 11, event renderedRowRemoved is now called " + events_1.Events.EVENT_VIRTUAL_ROW_REMOVED);
                }
                _super.prototype.addEventListener.call(this, eventType, listener);
            };
            RowComp.prototype.removeEventListener = function(eventType, listener) {
                if (eventType === "renderedRowRemoved" || eventType === "rowRemoved") {
                    eventType = events_1.Events.EVENT_VIRTUAL_ROW_REMOVED;
                    console.warn("ag-Grid: Since version 11, event renderedRowRemoved and rowRemoved is now called " + events_1.Events.EVENT_VIRTUAL_ROW_REMOVED);
                }
                _super.prototype.removeEventListener.call(this, eventType, listener);
            };
            RowComp.prototype.destroy = function(animate) {
                if (animate === void 0) {
                    animate = false;
                }
                _super.prototype.destroy.call(this);
                this.active = false;
                this.destroyFullWidthComponents();
                if (animate) {
                    this.removeFirstPassFuncs.forEach(function(func) {
                        return func();
                    });
                    this.removeSecondPassFuncs.push(this.destroyContainingCells.bind(this));
                } else {
                    this.destroyContainingCells();
                    var delayedDestroyFunctions = this.getAndClearDelayedDestroyFunctions();
                    delayedDestroyFunctions.forEach(function(func) {
                        return func();
                    });
                }
                var event = this.createRowEvent(events_1.Events.EVENT_VIRTUAL_ROW_REMOVED);
                this.dispatchEvent(event);
                this.beans.eventService.dispatchEvent(event);
            };
            RowComp.prototype.destroyContainingCells = function() {
                this.forEachCellComp(function(renderedCell) {
                    return renderedCell.destroy();
                });
                this.destroyFullWidthComponents();
            };
            RowComp.prototype.getAndClearDelayedDestroyFunctions = function() {
                var result = this.removeSecondPassFuncs;
                this.removeSecondPassFuncs = [];
                return result;
            };
            RowComp.prototype.onCellFocusChanged = function() {
                var rowFocused = this.beans.focusedCellController.isRowFocused(this.rowNode.rowIndex, this.rowNode.rowPinned);
                if (rowFocused !== this.rowFocused) {
                    this.eAllRowContainers.forEach(function(row) {
                        return utils_1._.addOrRemoveCssClass(row, "ag-row-focus", rowFocused);
                    });
                    this.eAllRowContainers.forEach(function(row) {
                        return utils_1._.addOrRemoveCssClass(row, "ag-row-no-focus", !rowFocused);
                    });
                    this.rowFocused = rowFocused;
                }
                if (!rowFocused && this.editingRow) {
                    this.stopEditing(false);
                }
            };
            RowComp.prototype.onPaginationChanged = function() {
                var currentPage = this.beans.paginationProxy.getCurrentPage();
                if (this.paginationPage !== currentPage) {
                    this.paginationPage = currentPage;
                    this.onTopChanged();
                }
            };
            RowComp.prototype.onTopChanged = function() {
                this.setRowTop(this.rowNode.rowTop);
            };
            RowComp.prototype.applyPaginationOffset = function(topPx, reverse) {
                if (reverse === void 0) {
                    reverse = false;
                }
                if (this.rowNode.isRowPinned()) {
                    return topPx;
                } else {
                    var pixelOffset = this.beans.paginationProxy.getPixelOffset();
                    if (reverse) {
                        return topPx + pixelOffset;
                    } else {
                        return topPx - pixelOffset;
                    }
                }
            };
            RowComp.prototype.setRowTop = function(pixels) {
                if (utils_1._.exists(pixels)) {
                    var afterPaginationPixels = this.applyPaginationOffset(pixels);
                    var afterScalingPixels = this.beans.heightScaler.getRealPixelPosition(afterPaginationPixels);
                    var topPx_1 = afterScalingPixels + "px";
                    if (this.beans.gridOptionsWrapper.isSuppressRowTransform()) {
                        this.eAllRowContainers.forEach(function(row) {
                            return row.style.top = "" + topPx_1;
                        });
                    } else {
                        this.eAllRowContainers.forEach(function(row) {
                            return row.style.transform = "translateY(" + topPx_1 + ")";
                        });
                    }
                }
            };
            RowComp.prototype.getAndClearNextVMTurnFunctions = function() {
                var result = this.createSecondPassFuncs;
                this.createSecondPassFuncs = [];
                return result;
            };
            RowComp.prototype.getRowNode = function() {
                return this.rowNode;
            };
            RowComp.prototype.getRenderedCellForColumn = function(column) {
                return this.cellComps[column.getColId()];
            };
            RowComp.prototype.onRowIndexChanged = function() {
                this.onCellFocusChanged();
                this.updateRowIndexes();
            };
            RowComp.prototype.updateRowIndexes = function() {
                var rowIndexStr = this.rowNode.getRowIndexString();
                var rowIsEven = this.rowNode.rowIndex % 2 === 0;
                var rowIsEvenChanged = this.rowIsEven !== rowIsEven;
                if (rowIsEvenChanged) {
                    this.rowIsEven = rowIsEven;
                }
                this.eAllRowContainers.forEach(function(eRow) {
                    eRow.setAttribute("row-index", rowIndexStr);
                    if (rowIsEvenChanged) {
                        utils_1._.addOrRemoveCssClass(eRow, "ag-row-even", rowIsEven);
                        utils_1._.addOrRemoveCssClass(eRow, "ag-row-odd", !rowIsEven);
                    }
                });
            };
            RowComp.prototype.ensureDomOrder = function() {
                var body = this.getBodyRowElement();
                if (body) {
                    this.bodyContainerComp.ensureDomOrder(body);
                }
                var left = this.getPinnedLeftRowElement();
                if (left) {
                    this.pinnedLeftContainerComp.ensureDomOrder(left);
                }
                var right = this.getPinnedRightRowElement();
                if (right) {
                    this.pinnedRightContainerComp.ensureDomOrder(right);
                }
                var fullWidth = this.getFullWidthRowElement();
                if (fullWidth) {
                    this.fullWidthContainerComp.ensureDomOrder(fullWidth);
                }
            };
            RowComp.prototype.getPinnedLeftRowElement = function() {
                return this.ePinnedLeftRow ? this.ePinnedLeftRow : this.eFullWidthRowLeft;
            };
            RowComp.prototype.getPinnedRightRowElement = function() {
                return this.ePinnedRightRow ? this.ePinnedRightRow : this.eFullWidthRowRight;
            };
            RowComp.prototype.getBodyRowElement = function() {
                return this.eBodyRow ? this.eBodyRow : this.eFullWidthRowBody;
            };
            RowComp.prototype.getFullWidthRowElement = function() {
                return this.eFullWidthRow;
            };
            RowComp.DOM_DATA_KEY_RENDERED_ROW = "renderedRow";
            RowComp.FULL_WIDTH_CELL_RENDERER = "fullWidthCellRenderer";
            RowComp.GROUP_ROW_RENDERER = "groupRowRenderer";
            RowComp.GROUP_ROW_RENDERER_COMP_NAME = "agGroupRowRenderer";
            RowComp.LOADING_CELL_RENDERER = "loadingCellRenderer";
            RowComp.LOADING_CELL_RENDERER_COMP_NAME = "agLoadingCellRenderer";
            RowComp.DETAIL_CELL_RENDERER = "detailCellRenderer";
            RowComp.DETAIL_CELL_RENDERER_COMP_NAME = "agDetailCellRenderer";
            return RowComp;
        }(component_1.Component);
        exports.RowComp = RowComp;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var component_1 = __webpack_require__(8);
        var componentAnnotations_1 = __webpack_require__(11);
        var context_1 = __webpack_require__(0);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var utils_1 = __webpack_require__(1);
        var FilterConditionType;
        (function(FilterConditionType) {
            FilterConditionType[FilterConditionType["MAIN"] = 0] = "MAIN";
            FilterConditionType[FilterConditionType["CONDITION"] = 1] = "CONDITION";
        })(FilterConditionType = exports.FilterConditionType || (exports.FilterConditionType = {}));
        var DEFAULT_TRANSLATIONS = {
            loadingOoo: "Loading...",
            equals: "Equals",
            notEqual: "Not equal",
            lessThan: "Less than",
            greaterThan: "Greater than",
            inRange: "In range",
            lessThanOrEqual: "Less than or equals",
            greaterThanOrEqual: "Greater than or equals",
            filterOoo: "Filter...",
            contains: "Contains",
            notContains: "Not contains",
            startsWith: "Starts with",
            endsWith: "Ends with",
            searchOoo: "Search...",
            selectAll: "Select All",
            applyFilter: "Apply Filter",
            clearFilter: "Clear Filter"
        };
        var BaseFilter = function(_super) {
            __extends(BaseFilter, _super);
            function BaseFilter() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            BaseFilter.prototype.init = function(params) {
                this.filterParams = params;
                this.defaultFilter = this.filterParams.defaultOption;
                if (this.filterParams.filterOptions && !this.defaultFilter) {
                    if (this.filterParams.filterOptions.lastIndexOf(BaseFilter.EQUALS) < 0) {
                        this.defaultFilter = this.filterParams.filterOptions[0];
                    }
                }
                this.customInit();
                this.filter = this.defaultFilter;
                this.filterCondition = this.defaultFilter;
                this.clearActive = params.clearButton === true;
                this.applyActive = params.applyButton === true || params.apply === true;
                this.newRowsActionKeep = params.newRowsAction === "keep";
                this.setTemplate(this.generateTemplate());
                utils_1._.setVisible(this.eApplyButton, this.applyActive);
                if (this.applyActive) {
                    this.addDestroyableEventListener(this.eApplyButton, "click", this.filterParams.filterChangedCallback);
                }
                utils_1._.setVisible(this.eClearButton, this.clearActive);
                if (this.clearActive) {
                    this.addDestroyableEventListener(this.eClearButton, "click", this.onClearButton.bind(this));
                }
                var anyButtonVisible = this.applyActive || this.clearActive;
                utils_1._.setVisible(this.eButtonsPanel, anyButtonVisible);
                this.instantiate(this.context);
                this.initialiseFilterBodyUi(FilterConditionType.MAIN);
                this.refreshFilterBodyUi(FilterConditionType.MAIN);
            };
            BaseFilter.prototype.onClearButton = function() {
                this.setModel(null);
                this.onFilterChanged();
            };
            BaseFilter.prototype.floatingFilter = function(from) {
                if (from !== "") {
                    var model = this.modelFromFloatingFilter(from);
                    this.setModel(model);
                } else {
                    this.resetState();
                }
                this.onFilterChanged();
            };
            BaseFilter.prototype.onNewRowsLoaded = function() {
                if (!this.newRowsActionKeep) {
                    this.resetState();
                }
            };
            BaseFilter.prototype.getModel = function() {
                if (this.isFilterActive()) {
                    if (!this.isFilterConditionActive(FilterConditionType.CONDITION)) {
                        return this.serialize(FilterConditionType.MAIN);
                    } else {
                        return {
                            condition1: this.serialize(FilterConditionType.MAIN),
                            condition2: this.serialize(FilterConditionType.CONDITION),
                            operator: this.conditionValue
                        };
                    }
                } else {
                    return null;
                }
            };
            BaseFilter.prototype.getNullableModel = function() {
                if (!this.isFilterConditionActive(FilterConditionType.CONDITION)) {
                    return this.serialize(FilterConditionType.MAIN);
                } else {
                    return {
                        condition1: this.serialize(FilterConditionType.MAIN),
                        condition2: this.serialize(FilterConditionType.CONDITION),
                        operator: this.conditionValue
                    };
                }
            };
            BaseFilter.prototype.setModel = function(model) {
                if (model) {
                    if (!model.operator) {
                        this.resetState();
                        this.parse(model, FilterConditionType.MAIN);
                    } else {
                        var asCombinedFilter = model;
                        this.parse(asCombinedFilter.condition1, FilterConditionType.MAIN);
                        this.parse(asCombinedFilter.condition2, FilterConditionType.CONDITION);
                        this.conditionValue = asCombinedFilter.operator;
                    }
                } else {
                    this.resetState();
                }
                this.redrawCondition();
                this.refreshFilterBodyUi(FilterConditionType.MAIN);
                this.refreshFilterBodyUi(FilterConditionType.CONDITION);
            };
            BaseFilter.prototype.doOnFilterChanged = function(applyNow) {
                if (applyNow === void 0) {
                    applyNow = false;
                }
                this.filterParams.filterModifiedCallback();
                var requiresApplyAndIsApplying = this.applyActive && applyNow;
                var notRequiresApply = !this.applyActive;
                var shouldFilter = notRequiresApply || requiresApplyAndIsApplying;
                if (shouldFilter) {
                    this.filterParams.filterChangedCallback();
                }
                this.refreshFilterBodyUi(FilterConditionType.MAIN);
                this.refreshFilterBodyUi(FilterConditionType.CONDITION);
                return shouldFilter;
            };
            BaseFilter.prototype.onFilterChanged = function(applyNow) {
                if (applyNow === void 0) {
                    applyNow = false;
                }
                this.doOnFilterChanged(applyNow);
                this.redrawCondition();
                this.refreshFilterBodyUi(FilterConditionType.MAIN);
                this.refreshFilterBodyUi(FilterConditionType.CONDITION);
            };
            BaseFilter.prototype.redrawCondition = function() {
                var _this = this;
                var filterCondition = this.eFilterBodyWrapper.querySelector(".ag-filter-condition");
                if (!filterCondition && this.isFilterActive() && this.acceptsBooleanLogic()) {
                    this.eConditionWrapper = utils_1._.loadTemplate(this.createConditionTemplate(FilterConditionType.CONDITION));
                    this.eFilterBodyWrapper.appendChild(this.eConditionWrapper);
                    this.wireQuerySelectors();
                    var _a = this.refreshOperatorUi(), andButton = _a.andButton, orButton = _a.orButton;
                    this.addDestroyableEventListener(andButton, "change", function() {
                        _this.conditionValue = "AND";
                        _this.onFilterChanged();
                    });
                    this.addDestroyableEventListener(orButton, "change", function() {
                        _this.conditionValue = "OR";
                        _this.onFilterChanged();
                    });
                    this.initialiseFilterBodyUi(FilterConditionType.CONDITION);
                } else if (filterCondition && !this.isFilterActive()) {
                    this.eFilterBodyWrapper.removeChild(this.eConditionWrapper);
                    this.eConditionWrapper = null;
                } else {
                    this.refreshFilterBodyUi(FilterConditionType.CONDITION);
                    if (this.eConditionWrapper) {
                        this.refreshOperatorUi();
                    }
                }
            };
            BaseFilter.prototype.refreshOperatorUi = function() {
                var andButton = this.eConditionWrapper.querySelector(".and");
                var orButton = this.eConditionWrapper.querySelector(".or");
                this.conditionValue = this.conditionValue == null ? "AND" : this.conditionValue;
                andButton.checked = this.conditionValue === "AND";
                orButton.checked = this.conditionValue === "OR";
                return {
                    andButton: andButton,
                    orButton: orButton
                };
            };
            BaseFilter.prototype.onFloatingFilterChanged = function(change) {
                var casted = change;
                if (casted == null) {
                    this.setModel(null);
                } else if (!this.isFilterConditionActive(FilterConditionType.CONDITION)) {
                    this.setModel(casted ? casted.model : null);
                } else {
                    var combinedFilter = {
                        condition1: casted.model,
                        condition2: this.serialize(FilterConditionType.CONDITION),
                        operator: this.conditionValue
                    };
                    this.setModel(combinedFilter);
                }
                return this.doOnFilterChanged(casted ? casted.apply : false);
            };
            BaseFilter.prototype.generateFilterHeader = function(type) {
                return "";
            };
            BaseFilter.prototype.generateTemplate = function() {
                var translate = this.translate.bind(this);
                var mainConditionBody = this.createConditionBody(FilterConditionType.MAIN);
                var bodyWithBooleanLogic = !this.acceptsBooleanLogic() ? mainConditionBody : this.wrapCondition(mainConditionBody);
                return "<div>\n                    <div class='ag-filter-body-wrapper'>" + bodyWithBooleanLogic + '</div>\n                    <div class="ag-filter-apply-panel" id="applyPanel">\n                        <button type="button" id="clearButton">' + translate("clearFilter") + '</button>\n                        <button type="button" id="applyButton">' + translate("applyFilter") + "</button>\n                    </div>\n                </div>";
            };
            BaseFilter.prototype.acceptsBooleanLogic = function() {
                return false;
            };
            BaseFilter.prototype.wrapCondition = function(mainCondition) {
                if (!this.isFilterActive()) return mainCondition;
                return "" + mainCondition + this.createConditionTemplate(FilterConditionType.CONDITION);
            };
            BaseFilter.prototype.createConditionTemplate = function(type) {
                return '<div class="ag-filter-condition">\n            <input id="andId" type="radio" class="and" name="booleanLogic" value="AND" checked="checked" /><label style="display: inline" for="andId">AND</label>\n            <input id="orId" type="radio" class="or" name="booleanLogic" value="OR" /><label style="display: inline" for="orId">OR</label>\n            <div>' + this.createConditionBody(type) + "</div>\n        </div>";
            };
            BaseFilter.prototype.createConditionBody = function(type) {
                var body = this.bodyTemplate(type);
                return this.generateFilterHeader(type) + body;
            };
            BaseFilter.prototype.translate = function(toTranslate) {
                var translate = this.gridOptionsWrapper.getLocaleTextFunc();
                return translate(toTranslate, DEFAULT_TRANSLATIONS[toTranslate]);
            };
            BaseFilter.prototype.getDebounceMs = function(filterParams) {
                if (filterParams.applyButton && filterParams.debounceMs) {
                    console.warn("ag-Grid: debounceMs is ignored when applyButton = true");
                    return 0;
                }
                return filterParams.debounceMs != null ? filterParams.debounceMs : 500;
            };
            BaseFilter.EQUALS = "equals";
            BaseFilter.NOT_EQUAL = "notEqual";
            BaseFilter.LESS_THAN = "lessThan";
            BaseFilter.LESS_THAN_OR_EQUAL = "lessThanOrEqual";
            BaseFilter.GREATER_THAN = "greaterThan";
            BaseFilter.GREATER_THAN_OR_EQUAL = "greaterThanOrEqual";
            BaseFilter.IN_RANGE = "inRange";
            BaseFilter.CONTAINS = "contains";
            BaseFilter.NOT_CONTAINS = "notContains";
            BaseFilter.STARTS_WITH = "startsWith";
            BaseFilter.ENDS_WITH = "endsWith";
            __decorate([ componentAnnotations_1.QuerySelector("#applyPanel"), __metadata("design:type", HTMLElement) ], BaseFilter.prototype, "eButtonsPanel", void 0);
            __decorate([ componentAnnotations_1.QuerySelector(".ag-filter-body-wrapper"), __metadata("design:type", HTMLElement) ], BaseFilter.prototype, "eFilterBodyWrapper", void 0);
            __decorate([ componentAnnotations_1.QuerySelector("#applyButton"), __metadata("design:type", HTMLElement) ], BaseFilter.prototype, "eApplyButton", void 0);
            __decorate([ componentAnnotations_1.QuerySelector("#clearButton"), __metadata("design:type", HTMLElement) ], BaseFilter.prototype, "eClearButton", void 0);
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], BaseFilter.prototype, "context", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], BaseFilter.prototype, "gridOptionsWrapper", void 0);
            return BaseFilter;
        }(component_1.Component);
        exports.BaseFilter = BaseFilter;
        var ComparableBaseFilter = function(_super) {
            __extends(ComparableBaseFilter, _super);
            function ComparableBaseFilter() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            ComparableBaseFilter.prototype.doesFilterPass = function(params) {
                var mainFilterResult = this.individualFilterPasses(params, FilterConditionType.MAIN);
                if (this.eTypeConditionSelector == null) {
                    return mainFilterResult;
                }
                var auxFilterResult = this.individualFilterPasses(params, FilterConditionType.CONDITION);
                return this.conditionValue === "AND" ? mainFilterResult && auxFilterResult : mainFilterResult || auxFilterResult;
            };
            ComparableBaseFilter.prototype.init = function(params) {
                _super.prototype.init.call(this, params);
                this.suppressAndOrCondition = params.suppressAndOrCondition;
            };
            ComparableBaseFilter.prototype.customInit = function() {
                if (!this.defaultFilter) {
                    this.defaultFilter = this.getDefaultType();
                }
            };
            ComparableBaseFilter.prototype.acceptsBooleanLogic = function() {
                return this.suppressAndOrCondition !== true;
            };
            ComparableBaseFilter.prototype.generateFilterHeader = function(type) {
                var _this = this;
                var defaultFilterTypes = this.getApplicableFilterTypes();
                var restrictedFilterTypes = this.filterParams.filterOptions;
                var actualFilterTypes = restrictedFilterTypes ? restrictedFilterTypes : defaultFilterTypes;
                var optionsHtml = actualFilterTypes.map(function(filterType) {
                    var localeFilterName = _this.translate(filterType);
                    return '<option value="' + filterType + '">' + localeFilterName + "</option>";
                });
                var readOnly = optionsHtml.length == 1 ? "disabled" : "";
                var id = type == FilterConditionType.MAIN ? "filterType" : "filterConditionType";
                return optionsHtml.length <= 0 ? "" : '<div>\n                <select class="ag-filter-select" id="' + id + '" ' + readOnly + ">\n                    " + optionsHtml.join("") + "\n                </select>\n            </div>";
            };
            ComparableBaseFilter.prototype.initialiseFilterBodyUi = function(type) {
                var _this = this;
                if (type === FilterConditionType.MAIN) {
                    this.setFilterType(this.filter, type);
                    this.addDestroyableEventListener(this.eTypeSelector, "change", function() {
                        return _this.onFilterTypeChanged(type);
                    });
                } else {
                    this.setFilterType(this.filterCondition, type);
                    this.addDestroyableEventListener(this.eTypeConditionSelector, "change", function() {
                        return _this.onFilterTypeChanged(type);
                    });
                }
            };
            ComparableBaseFilter.prototype.onFilterTypeChanged = function(type) {
                if (type === FilterConditionType.MAIN) {
                    this.filter = this.eTypeSelector.value;
                } else {
                    this.filterCondition = this.eTypeConditionSelector.value;
                }
                this.refreshFilterBodyUi(type);
                if (this.isFilterActive()) {
                    this.onFilterChanged();
                }
            };
            ComparableBaseFilter.prototype.isFilterActive = function() {
                var rawFilterValues = this.filterValues(FilterConditionType.MAIN);
                if (this.filter === BaseFilter.IN_RANGE) {
                    var filterValueArray = rawFilterValues;
                    return filterValueArray[0] != null && filterValueArray[1] != null;
                } else {
                    return rawFilterValues != null;
                }
            };
            ComparableBaseFilter.prototype.setFilterType = function(filterType, type) {
                if (type === FilterConditionType.MAIN) {
                    this.filter = filterType;
                    if (!this.eTypeSelector) return;
                    this.eTypeSelector.value = filterType;
                } else {
                    this.filterCondition = filterType;
                    if (!this.eTypeConditionSelector) return;
                    this.eTypeConditionSelector.value = filterType;
                }
            };
            ComparableBaseFilter.prototype.isFilterConditionActive = function(type) {
                return this.filterValues(type) != null;
            };
            __decorate([ componentAnnotations_1.QuerySelector("#filterType"), __metadata("design:type", HTMLSelectElement) ], ComparableBaseFilter.prototype, "eTypeSelector", void 0);
            __decorate([ componentAnnotations_1.QuerySelector("#filterConditionType"), __metadata("design:type", HTMLSelectElement) ], ComparableBaseFilter.prototype, "eTypeConditionSelector", void 0);
            return ComparableBaseFilter;
        }(BaseFilter);
        exports.ComparableBaseFilter = ComparableBaseFilter;
        var ScalarBaseFilter = function(_super) {
            __extends(ScalarBaseFilter, _super);
            function ScalarBaseFilter() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            ScalarBaseFilter.prototype.nullComparator = function(type) {
                var _this = this;
                return function(filterValue, gridValue) {
                    if (gridValue == null) {
                        var nullValue = _this.translateNull(type);
                        if (_this.filter === BaseFilter.EQUALS) {
                            return nullValue ? 0 : 1;
                        }
                        if (_this.filter === BaseFilter.GREATER_THAN) {
                            return nullValue ? 1 : -1;
                        }
                        if (_this.filter === BaseFilter.GREATER_THAN_OR_EQUAL) {
                            return nullValue ? 1 : -1;
                        }
                        if (_this.filter === BaseFilter.LESS_THAN_OR_EQUAL) {
                            return nullValue ? -1 : 1;
                        }
                        if (_this.filter === BaseFilter.LESS_THAN) {
                            return nullValue ? -1 : 1;
                        }
                        if (_this.filter === BaseFilter.NOT_EQUAL) {
                            return nullValue ? 1 : 0;
                        }
                    }
                    var actualComparator = _this.comparator();
                    return actualComparator(filterValue, gridValue);
                };
            };
            ScalarBaseFilter.prototype.getDefaultType = function() {
                return BaseFilter.EQUALS;
            };
            ScalarBaseFilter.prototype.translateNull = function(type) {
                var reducedType = type.indexOf("greater") > -1 ? "greaterThan" : type.indexOf("lessThan") > -1 ? "lessThan" : "equals";
                if (this.filterParams.nullComparator && this.filterParams.nullComparator[reducedType]) {
                    return this.filterParams.nullComparator[reducedType];
                }
                return ScalarBaseFilter.DEFAULT_NULL_COMPARATOR[reducedType];
            };
            ScalarBaseFilter.prototype.individualFilterPasses = function(params, type) {
                return this.doIndividualFilterPasses(params, type, type === FilterConditionType.MAIN ? this.filter : this.filterCondition);
            };
            ScalarBaseFilter.prototype.doIndividualFilterPasses = function(params, type, filter) {
                var value = this.filterParams.valueGetter(params.node);
                var comparator = this.nullComparator(filter);
                var rawFilterValues = this.filterValues(type);
                var from = Array.isArray(rawFilterValues) ? rawFilterValues[0] : rawFilterValues;
                if (from == null) {
                    return type === FilterConditionType.MAIN ? true : this.conditionValue === "AND";
                }
                var compareResult = comparator(from, value);
                if (filter === BaseFilter.EQUALS) {
                    return compareResult === 0;
                }
                if (filter === BaseFilter.GREATER_THAN) {
                    return compareResult > 0;
                }
                if (filter === BaseFilter.GREATER_THAN_OR_EQUAL) {
                    return compareResult >= 0;
                }
                if (filter === BaseFilter.LESS_THAN_OR_EQUAL) {
                    return compareResult <= 0;
                }
                if (filter === BaseFilter.LESS_THAN) {
                    return compareResult < 0;
                }
                if (filter === BaseFilter.NOT_EQUAL) {
                    return compareResult != 0;
                }
                var compareToResult = comparator(rawFilterValues[1], value);
                if (filter === BaseFilter.IN_RANGE) {
                    if (!this.filterParams.inRangeInclusive) {
                        return compareResult > 0 && compareToResult < 0;
                    } else {
                        return compareResult >= 0 && compareToResult <= 0;
                    }
                }
                throw new Error("Unexpected type of filter!: " + filter);
            };
            ScalarBaseFilter.DEFAULT_NULL_COMPARATOR = {
                equals: false,
                lessThan: false,
                greaterThan: false
            };
            return ScalarBaseFilter;
        }(ComparableBaseFilter);
        exports.ScalarBaseFilter = ScalarBaseFilter;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var column_1 = __webpack_require__(10);
        var beanStub_1 = __webpack_require__(13);
        var SetLeftFeature = function(_super) {
            __extends(SetLeftFeature, _super);
            function SetLeftFeature(columnOrGroup, eCell, beans, colsSpanning) {
                var _this = _super.call(this) || this;
                _this.columnOrGroup = columnOrGroup;
                _this.eCell = eCell;
                _this.colsSpanning = colsSpanning;
                _this.beans = beans;
                return _this;
            }
            SetLeftFeature.prototype.setColsSpanning = function(colsSpanning) {
                this.colsSpanning = colsSpanning;
                this.onLeftChanged();
            };
            SetLeftFeature.prototype.getColumnOrGroup = function() {
                if (this.beans.gridOptionsWrapper.isEnableRtl() && this.colsSpanning) {
                    return this.colsSpanning[this.colsSpanning.length - 1];
                } else {
                    return this.columnOrGroup;
                }
            };
            SetLeftFeature.prototype.init = function() {
                this.addDestroyableEventListener(this.columnOrGroup, column_1.Column.EVENT_LEFT_CHANGED, this.onLeftChanged.bind(this));
                this.setLeftFirstTime();
            };
            SetLeftFeature.prototype.setLeftFirstTime = function() {
                var suppressMoveAnimation = this.beans.gridOptionsWrapper.isSuppressColumnMoveAnimation();
                var oldLeftExists = utils_1.Utils.exists(this.columnOrGroup.getOldLeft());
                var animateColumnMove = this.beans.columnAnimationService.isActive() && oldLeftExists && !suppressMoveAnimation;
                if (animateColumnMove) {
                    this.animateInLeft();
                } else {
                    this.onLeftChanged();
                }
            };
            SetLeftFeature.prototype.animateInLeft = function() {
                var _this = this;
                var left = this.getColumnOrGroup().getLeft();
                var oldLeft = this.getColumnOrGroup().getOldLeft();
                this.setLeft(oldLeft);
                this.actualLeft = left;
                this.beans.columnAnimationService.executeNextVMTurn(function() {
                    if (_this.actualLeft === left) {
                        _this.setLeft(left);
                    }
                });
            };
            SetLeftFeature.prototype.onLeftChanged = function() {
                this.actualLeft = this.getColumnOrGroup().getLeft();
                this.setLeft(this.actualLeft);
            };
            SetLeftFeature.prototype.setLeft = function(value) {
                if (utils_1.Utils.exists(value)) {
                    this.eCell.style.left = value + "px";
                }
            };
            return SetLeftFeature;
        }(beanStub_1.BeanStub);
        exports.SetLeftFeature = SetLeftFeature;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var ColumnAnimationService = function() {
            function ColumnAnimationService() {
                this.executeNextFuncs = [];
                this.executeLaterFuncs = [];
                this.active = false;
                this.animationThreadCount = 0;
            }
            ColumnAnimationService.prototype.registerGridComp = function(gridPanel) {
                this.gridPanel = gridPanel;
            };
            ColumnAnimationService.prototype.isActive = function() {
                return this.active;
            };
            ColumnAnimationService.prototype.start = function() {
                if (this.active) {
                    return;
                }
                if (this.gridOptionsWrapper.isSuppressColumnMoveAnimation()) {
                    return;
                }
                if (this.gridOptionsWrapper.isEnableRtl()) {
                    return;
                }
                this.ensureAnimationCssClassPresent();
                this.active = true;
            };
            ColumnAnimationService.prototype.finish = function() {
                if (!this.active) {
                    return;
                }
                this.flush();
                this.active = false;
            };
            ColumnAnimationService.prototype.executeNextVMTurn = function(func) {
                if (this.active) {
                    this.executeNextFuncs.push(func);
                } else {
                    func();
                }
            };
            ColumnAnimationService.prototype.executeLaterVMTurn = function(func) {
                if (this.active) {
                    this.executeLaterFuncs.push(func);
                } else {
                    func();
                }
            };
            ColumnAnimationService.prototype.ensureAnimationCssClassPresent = function() {
                var _this = this;
                this.animationThreadCount++;
                var animationThreadCountCopy = this.animationThreadCount;
                this.gridPanel.setColumnMovingCss(true);
                this.executeLaterFuncs.push(function() {
                    if (_this.animationThreadCount === animationThreadCountCopy) {
                        _this.gridPanel.setColumnMovingCss(false);
                    }
                });
            };
            ColumnAnimationService.prototype.flush = function() {
                var nowFuncs = this.executeNextFuncs;
                this.executeNextFuncs = [];
                var waitFuncs = this.executeLaterFuncs;
                this.executeLaterFuncs = [];
                if (nowFuncs.length === 0 && waitFuncs.length === 0) {
                    return;
                }
                setTimeout(function() {
                    return nowFuncs.forEach(function(func) {
                        return func();
                    });
                }, 0);
                setTimeout(function() {
                    return waitFuncs.forEach(function(func) {
                        return func();
                    });
                }, 300);
            };
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], ColumnAnimationService.prototype, "gridOptionsWrapper", void 0);
            ColumnAnimationService = __decorate([ context_1.Bean("columnAnimationService") ], ColumnAnimationService);
            return ColumnAnimationService;
        }();
        exports.ColumnAnimationService = ColumnAnimationService;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var popupEditorWrapper_1 = __webpack_require__(69);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var componentResolver_1 = __webpack_require__(27);
        var CellEditorFactory = function() {
            function CellEditorFactory() {}
            CellEditorFactory.prototype.init = function() {};
            CellEditorFactory.prototype.addCellEditor = function(key, cellEditor) {
                console.warn("ag-grid: since v13.3.1 this method is not supported anymore. If you want to register your own editor check the docs: https://www.ag-grid.com/javascript-grid-cell-editor/");
            };
            CellEditorFactory.prototype.createCellEditor = function(column, params) {
                var _this = this;
                var cellEditorPromise = this.componentResolver.createAgGridComponent(column, params, "cellEditor", {
                    api: params.api,
                    columnApi: params.columnApi,
                    node: params.node,
                    data: params.node.data,
                    rowIndex: params.rowIndex,
                    column: params.column,
                    colDef: params.column.getColDef()
                }, "agCellEditor");
                return cellEditorPromise.map(function(cellEditor) {
                    var isPopup = cellEditor.isPopup && cellEditor.isPopup();
                    if (!isPopup) {
                        return cellEditor;
                    }
                    if (_this.gridOptionsWrapper.isFullRowEdit()) {
                        console.warn("ag-Grid: popup cellEditor does not work with fullRowEdit - you cannot use them both " + "- either turn off fullRowEdit, or stop using popup editors.");
                    }
                    var popupEditorWrapper = new popupEditorWrapper_1.PopupEditorWrapper(cellEditor);
                    _this.context.wireBean(popupEditorWrapper);
                    popupEditorWrapper.init(params);
                    return popupEditorWrapper;
                });
            };
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], CellEditorFactory.prototype, "context", void 0);
            __decorate([ context_1.Autowired("componentResolver"), __metadata("design:type", componentResolver_1.ComponentResolver) ], CellEditorFactory.prototype, "componentResolver", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], CellEditorFactory.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], CellEditorFactory.prototype, "init", null);
            CellEditorFactory = __decorate([ context_1.Bean("cellEditorFactory") ], CellEditorFactory);
            return CellEditorFactory;
        }();
        exports.CellEditorFactory = CellEditorFactory;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var utils_1 = __webpack_require__(1);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var eventService_1 = __webpack_require__(3);
        var expressionService_1 = __webpack_require__(19);
        var animateSlideCellRenderer_1 = __webpack_require__(70);
        var animateShowChangeCellRenderer_1 = __webpack_require__(71);
        var groupCellRenderer_1 = __webpack_require__(72);
        var CellRendererFactory = function() {
            function CellRendererFactory() {
                this.cellRendererMap = {};
            }
            CellRendererFactory_1 = CellRendererFactory;
            CellRendererFactory.prototype.init = function() {
                this.cellRendererMap[CellRendererFactory_1.ANIMATE_SLIDE] = animateSlideCellRenderer_1.AnimateSlideCellRenderer;
                this.cellRendererMap[CellRendererFactory_1.ANIMATE_SHOW_CHANGE] = animateShowChangeCellRenderer_1.AnimateShowChangeCellRenderer;
                this.cellRendererMap[CellRendererFactory_1.GROUP] = groupCellRenderer_1.GroupCellRenderer;
            };
            CellRendererFactory.prototype.addCellRenderer = function(key, cellRenderer) {
                this.cellRendererMap[key] = cellRenderer;
            };
            CellRendererFactory.prototype.getCellRenderer = function(key) {
                var result = this.cellRendererMap[key];
                if (utils_1.Utils.missing(result)) {
                    console.warn("ag-Grid: unable to find cellRenderer for key " + key);
                    return null;
                }
                return result;
            };
            CellRendererFactory.ANIMATE_SLIDE = "animateSlide";
            CellRendererFactory.ANIMATE_SHOW_CHANGE = "animateShowChange";
            CellRendererFactory.GROUP = "group";
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], CellRendererFactory.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("expressionService"), __metadata("design:type", expressionService_1.ExpressionService) ], CellRendererFactory.prototype, "expressionService", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], CellRendererFactory.prototype, "eventService", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], CellRendererFactory.prototype, "init", null);
            CellRendererFactory = CellRendererFactory_1 = __decorate([ context_1.Bean("cellRendererFactory") ], CellRendererFactory);
            return CellRendererFactory;
            var CellRendererFactory_1;
        }();
        exports.CellRendererFactory = CellRendererFactory;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var componentRecipes_1 = __webpack_require__(21);
        var componentResolver_1 = __webpack_require__(27);
        var utils_1 = __webpack_require__(1);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var CellRendererService = function() {
            function CellRendererService() {}
            CellRendererService.prototype.useCellRenderer = function(target, eTarget, params) {
                var _this = this;
                var cellRendererPromise = this.componentRecipes.newCellRenderer(target, params);
                if (cellRendererPromise != null) {
                    cellRendererPromise.then(function(cellRenderer) {
                        if (cellRenderer == null) {
                            eTarget.innerText = params.valueFormatted != null ? params.valueFormatted : params.value;
                        } else {
                            _this.bindToHtml(cellRendererPromise, eTarget);
                        }
                    });
                } else {
                    eTarget.innerText = params.valueFormatted != null ? params.valueFormatted : params.value;
                }
                return cellRendererPromise;
            };
            CellRendererService.prototype.useFilterCellRenderer = function(target, eTarget, params) {
                var cellRendererPromise = this.componentRecipes.newCellRenderer(target.filterParams, params);
                if (cellRendererPromise != null) {
                    this.bindToHtml(cellRendererPromise, eTarget);
                } else {
                    if (params.valueFormatted == null && params.value == null) {
                        var localeTextFunc = this.gridOptionsWrapper.getLocaleTextFunc();
                        eTarget.innerText = "(" + localeTextFunc("blanks", "Blanks") + ")";
                    } else {
                        eTarget.innerText = params.valueFormatted != null ? params.valueFormatted : params.value;
                    }
                }
                return cellRendererPromise;
            };
            CellRendererService.prototype.useRichSelectCellRenderer = function(target, eTarget, params) {
                var cellRendererPromise = this.componentRecipes.newCellRenderer(target.cellEditorParams, params);
                if (cellRendererPromise != null) {
                    this.bindToHtml(cellRendererPromise, eTarget);
                } else {
                    eTarget.innerText = params.valueFormatted != null ? params.valueFormatted : params.value;
                }
                return cellRendererPromise;
            };
            CellRendererService.prototype.useInnerCellRenderer = function(target, originalColumn, eTarget, params) {
                var _this = this;
                var rendererToUsePromise = null;
                var componentToUse = this.componentResolver.getComponentToUse(target, "innerRenderer", null);
                if (componentToUse && componentToUse.component != null && componentToUse.source != componentResolver_1.ComponentSource.DEFAULT) {
                    rendererToUsePromise = this.componentRecipes.newInnerCellRenderer(target, params);
                } else {
                    var otherRenderer = this.componentResolver.getComponentToUse(originalColumn, "cellRenderer", null);
                    if (otherRenderer && otherRenderer.source != componentResolver_1.ComponentSource.DEFAULT) {
                        rendererToUsePromise = this.componentRecipes.newCellRenderer(originalColumn, params);
                    } else if (otherRenderer && otherRenderer.source == componentResolver_1.ComponentSource.DEFAULT && utils_1._.get(originalColumn, "cellRendererParams.innerRenderer", null)) {
                        rendererToUsePromise = this.componentRecipes.newInnerCellRenderer(originalColumn.cellRendererParams, params);
                    } else {
                        rendererToUsePromise = this.componentRecipes.newCellRenderer({}, params);
                    }
                }
                if (rendererToUsePromise != null) {
                    rendererToUsePromise.then(function(rendererToUse) {
                        if (rendererToUse == null) {
                            eTarget.innerText = params.valueFormatted != null ? params.valueFormatted : params.value;
                            return;
                        }
                        _this.bindToHtml(rendererToUsePromise, eTarget);
                    });
                } else {
                    eTarget.innerText = params.valueFormatted != null ? params.valueFormatted : params.value;
                }
                return rendererToUsePromise;
            };
            CellRendererService.prototype.useFullWidthGroupRowInnerCellRenderer = function(eTarget, params) {
                var cellRendererPromise = this.componentRecipes.newFullWidthGroupRowInnerCellRenderer(params);
                if (cellRendererPromise != null) {
                    this.bindToHtml(cellRendererPromise, eTarget);
                } else {
                    eTarget.innerText = params.valueFormatted != null ? params.valueFormatted : params.value;
                }
                return cellRendererPromise;
            };
            CellRendererService.prototype.bindToHtml = function(cellRendererPromise, eTarget) {
                cellRendererPromise.then(function(cellRenderer) {
                    var gui = cellRenderer.getGui();
                    if (gui != null) {
                        if (typeof gui == "object") {
                            eTarget.appendChild(gui);
                        } else {
                            eTarget.innerHTML = gui;
                        }
                    }
                });
                return cellRendererPromise;
            };
            __decorate([ context_1.Autowired("componentRecipes"), __metadata("design:type", componentRecipes_1.ComponentRecipes) ], CellRendererService.prototype, "componentRecipes", void 0);
            __decorate([ context_1.Autowired("componentResolver"), __metadata("design:type", componentResolver_1.ComponentResolver) ], CellRendererService.prototype, "componentResolver", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], CellRendererService.prototype, "gridOptionsWrapper", void 0);
            CellRendererService = __decorate([ context_1.Bean("cellRendererService") ], CellRendererService);
            return CellRendererService;
        }();
        exports.CellRendererService = CellRendererService;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var beanStub_1 = __webpack_require__(13);
        var context_1 = __webpack_require__(0);
        var eventService_1 = __webpack_require__(3);
        var eventKeys_1 = __webpack_require__(25);
        var utils_1 = __webpack_require__(1);
        var HeightScaler = function(_super) {
            __extends(HeightScaler, _super);
            function HeightScaler() {
                var _this = _super !== null && _super.apply(this, arguments) || this;
                _this.scrollY = 0;
                _this.uiBodyHeight = 0;
                return _this;
            }
            HeightScaler.prototype.postConstruct = function() {
                this.addDestroyableEventListener(this.eventService, eventKeys_1.Events.EVENT_BODY_HEIGHT_CHANGED, this.update.bind(this));
                this.scrollBarWidth = utils_1._.getScrollbarWidth();
                this.maxDivHeight = utils_1._.getMaxDivHeight();
            };
            HeightScaler.prototype.registerGridComp = function(gridPanel) {
                this.gridPanel = gridPanel;
            };
            HeightScaler.prototype.isScaling = function() {
                return this.scaling;
            };
            HeightScaler.prototype.getOffset = function() {
                return this.offset;
            };
            HeightScaler.prototype.update = function() {
                if (!this.scaling) {
                    return;
                }
                var newScrollY = this.gridPanel.getVScrollPosition().top;
                var newBodyHeight = this.getUiBodyHeight();
                var atLeastOneChanged = newScrollY !== this.scrollY || newBodyHeight !== this.uiBodyHeight;
                if (atLeastOneChanged) {
                    this.scrollY = newScrollY;
                    this.uiBodyHeight = newBodyHeight;
                    this.calculateOffset();
                }
            };
            HeightScaler.prototype.calculateOffset = function() {
                this.uiContainerHeight = this.maxDivHeight;
                this.pixelsToShave = this.modelHeight - this.uiContainerHeight;
                this.maxScrollY = this.uiContainerHeight - this.uiBodyHeight;
                var scrollPercent = this.scrollY / this.maxScrollY;
                this.setOffset(scrollPercent * this.pixelsToShave);
            };
            HeightScaler.prototype.clearOffset = function() {
                this.uiContainerHeight = this.modelHeight;
                this.pixelsToShave = 0;
                this.setOffset(0);
            };
            HeightScaler.prototype.setOffset = function(newOffset) {
                var newOffsetFloor = typeof newOffset === "number" ? Math.floor(newOffset) : null;
                if (this.offset !== newOffsetFloor) {
                    this.offset = newOffsetFloor;
                    this.eventService.dispatchEvent({
                        type: eventKeys_1.Events.EVENT_HEIGHT_SCALE_CHANGED
                    });
                }
            };
            HeightScaler.prototype.setModelHeight = function(modelHeight) {
                this.modelHeight = modelHeight;
                this.scaling = this.maxDivHeight > 0 && modelHeight > this.maxDivHeight;
                if (this.scaling) {
                    this.calculateOffset();
                } else {
                    this.clearOffset();
                }
            };
            HeightScaler.prototype.getUiContainerHeight = function() {
                return this.uiContainerHeight;
            };
            HeightScaler.prototype.getRealPixelPosition = function(modelPixel) {
                var uiPixel = modelPixel - this.offset;
                return uiPixel;
            };
            HeightScaler.prototype.getUiBodyHeight = function() {
                var pos = this.gridPanel.getVScrollPosition();
                var bodyHeight = pos.bottom - pos.top;
                if (this.gridPanel.isHorizontalScrollShowing()) {
                    bodyHeight -= this.scrollBarWidth;
                }
                return bodyHeight;
            };
            HeightScaler.prototype.getScrollPositionForPixel = function(rowTop) {
                if (this.pixelsToShave <= 0) {
                    return rowTop;
                } else {
                    var modelMaxScroll = this.modelHeight - this.getUiBodyHeight();
                    var scrollPercent = rowTop / modelMaxScroll;
                    var scrollPixel = this.maxScrollY * scrollPercent;
                    return scrollPixel;
                }
            };
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], HeightScaler.prototype, "eventService", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], HeightScaler.prototype, "postConstruct", null);
            HeightScaler = __decorate([ context_1.Bean("heightScaler") ], HeightScaler);
            return HeightScaler;
        }(beanStub_1.BeanStub);
        exports.HeightScaler = HeightScaler;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        var __param = this && this.__param || function(paramIndex, decorator) {
            return function(target, key) {
                decorator(target, key, paramIndex);
            };
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var columnController_1 = __webpack_require__(4);
        var eventService_1 = __webpack_require__(3);
        var logger_1 = __webpack_require__(12);
        var events_1 = __webpack_require__(5);
        var context_1 = __webpack_require__(0);
        var context_2 = __webpack_require__(0);
        var context_3 = __webpack_require__(0);
        var context_4 = __webpack_require__(0);
        var AlignedGridsService = function() {
            function AlignedGridsService() {
                this.consuming = false;
            }
            AlignedGridsService.prototype.setBeans = function(loggerFactory) {
                this.logger = loggerFactory.create("AlignedGridsService");
            };
            AlignedGridsService.prototype.registerGridComp = function(gridPanel) {
                this.gridPanel = gridPanel;
            };
            AlignedGridsService.prototype.init = function() {
                this.eventService.addEventListener(events_1.Events.EVENT_COLUMN_MOVED, this.fireColumnEvent.bind(this));
                this.eventService.addEventListener(events_1.Events.EVENT_COLUMN_VISIBLE, this.fireColumnEvent.bind(this));
                this.eventService.addEventListener(events_1.Events.EVENT_COLUMN_PINNED, this.fireColumnEvent.bind(this));
                this.eventService.addEventListener(events_1.Events.EVENT_COLUMN_GROUP_OPENED, this.fireColumnEvent.bind(this));
                this.eventService.addEventListener(events_1.Events.EVENT_COLUMN_RESIZED, this.fireColumnEvent.bind(this));
                this.eventService.addEventListener(events_1.Events.EVENT_BODY_SCROLL, this.fireScrollEvent.bind(this));
            };
            AlignedGridsService.prototype.fireEvent = function(callback) {
                if (this.consuming) {
                    return;
                }
                var otherGrids = this.gridOptionsWrapper.getAlignedGrids();
                if (otherGrids) {
                    otherGrids.forEach(function(otherGridOptions) {
                        if (otherGridOptions.api) {
                            var alignedGridService = otherGridOptions.api.__getAlignedGridService();
                            callback(alignedGridService);
                        }
                    });
                }
            };
            AlignedGridsService.prototype.onEvent = function(callback) {
                this.consuming = true;
                callback();
                this.consuming = false;
            };
            AlignedGridsService.prototype.fireColumnEvent = function(event) {
                this.fireEvent(function(alignedGridsService) {
                    alignedGridsService.onColumnEvent(event);
                });
            };
            AlignedGridsService.prototype.fireScrollEvent = function(event) {
                if (event.direction !== "horizontal") {
                    return;
                }
                this.fireEvent(function(alignedGridsService) {
                    alignedGridsService.onScrollEvent(event);
                });
            };
            AlignedGridsService.prototype.onScrollEvent = function(event) {
                var _this = this;
                this.onEvent(function() {
                    _this.gridPanel.setHorizontalScrollPosition(event.left);
                });
            };
            AlignedGridsService.prototype.getMasterColumns = function(event) {
                var result = [];
                if (event.columns) {
                    event.columns.forEach(function(column) {
                        result.push(column);
                    });
                } else if (event.column) {
                    result.push(event.column);
                }
                return result;
            };
            AlignedGridsService.prototype.getColumnIds = function(event) {
                var result = [];
                if (event.columns) {
                    event.columns.forEach(function(column) {
                        result.push(column.getColId());
                    });
                } else if (event.columns) {
                    result.push(event.column.getColId());
                }
                return result;
            };
            AlignedGridsService.prototype.onColumnEvent = function(event) {
                var _this = this;
                this.onEvent(function() {
                    switch (event.type) {
                      case events_1.Events.EVENT_COLUMN_MOVED:
                      case events_1.Events.EVENT_COLUMN_VISIBLE:
                      case events_1.Events.EVENT_COLUMN_PINNED:
                      case events_1.Events.EVENT_COLUMN_RESIZED:
                        var colEvent = event;
                        _this.processColumnEvent(colEvent);
                        break;

                      case events_1.Events.EVENT_COLUMN_GROUP_OPENED:
                        var groupOpenedEvent = event;
                        _this.processGroupOpenedEvent(groupOpenedEvent);
                        break;

                      case events_1.Events.EVENT_COLUMN_PIVOT_CHANGED:
                        console.warn("ag-Grid: pivoting is not supported with aligned grids. " + "You can only use one of these features at a time in a grid.");
                        break;
                    }
                });
            };
            AlignedGridsService.prototype.processGroupOpenedEvent = function(groupOpenedEvent) {
                var masterColumnGroup = groupOpenedEvent.columnGroup;
                var otherColumnGroup;
                if (masterColumnGroup) {
                    var groupId = masterColumnGroup.getGroupId();
                    otherColumnGroup = this.columnController.getOriginalColumnGroup(groupId);
                }
                if (masterColumnGroup && !otherColumnGroup) {
                    return;
                }
                this.logger.log("onColumnEvent-> processing " + event + " expanded = " + masterColumnGroup.isExpanded());
                this.columnController.setColumnGroupOpened(otherColumnGroup, masterColumnGroup.isExpanded(), "alignedGridChanged");
            };
            AlignedGridsService.prototype.processColumnEvent = function(colEvent) {
                var _this = this;
                var masterColumn = colEvent.column;
                var otherColumn;
                if (masterColumn) {
                    otherColumn = this.columnController.getPrimaryColumn(masterColumn.getColId());
                }
                if (masterColumn && !otherColumn) {
                    return;
                }
                var columnIds = this.getColumnIds(colEvent);
                var masterColumns = this.getMasterColumns(colEvent);
                switch (colEvent.type) {
                  case events_1.Events.EVENT_COLUMN_MOVED:
                    var movedEvent = colEvent;
                    this.logger.log("onColumnEvent-> processing " + colEvent.type + " toIndex = " + movedEvent.toIndex);
                    this.columnController.moveColumns(columnIds, movedEvent.toIndex, "alignedGridChanged");
                    break;

                  case events_1.Events.EVENT_COLUMN_VISIBLE:
                    var visibleEvent = colEvent;
                    this.logger.log("onColumnEvent-> processing " + colEvent.type + " visible = " + visibleEvent.visible);
                    this.columnController.setColumnsVisible(columnIds, visibleEvent.visible, "alignedGridChanged");
                    break;

                  case events_1.Events.EVENT_COLUMN_PINNED:
                    var pinnedEvent = colEvent;
                    this.logger.log("onColumnEvent-> processing " + colEvent.type + " pinned = " + pinnedEvent.pinned);
                    this.columnController.setColumnsPinned(columnIds, pinnedEvent.pinned, "alignedGridChanged");
                    break;

                  case events_1.Events.EVENT_COLUMN_RESIZED:
                    var resizedEvent_1 = colEvent;
                    masterColumns.forEach(function(masterColumn) {
                        _this.logger.log("onColumnEvent-> processing " + colEvent.type + " actualWidth = " + masterColumn.getActualWidth());
                        _this.columnController.setColumnWidth(masterColumn.getColId(), masterColumn.getActualWidth(), false, resizedEvent_1.finished, "alignedGridChanged");
                    });
                    break;
                }
            };
            __decorate([ context_3.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], AlignedGridsService.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_3.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], AlignedGridsService.prototype, "columnController", void 0);
            __decorate([ context_3.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], AlignedGridsService.prototype, "eventService", void 0);
            __decorate([ __param(0, context_2.Qualifier("loggerFactory")), __metadata("design:type", Function), __metadata("design:paramtypes", [ logger_1.LoggerFactory ]), __metadata("design:returntype", void 0) ], AlignedGridsService.prototype, "setBeans", null);
            __decorate([ context_4.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], AlignedGridsService.prototype, "init", null);
            AlignedGridsService = __decorate([ context_1.Bean("alignedGridsService") ], AlignedGridsService);
            return AlignedGridsService;
        }();
        exports.AlignedGridsService = AlignedGridsService;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var context_1 = __webpack_require__(0);
        var dragService_1 = __webpack_require__(40);
        var HorizontalResizeService = function() {
            function HorizontalResizeService() {}
            HorizontalResizeService.prototype.addResizeBar = function(params) {
                var _this = this;
                var dragSource = {
                    dragStartPixels: 0,
                    eElement: params.eResizeBar,
                    onDragStart: this.onDragStart.bind(this, params),
                    onDragStop: this.onDragStop.bind(this, params),
                    onDragging: this.onDragging.bind(this, params)
                };
                this.dragService.addDragSource(dragSource, true);
                var finishedWithResizeFunc = function() {
                    return _this.dragService.removeDragSource(dragSource);
                };
                return finishedWithResizeFunc;
            };
            HorizontalResizeService.prototype.onDragStart = function(params, mouseEvent) {
                this.draggingStarted = true;
                this.dragStartX = mouseEvent.clientX;
                this.setResizeIcons();
                var shiftKey = mouseEvent instanceof MouseEvent ? mouseEvent.shiftKey === true : false;
                params.onResizeStart(shiftKey);
            };
            HorizontalResizeService.prototype.setResizeIcons = function() {
                this.oldBodyCursor = this.eGridDiv.style.cursor;
                this.oldMsUserSelect = this.eGridDiv.style.msUserSelect;
                this.oldWebkitUserSelect = this.eGridDiv.style.webkitUserSelect;
                this.eGridDiv.style.cursor = "col-resize";
                this.eGridDiv.style.msUserSelect = "none";
                this.eGridDiv.style.webkitUserSelect = "none";
            };
            HorizontalResizeService.prototype.onDragStop = function(params, mouseEvent) {
                params.onResizeEnd(this.resizeAmount);
                this.resetIcons();
            };
            HorizontalResizeService.prototype.resetIcons = function() {
                this.eGridDiv.style.cursor = this.oldBodyCursor;
                this.eGridDiv.style.msUserSelect = this.oldMsUserSelect;
                this.eGridDiv.style.webkitUserSelect = this.oldWebkitUserSelect;
            };
            HorizontalResizeService.prototype.onDragging = function(params, mouseEvent) {
                this.resizeAmount = mouseEvent.clientX - this.dragStartX;
                params.onResizing(this.resizeAmount);
            };
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], HorizontalResizeService.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("dragService"), __metadata("design:type", dragService_1.DragService) ], HorizontalResizeService.prototype, "dragService", void 0);
            __decorate([ context_1.Autowired("eGridDiv"), __metadata("design:type", HTMLElement) ], HorizontalResizeService.prototype, "eGridDiv", void 0);
            HorizontalResizeService = __decorate([ context_1.Bean("horizontalResizeService") ], HorizontalResizeService);
            return HorizontalResizeService;
        }();
        exports.HorizontalResizeService = HorizontalResizeService;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var component_1 = __webpack_require__(8);
        var componentAnnotations_1 = __webpack_require__(11);
        var utils_1 = __webpack_require__(1);
        var context_1 = __webpack_require__(0);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var AgCheckbox = function(_super) {
            __extends(AgCheckbox, _super);
            function AgCheckbox() {
                var _this = _super.call(this) || this;
                _this.selected = false;
                _this.readOnly = false;
                _this.passive = false;
                return _this;
            }
            AgCheckbox.prototype.preConstruct = function() {
                this.setTemplate(AgCheckbox.TEMPLATE);
            };
            AgCheckbox.prototype.postConstruct = function() {
                this.loadIcons();
                this.updateIcons();
                if (this.props.label) {
                    this.eLabel.innerText = this.props.label;
                }
            };
            AgCheckbox.prototype.loadIcons = function() {
                utils_1.Utils.removeAllChildren(this.eChecked);
                utils_1.Utils.removeAllChildren(this.eUnchecked);
                utils_1.Utils.removeAllChildren(this.eIndeterminate);
                if (this.readOnly) {
                    this.eChecked.appendChild(utils_1.Utils.createIconNoSpan("checkboxCheckedReadOnly", this.gridOptionsWrapper, null));
                    this.eUnchecked.appendChild(utils_1.Utils.createIconNoSpan("checkboxUncheckedReadOnly", this.gridOptionsWrapper, null));
                    this.eIndeterminate.appendChild(utils_1.Utils.createIconNoSpan("checkboxIndeterminateReadOnly", this.gridOptionsWrapper, null));
                } else {
                    this.eChecked.appendChild(utils_1.Utils.createIconNoSpan("checkboxChecked", this.gridOptionsWrapper, null));
                    this.eUnchecked.appendChild(utils_1.Utils.createIconNoSpan("checkboxUnchecked", this.gridOptionsWrapper, null));
                    this.eIndeterminate.appendChild(utils_1.Utils.createIconNoSpan("checkboxIndeterminate", this.gridOptionsWrapper, null));
                }
            };
            AgCheckbox.prototype.onClick = function(event) {
                utils_1.Utils.addAgGridEventPath(event);
                if (!this.readOnly) {
                    this.toggle();
                }
            };
            AgCheckbox.prototype.getNextValue = function() {
                if (this.selected === undefined) {
                    return true;
                } else {
                    return !this.selected;
                }
            };
            AgCheckbox.prototype.setPassive = function(passive) {
                this.passive = passive;
            };
            AgCheckbox.prototype.setReadOnly = function(readOnly) {
                this.readOnly = readOnly;
                this.loadIcons();
            };
            AgCheckbox.prototype.isReadOnly = function() {
                return this.readOnly;
            };
            AgCheckbox.prototype.isSelected = function() {
                return this.selected;
            };
            AgCheckbox.prototype.toggle = function() {
                var nextValue = this.getNextValue();
                if (this.passive) {
                    var event_1 = {
                        type: AgCheckbox.EVENT_CHANGED,
                        selected: nextValue
                    };
                    this.dispatchEvent(event_1);
                } else {
                    this.setSelected(nextValue);
                }
            };
            AgCheckbox.prototype.setSelected = function(selected) {
                if (this.selected === selected) {
                    return;
                }
                if (selected === true) {
                    this.selected = true;
                } else if (selected === false) {
                    this.selected = false;
                } else {
                    this.selected = undefined;
                }
                this.updateIcons();
                var event = {
                    type: AgCheckbox.EVENT_CHANGED,
                    selected: this.selected
                };
                this.dispatchEvent(event);
            };
            AgCheckbox.prototype.updateIcons = function() {
                utils_1.Utils.setVisible(this.eChecked, this.selected === true);
                utils_1.Utils.setVisible(this.eUnchecked, this.selected === false);
                utils_1.Utils.setVisible(this.eIndeterminate, this.selected === undefined);
            };
            AgCheckbox.EVENT_CHANGED = "change";
            AgCheckbox.TEMPLATE = '<span class="ag-checkbox" role="presentation">' + '  <span class="ag-checkbox-checked" role="presentation"></span>' + '  <span class="ag-checkbox-unchecked" role="presentation"></span>' + '  <span class="ag-checkbox-indeterminate" role="presentation"></span>' + '  <span class="ag-checkbox-label" role="presentation"></span>' + "</span>";
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], AgCheckbox.prototype, "gridOptionsWrapper", void 0);
            __decorate([ componentAnnotations_1.QuerySelector(".ag-checkbox-checked"), __metadata("design:type", HTMLElement) ], AgCheckbox.prototype, "eChecked", void 0);
            __decorate([ componentAnnotations_1.QuerySelector(".ag-checkbox-unchecked"), __metadata("design:type", HTMLElement) ], AgCheckbox.prototype, "eUnchecked", void 0);
            __decorate([ componentAnnotations_1.QuerySelector(".ag-checkbox-indeterminate"), __metadata("design:type", HTMLElement) ], AgCheckbox.prototype, "eIndeterminate", void 0);
            __decorate([ componentAnnotations_1.QuerySelector(".ag-checkbox-label"), __metadata("design:type", HTMLElement) ], AgCheckbox.prototype, "eLabel", void 0);
            __decorate([ context_1.PreConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], AgCheckbox.prototype, "preConstruct", null);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], AgCheckbox.prototype, "postConstruct", null);
            __decorate([ componentAnnotations_1.Listener("click"), __metadata("design:type", Function), __metadata("design:paramtypes", [ MouseEvent ]), __metadata("design:returntype", void 0) ], AgCheckbox.prototype, "onClick", null);
            return AgCheckbox;
        }(component_1.Component);
        exports.AgCheckbox = AgCheckbox;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var rowNode_1 = __webpack_require__(14);
        var beanStub_1 = __webpack_require__(13);
        var RowNodeBlock = function(_super) {
            __extends(RowNodeBlock, _super);
            function RowNodeBlock(blockNumber, rowNodeCacheParams) {
                var _this = _super.call(this) || this;
                _this.version = 0;
                _this.state = RowNodeBlock.STATE_DIRTY;
                _this.rowNodeCacheParams = rowNodeCacheParams;
                _this.blockNumber = blockNumber;
                _this.startRow = blockNumber * rowNodeCacheParams.blockSize;
                _this.endRow = _this.startRow + rowNodeCacheParams.blockSize;
                return _this;
            }
            RowNodeBlock.prototype.isAnyNodeOpen = function(rowCount) {
                var result = false;
                this.forEachNodeCallback(function(rowNode) {
                    if (rowNode.expanded) {
                        result = true;
                    }
                }, rowCount);
                return result;
            };
            RowNodeBlock.prototype.forEachNodeCallback = function(callback, rowCount) {
                for (var rowIndex = this.startRow; rowIndex < this.endRow; rowIndex++) {
                    if (rowIndex < rowCount) {
                        var rowNode = this.getRowUsingLocalIndex(rowIndex);
                        callback(rowNode, rowIndex);
                    }
                }
            };
            RowNodeBlock.prototype.forEachNode = function(callback, sequence, rowCount, deep) {
                this.forEachNodeCallback(function(rowNode) {
                    callback(rowNode, sequence.next());
                    if (deep && rowNode.childrenCache) {
                        rowNode.childrenCache.forEachNodeDeep(callback, sequence);
                    }
                }, rowCount);
            };
            RowNodeBlock.prototype.forEachNodeDeep = function(callback, sequence, rowCount) {
                this.forEachNode(callback, sequence, rowCount, true);
            };
            RowNodeBlock.prototype.forEachNodeShallow = function(callback, sequence, rowCount) {
                this.forEachNode(callback, sequence, rowCount, false);
            };
            RowNodeBlock.prototype.getVersion = function() {
                return this.version;
            };
            RowNodeBlock.prototype.getLastAccessed = function() {
                return this.lastAccessed;
            };
            RowNodeBlock.prototype.getRowUsingLocalIndex = function(rowIndex, dontTouchLastAccessed) {
                if (dontTouchLastAccessed === void 0) {
                    dontTouchLastAccessed = false;
                }
                if (!dontTouchLastAccessed) {
                    this.lastAccessed = this.rowNodeCacheParams.lastAccessedSequence.next();
                }
                var localIndex = rowIndex - this.startRow;
                return this.rowNodes[localIndex];
            };
            RowNodeBlock.prototype.init = function(beans) {
                this.beans = beans;
                this.createRowNodes();
            };
            RowNodeBlock.prototype.getStartRow = function() {
                return this.startRow;
            };
            RowNodeBlock.prototype.getEndRow = function() {
                return this.endRow;
            };
            RowNodeBlock.prototype.getBlockNumber = function() {
                return this.blockNumber;
            };
            RowNodeBlock.prototype.setDirty = function() {
                this.version++;
                this.state = RowNodeBlock.STATE_DIRTY;
            };
            RowNodeBlock.prototype.setDirtyAndPurge = function() {
                this.setDirty();
                this.rowNodes.forEach(function(rowNode) {
                    rowNode.setData(null);
                });
            };
            RowNodeBlock.prototype.getState = function() {
                return this.state;
            };
            RowNodeBlock.prototype.setRowNode = function(rowIndex, rowNode) {
                var localIndex = rowIndex - this.startRow;
                this.rowNodes[localIndex] = rowNode;
            };
            RowNodeBlock.prototype.setBlankRowNode = function(rowIndex) {
                var localIndex = rowIndex - this.startRow;
                var newRowNode = this.createBlankRowNode(rowIndex);
                this.rowNodes[localIndex] = newRowNode;
                return newRowNode;
            };
            RowNodeBlock.prototype.setNewData = function(rowIndex, dataItem) {
                var newRowNode = this.setBlankRowNode(rowIndex);
                this.setDataAndId(newRowNode, dataItem, this.startRow + rowIndex);
                return newRowNode;
            };
            RowNodeBlock.prototype.createBlankRowNode = function(rowIndex) {
                var rowNode = new rowNode_1.RowNode();
                this.beans.context.wireBean(rowNode);
                rowNode.setRowHeight(this.rowNodeCacheParams.rowHeight);
                return rowNode;
            };
            RowNodeBlock.prototype.createRowNodes = function() {
                this.rowNodes = [];
                for (var i = 0; i < this.rowNodeCacheParams.blockSize; i++) {
                    var rowIndex = this.startRow + i;
                    var rowNode = this.createBlankRowNode(rowIndex);
                    this.rowNodes.push(rowNode);
                }
            };
            RowNodeBlock.prototype.load = function() {
                this.state = RowNodeBlock.STATE_LOADING;
                this.loadFromDatasource();
            };
            RowNodeBlock.prototype.pageLoadFailed = function() {
                this.state = RowNodeBlock.STATE_FAILED;
                var event = {
                    type: RowNodeBlock.EVENT_LOAD_COMPLETE,
                    success: false,
                    page: this,
                    lastRow: null
                };
                this.dispatchEvent(event);
            };
            RowNodeBlock.prototype.populateWithRowData = function(rows) {
                var _this = this;
                var rowNodesToRefresh = [];
                this.rowNodes.forEach(function(rowNode, index) {
                    var data = rows[index];
                    if (rowNode.stub) {
                        rowNodesToRefresh.push(rowNode);
                    }
                    _this.setDataAndId(rowNode, data, _this.startRow + index);
                });
                if (rowNodesToRefresh.length > 0) {
                    this.beans.rowRenderer.redrawRows(rowNodesToRefresh);
                }
            };
            RowNodeBlock.prototype.destroy = function() {
                _super.prototype.destroy.call(this);
                this.rowNodes.forEach(function(rowNode) {
                    if (rowNode.childrenCache) {
                        rowNode.childrenCache.destroy();
                        rowNode.childrenCache = null;
                    }
                    rowNode.clearRowTop();
                });
            };
            RowNodeBlock.prototype.pageLoaded = function(version, rows, lastRow) {
                if (version === this.version) {
                    this.state = RowNodeBlock.STATE_LOADED;
                    this.populateWithRowData(rows);
                }
                lastRow = utils_1.Utils.cleanNumber(lastRow);
                var event = {
                    type: RowNodeBlock.EVENT_LOAD_COMPLETE,
                    success: true,
                    page: this,
                    lastRow: lastRow
                };
                this.dispatchEvent(event);
            };
            RowNodeBlock.EVENT_LOAD_COMPLETE = "loadComplete";
            RowNodeBlock.STATE_DIRTY = "dirty";
            RowNodeBlock.STATE_LOADING = "loading";
            RowNodeBlock.STATE_LOADED = "loaded";
            RowNodeBlock.STATE_FAILED = "failed";
            return RowNodeBlock;
        }(beanStub_1.BeanStub);
        exports.RowNodeBlock = RowNodeBlock;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var events_1 = __webpack_require__(5);
        var propertyKeys_1 = __webpack_require__(90);
        var utils_1 = __webpack_require__(1);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var ComponentUtil = function() {
            function ComponentUtil() {}
            ComponentUtil.getEventCallbacks = function() {
                if (!ComponentUtil.EVENT_CALLBACKS) {
                    ComponentUtil.EVENT_CALLBACKS = [];
                    ComponentUtil.EVENT_CALLBACKS_NO_PREFIX = [];
                    ComponentUtil.EVENTS.forEach(function(eventName) {
                        ComponentUtil.EVENT_CALLBACKS.push(ComponentUtil.getCallbackForEvent(eventName));
                        ComponentUtil.EVENT_CALLBACKS_NO_PREFIX.push(eventName);
                    });
                }
                return ComponentUtil.EVENT_CALLBACKS;
            };
            ComponentUtil.copyAttributesToGridOptions = function(gridOptions, component, skipEventDeprecationCheck) {
                if (skipEventDeprecationCheck === void 0) {
                    skipEventDeprecationCheck = false;
                }
                checkForDeprecated(component);
                if (typeof gridOptions !== "object") {
                    gridOptions = {};
                }
                var pGridOptions = gridOptions;
                ComponentUtil.ARRAY_PROPERTIES.concat(ComponentUtil.STRING_PROPERTIES).concat(ComponentUtil.OBJECT_PROPERTIES).concat(ComponentUtil.FUNCTION_PROPERTIES).forEach(function(key) {
                    if (typeof component[key] !== "undefined") {
                        pGridOptions[key] = component[key];
                    }
                });
                ComponentUtil.BOOLEAN_PROPERTIES.forEach(function(key) {
                    if (typeof component[key] !== "undefined") {
                        pGridOptions[key] = ComponentUtil.toBoolean(component[key]);
                    }
                });
                ComponentUtil.NUMBER_PROPERTIES.forEach(function(key) {
                    if (typeof component[key] !== "undefined") {
                        pGridOptions[key] = ComponentUtil.toNumber(component[key]);
                    }
                });
                ComponentUtil.getEventCallbacks().forEach(function(funcName) {
                    if (typeof component[funcName] !== "undefined") {
                        pGridOptions[funcName] = component[funcName];
                    }
                });
                if (!skipEventDeprecationCheck) {
                    ComponentUtil.EVENT_CALLBACKS_NO_PREFIX.forEach(function(funcName) {
                        var onMethodName = ComponentUtil.getCallbackForEvent(funcName);
                        if (typeof component[funcName] !== "undefined" || typeof component[onMethodName] !== "undefined") {
                            gridOptionsWrapper_1.GridOptionsWrapper.checkEventDeprecation(funcName);
                        }
                    });
                }
                return gridOptions;
            };
            ComponentUtil.getCallbackForEvent = function(eventName) {
                if (!eventName || eventName.length < 2) {
                    return eventName;
                } else {
                    return "on" + eventName[0].toUpperCase() + eventName.substr(1);
                }
            };
            ComponentUtil.processOnChange = function(changes, gridOptions, api, columnApi) {
                if (!changes) {
                    return;
                }
                checkForDeprecated(changes);
                var pGridOptions = gridOptions;
                ComponentUtil.ARRAY_PROPERTIES.concat(ComponentUtil.OBJECT_PROPERTIES).concat(ComponentUtil.STRING_PROPERTIES).forEach(function(key) {
                    if (changes[key]) {
                        pGridOptions[key] = changes[key].currentValue;
                    }
                });
                ComponentUtil.BOOLEAN_PROPERTIES.forEach(function(key) {
                    if (changes[key]) {
                        pGridOptions[key] = ComponentUtil.toBoolean(changes[key].currentValue);
                    }
                });
                ComponentUtil.NUMBER_PROPERTIES.forEach(function(key) {
                    if (changes[key]) {
                        pGridOptions[key] = ComponentUtil.toNumber(changes[key].currentValue);
                    }
                });
                ComponentUtil.getEventCallbacks().forEach(function(funcName) {
                    if (changes[funcName]) {
                        pGridOptions[funcName] = changes[funcName].currentValue;
                    }
                });
                if (changes.showToolPanel) {
                    api.showToolPanel(ComponentUtil.toBoolean(changes.showToolPanel.currentValue));
                }
                if (changes.quickFilterText) {
                    api.setQuickFilter(changes.quickFilterText.currentValue);
                }
                if (changes.rowData) {
                    api.setRowData(changes.rowData.currentValue);
                }
                if (changes.pinnedTopRowData) {
                    api.setPinnedTopRowData(changes.pinnedTopRowData.currentValue);
                }
                if (changes.pinnedBottomRowData) {
                    api.setPinnedBottomRowData(changes.pinnedBottomRowData.currentValue);
                }
                if (changes.columnDefs) {
                    api.setColumnDefs(changes.columnDefs.currentValue, "gridOptionsChanged");
                }
                if (changes.datasource) {
                    api.setDatasource(changes.datasource.currentValue);
                }
                if (changes.headerHeight) {
                    api.setHeaderHeight(ComponentUtil.toNumber(changes.headerHeight.currentValue));
                }
                if (changes.paginationPageSize) {
                    api.paginationSetPageSize(ComponentUtil.toNumber(changes.paginationPageSize.currentValue));
                }
                if (changes.pivotMode) {
                    columnApi.setPivotMode(ComponentUtil.toBoolean(changes.pivotMode.currentValue));
                }
                if (changes.groupRemoveSingleChildren) {
                    api.setGroupRemoveSingleChildren(ComponentUtil.toBoolean(changes.groupRemoveSingleChildren.currentValue));
                }
                if (changes.suppressRowDrag) {
                    api.setSuppressRowDrag(ComponentUtil.toBoolean(changes.suppressRowDrag.currentValue));
                }
                if (changes.gridAutoHeight) {
                    api.setGridAutoHeight(ComponentUtil.toBoolean(changes.gridAutoHeight.currentValue));
                }
                if (changes.suppressClipboardPaste) {
                    api.setSuppressClipboardPaste(ComponentUtil.toBoolean(changes.suppressClipboardPaste.currentValue));
                }
                var event = {
                    type: events_1.Events.EVENT_COMPONENT_STATE_CHANGED,
                    api: gridOptions.api,
                    columnApi: gridOptions.columnApi
                };
                utils_1.Utils.iterateObject(changes, function(key, value) {
                    event[key] = value;
                });
                api.dispatchEvent(event);
            };
            ComponentUtil.toBoolean = function(value) {
                if (typeof value === "boolean") {
                    return value;
                } else if (typeof value === "string") {
                    return value.toUpperCase() === "TRUE" || value == "";
                } else {
                    return false;
                }
            };
            ComponentUtil.toNumber = function(value) {
                if (typeof value === "number") {
                    return value;
                } else if (typeof value === "string") {
                    return Number(value);
                } else {
                    return undefined;
                }
            };
            ComponentUtil.EVENTS = [];
            ComponentUtil.STRING_PROPERTIES = propertyKeys_1.PropertyKeys.STRING_PROPERTIES;
            ComponentUtil.OBJECT_PROPERTIES = propertyKeys_1.PropertyKeys.OBJECT_PROPERTIES;
            ComponentUtil.ARRAY_PROPERTIES = propertyKeys_1.PropertyKeys.ARRAY_PROPERTIES;
            ComponentUtil.NUMBER_PROPERTIES = propertyKeys_1.PropertyKeys.NUMBER_PROPERTIES;
            ComponentUtil.BOOLEAN_PROPERTIES = propertyKeys_1.PropertyKeys.BOOLEAN_PROPERTIES;
            ComponentUtil.FUNCTION_PROPERTIES = propertyKeys_1.PropertyKeys.FUNCTION_PROPERTIES;
            ComponentUtil.ALL_PROPERTIES = propertyKeys_1.PropertyKeys.ALL_PROPERTIES;
            return ComponentUtil;
        }();
        exports.ComponentUtil = ComponentUtil;
        utils_1.Utils.iterateObject(events_1.Events, function(key, value) {
            ComponentUtil.EVENTS.push(value);
        });
        function checkForDeprecated(changes) {
            if (changes.rowDeselected || changes.onRowDeselected) {
                console.warn("ag-grid: as of v3.4 rowDeselected no longer exists. Please check the docs.");
            }
        }
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var columnController_1 = __webpack_require__(4);
        var constants_1 = __webpack_require__(9);
        var utils_1 = __webpack_require__(1);
        var selectionController_1 = __webpack_require__(17);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var displayedGroupCreator_1 = __webpack_require__(48);
        var balancedColumnTreeBuilder_1 = __webpack_require__(38);
        var groupInstanceIdCreator_1 = __webpack_require__(83);
        var columnGroup_1 = __webpack_require__(26);
        var pinnedRowModel_1 = __webpack_require__(30);
        var BaseGridSerializingSession = function() {
            function BaseGridSerializingSession(columnController, valueService, gridOptionsWrapper, processCellCallback, processHeaderCallback, cellAndHeaderEscaper) {
                this.columnController = columnController;
                this.valueService = valueService;
                this.gridOptionsWrapper = gridOptionsWrapper;
                this.processCellCallback = processCellCallback;
                this.processHeaderCallback = processHeaderCallback;
                this.cellAndHeaderEscaper = cellAndHeaderEscaper;
            }
            BaseGridSerializingSession.prototype.extractHeaderValue = function(column) {
                var nameForCol = this.getHeaderName(this.processHeaderCallback, column);
                if (nameForCol === null || nameForCol === undefined) {
                    nameForCol = "";
                }
                return this.cellAndHeaderEscaper ? this.cellAndHeaderEscaper(nameForCol) : nameForCol;
            };
            BaseGridSerializingSession.prototype.extractRowCellValue = function(column, index, type, node) {
                var isRowGrouping = this.columnController.getRowGroupColumns().length > 0;
                var valueForCell;
                if (node.group && isRowGrouping && index === 0) {
                    valueForCell = this.createValueForGroupNode(node);
                } else {
                    valueForCell = this.valueService.getValue(column, node);
                }
                valueForCell = this.processCell(node, column, valueForCell, this.processCellCallback, type);
                if (valueForCell === null || valueForCell === undefined) {
                    valueForCell = "";
                }
                return this.cellAndHeaderEscaper ? this.cellAndHeaderEscaper(valueForCell) : valueForCell;
            };
            BaseGridSerializingSession.prototype.getHeaderName = function(callback, column) {
                if (callback) {
                    return callback({
                        column: column,
                        api: this.gridOptionsWrapper.getApi(),
                        columnApi: this.gridOptionsWrapper.getColumnApi(),
                        context: this.gridOptionsWrapper.getContext()
                    });
                } else {
                    return this.columnController.getDisplayNameForColumn(column, "csv", true);
                }
            };
            BaseGridSerializingSession.prototype.createValueForGroupNode = function(node) {
                var keys = [ node.key ];
                while (node.parent) {
                    node = node.parent;
                    keys.push(node.key);
                }
                return keys.reverse().join(" -> ");
            };
            BaseGridSerializingSession.prototype.processCell = function(rowNode, column, value, processCellCallback, type) {
                if (processCellCallback) {
                    return processCellCallback({
                        column: column,
                        node: rowNode,
                        value: value,
                        api: this.gridOptionsWrapper.getApi(),
                        columnApi: this.gridOptionsWrapper.getColumnApi(),
                        context: this.gridOptionsWrapper.getContext(),
                        type: type
                    });
                } else {
                    return value;
                }
            };
            return BaseGridSerializingSession;
        }();
        exports.BaseGridSerializingSession = BaseGridSerializingSession;
        var GridSerializer = function() {
            function GridSerializer() {}
            GridSerializer.prototype.serialize = function(gridSerializingSession, params) {
                var dontSkipRows = function() {
                    return false;
                };
                var skipGroups = params && params.skipGroups;
                var skipHeader = params && params.skipHeader;
                var columnGroups = params && params.columnGroups;
                var skipFooters = params && params.skipFooters;
                var skipPinnedTop = params && params.skipPinnedTop;
                var skipPinnedBottom = params && params.skipPinnedBottom;
                var includeCustomHeader = params && params.customHeader;
                var includeCustomFooter = params && params.customFooter;
                var allColumns = params && params.allColumns;
                var onlySelected = params && params.onlySelected;
                var columnKeys = params && params.columnKeys;
                var onlySelectedAllPages = params && params.onlySelectedAllPages;
                var rowSkipper = params && params.shouldRowBeSkipped || dontSkipRows;
                var api = this.gridOptionsWrapper.getApi();
                var context = this.gridOptionsWrapper.getContext();
                var isPivotMode = this.columnController.isPivotMode();
                var rowModelNormal = this.rowModel.getType() === constants_1.Constants.ROW_MODEL_TYPE_CLIENT_SIDE;
                var onlySelectedNonStandardModel = !rowModelNormal && onlySelected;
                var columnsToExport;
                if (utils_1.Utils.existsAndNotEmpty(columnKeys)) {
                    columnsToExport = this.columnController.getGridColumns(columnKeys);
                } else if (allColumns && !isPivotMode) {
                    columnsToExport = this.columnController.getAllPrimaryColumns();
                } else {
                    columnsToExport = this.columnController.getAllDisplayedColumns();
                }
                if (!columnsToExport || columnsToExport.length === 0) {
                    return "";
                }
                gridSerializingSession.prepare(columnsToExport);
                if (includeCustomHeader) {
                    gridSerializingSession.addCustomHeader(params.customHeader);
                }
                if (columnGroups) {
                    var groupInstanceIdCreator = new groupInstanceIdCreator_1.GroupInstanceIdCreator();
                    var displayedGroups = this.displayedGroupCreator.createDisplayedGroups(columnsToExport, this.columnController.getGridBalancedTree(), groupInstanceIdCreator);
                    this.recursivelyAddHeaderGroups(displayedGroups, gridSerializingSession);
                }
                if (!skipHeader) {
                    var gridRowIterator_1 = gridSerializingSession.onNewHeaderRow();
                    columnsToExport.forEach(function(column, index) {
                        gridRowIterator_1.onColumn(column, index, null);
                    });
                }
                this.pinnedRowModel.forEachPinnedTopRow(processRow);
                if (isPivotMode) {
                    if (this.rowModel.forEachPivotNode) {
                        this.rowModel.forEachPivotNode(processRow);
                    } else {
                        this.rowModel.forEachNode(processRow);
                    }
                } else {
                    if (onlySelectedAllPages || onlySelectedNonStandardModel) {
                        var selectedNodes = this.selectionController.getSelectedNodes();
                        selectedNodes.forEach(function(node) {
                            processRow(node);
                        });
                    } else {
                        if (rowModelNormal) {
                            this.rowModel.forEachNodeAfterFilterAndSort(processRow);
                        } else {
                            this.rowModel.forEachNode(processRow);
                        }
                    }
                }
                this.pinnedRowModel.forEachPinnedBottomRow(processRow);
                if (includeCustomFooter) {
                    gridSerializingSession.addCustomFooter(params.customFooter);
                }
                function processRow(node) {
                    if (skipGroups && node.group) {
                        return;
                    }
                    if (skipFooters && node.footer) {
                        return;
                    }
                    if (onlySelected && !node.isSelected()) {
                        return;
                    }
                    if (skipPinnedTop && node.rowPinned === "top") {
                        return;
                    }
                    if (skipPinnedBottom && node.rowPinned === "bottom") {
                        return;
                    }
                    var nodeIsRootNode = node.level === -1;
                    if (nodeIsRootNode && !node.leafGroup) {
                        return;
                    }
                    var shouldRowBeSkipped = rowSkipper({
                        node: node,
                        api: api,
                        context: context
                    });
                    if (shouldRowBeSkipped) return;
                    var rowAccumulator = gridSerializingSession.onNewBodyRow();
                    columnsToExport.forEach(function(column, index) {
                        rowAccumulator.onColumn(column, index, node);
                    });
                }
                return gridSerializingSession.parse();
            };
            GridSerializer.prototype.recursivelyAddHeaderGroups = function(displayedGroups, gridSerializingSession) {
                var directChildrenHeaderGroups = [];
                displayedGroups.forEach(function(columnGroupChild) {
                    var columnGroup = columnGroupChild;
                    if (!columnGroup.getChildren) return;
                    columnGroup.getChildren().forEach(function(it) {
                        return directChildrenHeaderGroups.push(it);
                    });
                });
                if (displayedGroups.length > 0 && displayedGroups[0] instanceof columnGroup_1.ColumnGroup) {
                    this.doAddHeaderHeader(gridSerializingSession, displayedGroups);
                }
                if (directChildrenHeaderGroups && directChildrenHeaderGroups.length > 0) {
                    this.recursivelyAddHeaderGroups(directChildrenHeaderGroups, gridSerializingSession);
                }
            };
            GridSerializer.prototype.doAddHeaderHeader = function(gridSerializingSession, displayedGroups) {
                var _this = this;
                var gridRowIterator = gridSerializingSession.onNewHeaderGroupingRow();
                var columnIndex = 0;
                displayedGroups.forEach(function(columnGroupChild) {
                    var columnGroup = columnGroupChild;
                    var colDef = columnGroup.getDefinition();
                    var columnName = _this.columnController.getDisplayNameForColumnGroup(columnGroup, "header");
                    gridRowIterator.onColumn(columnName, columnIndex++, columnGroup.getLeafColumns().length - 1);
                });
            };
            __decorate([ context_1.Autowired("displayedGroupCreator"), __metadata("design:type", displayedGroupCreator_1.DisplayedGroupCreator) ], GridSerializer.prototype, "displayedGroupCreator", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], GridSerializer.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("rowModel"), __metadata("design:type", Object) ], GridSerializer.prototype, "rowModel", void 0);
            __decorate([ context_1.Autowired("pinnedRowModel"), __metadata("design:type", pinnedRowModel_1.PinnedRowModel) ], GridSerializer.prototype, "pinnedRowModel", void 0);
            __decorate([ context_1.Autowired("selectionController"), __metadata("design:type", selectionController_1.SelectionController) ], GridSerializer.prototype, "selectionController", void 0);
            __decorate([ context_1.Autowired("balancedColumnTreeBuilder"), __metadata("design:type", balancedColumnTreeBuilder_1.BalancedColumnTreeBuilder) ], GridSerializer.prototype, "balancedColumnTreeBuilder", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], GridSerializer.prototype, "gridOptionsWrapper", void 0);
            GridSerializer = __decorate([ context_1.Bean("gridSerializer") ], GridSerializer);
            return GridSerializer;
        }();
        exports.GridSerializer = GridSerializer;
        var RowType;
        (function(RowType) {
            RowType[RowType["HEADER_GROUPING"] = 0] = "HEADER_GROUPING";
            RowType[RowType["HEADER"] = 1] = "HEADER";
            RowType[RowType["BODY"] = 2] = "BODY";
        })(RowType = exports.RowType || (exports.RowType = {}));
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var constants_1 = __webpack_require__(9);
        var utils_1 = __webpack_require__(1);
        var gridCell_1 = __webpack_require__(23);
        var GridRow = function() {
            function GridRow(rowIndex, floating) {
                this.rowIndex = rowIndex;
                this.floating = utils_1.Utils.makeNull(floating);
            }
            GridRow.prototype.isFloatingTop = function() {
                return this.floating === constants_1.Constants.PINNED_TOP;
            };
            GridRow.prototype.isFloatingBottom = function() {
                return this.floating === constants_1.Constants.PINNED_BOTTOM;
            };
            GridRow.prototype.isNotFloating = function() {
                return !this.isFloatingBottom() && !this.isFloatingTop();
            };
            GridRow.prototype.equals = function(otherSelection) {
                return this.rowIndex === otherSelection.rowIndex && this.floating === otherSelection.floating;
            };
            GridRow.prototype.toString = function() {
                return "rowIndex = " + this.rowIndex + ", floating = " + this.floating;
            };
            GridRow.prototype.getGridCell = function(column) {
                var gridCellDef = {
                    rowIndex: this.rowIndex,
                    floating: this.floating,
                    column: column
                };
                return new gridCell_1.GridCell(gridCellDef);
            };
            GridRow.prototype.before = function(otherSelection) {
                var otherFloating = otherSelection.floating;
                switch (this.floating) {
                  case constants_1.Constants.PINNED_TOP:
                    if (otherFloating !== constants_1.Constants.PINNED_TOP) {
                        return true;
                    }
                    break;

                  case constants_1.Constants.PINNED_BOTTOM:
                    if (otherFloating !== constants_1.Constants.PINNED_BOTTOM) {
                        return false;
                    }
                    break;

                  default:
                    if (utils_1.Utils.exists(otherFloating)) {
                        if (otherFloating === constants_1.Constants.PINNED_TOP) {
                            return false;
                        } else {
                            return true;
                        }
                    }
                    break;
                }
                return this.rowIndex < otherSelection.rowIndex;
            };
            return GridRow;
        }();
        exports.GridRow = GridRow;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var component_1 = __webpack_require__(8);
        var rowNode_1 = __webpack_require__(14);
        var utils_1 = __webpack_require__(1);
        var context_1 = __webpack_require__(0);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var events_1 = __webpack_require__(5);
        var eventService_1 = __webpack_require__(3);
        var gridApi_1 = __webpack_require__(6);
        var columnApi_1 = __webpack_require__(7);
        var CheckboxSelectionComponent = function(_super) {
            __extends(CheckboxSelectionComponent, _super);
            function CheckboxSelectionComponent() {
                return _super.call(this, '<span class="ag-selection-checkbox"/>') || this;
            }
            CheckboxSelectionComponent.prototype.createAndAddIcons = function() {
                this.eCheckedIcon = utils_1.Utils.createIconNoSpan("checkboxChecked", this.gridOptionsWrapper, this.column);
                this.eUncheckedIcon = utils_1.Utils.createIconNoSpan("checkboxUnchecked", this.gridOptionsWrapper, this.column);
                this.eIndeterminateIcon = utils_1.Utils.createIconNoSpan("checkboxIndeterminate", this.gridOptionsWrapper, this.column);
                var element = this.getGui();
                element.appendChild(this.eCheckedIcon);
                element.appendChild(this.eUncheckedIcon);
                element.appendChild(this.eIndeterminateIcon);
            };
            CheckboxSelectionComponent.prototype.onDataChanged = function() {
                this.onSelectionChanged();
            };
            CheckboxSelectionComponent.prototype.onSelectableChanged = function() {
                this.showOrHideSelect();
            };
            CheckboxSelectionComponent.prototype.onSelectionChanged = function() {
                var state = this.rowNode.isSelected();
                utils_1.Utils.setVisible(this.eCheckedIcon, state === true);
                utils_1.Utils.setVisible(this.eUncheckedIcon, state === false);
                utils_1.Utils.setVisible(this.eIndeterminateIcon, typeof state !== "boolean");
            };
            CheckboxSelectionComponent.prototype.onCheckedClicked = function() {
                var groupSelectsFiltered = this.gridOptionsWrapper.isGroupSelectsFiltered();
                var updatedCount = this.rowNode.setSelectedParams({
                    newValue: false,
                    groupSelectsFiltered: groupSelectsFiltered
                });
                return updatedCount;
            };
            CheckboxSelectionComponent.prototype.onUncheckedClicked = function(event) {
                var groupSelectsFiltered = this.gridOptionsWrapper.isGroupSelectsFiltered();
                var updatedCount = this.rowNode.setSelectedParams({
                    newValue: true,
                    rangeSelect: event.shiftKey,
                    groupSelectsFiltered: groupSelectsFiltered
                });
                return updatedCount;
            };
            CheckboxSelectionComponent.prototype.onIndeterminateClicked = function(event) {
                var result = this.onUncheckedClicked(event);
                if (result === 0) {
                    this.onCheckedClicked();
                }
            };
            CheckboxSelectionComponent.prototype.init = function(params) {
                this.rowNode = params.rowNode;
                this.column = params.column;
                this.createAndAddIcons();
                this.onSelectionChanged();
                this.addGuiEventListener("click", function(event) {
                    return utils_1.Utils.stopPropagationForAgGrid(event);
                });
                this.addGuiEventListener("dblclick", function(event) {
                    return utils_1.Utils.stopPropagationForAgGrid(event);
                });
                this.addDestroyableEventListener(this.eCheckedIcon, "click", this.onCheckedClicked.bind(this));
                this.addDestroyableEventListener(this.eUncheckedIcon, "click", this.onUncheckedClicked.bind(this));
                this.addDestroyableEventListener(this.eIndeterminateIcon, "click", this.onIndeterminateClicked.bind(this));
                this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_ROW_SELECTED, this.onSelectionChanged.bind(this));
                this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_DATA_CHANGED, this.onDataChanged.bind(this));
                this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_SELECTABLE_CHANGED, this.onSelectableChanged.bind(this));
                this.isRowSelectableFunc = this.gridOptionsWrapper.getIsRowSelectableFunc();
                var checkboxVisibleIsDynamic = this.isRowSelectableFunc || this.checkboxCallbackExists();
                if (checkboxVisibleIsDynamic) {
                    this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_DISPLAYED_COLUMNS_CHANGED, this.showOrHideSelect.bind(this));
                    this.showOrHideSelect();
                }
            };
            CheckboxSelectionComponent.prototype.showOrHideSelect = function() {
                var selectable = this.rowNode.selectable;
                if (selectable && this.checkboxCallbackExists()) {
                    selectable = this.column.isCellCheckboxSelection(this.rowNode);
                }
                this.setVisible(selectable);
            };
            CheckboxSelectionComponent.prototype.checkboxCallbackExists = function() {
                var colDef = this.column ? this.column.getColDef() : null;
                return colDef && typeof colDef.checkboxSelection === "function";
            };
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], CheckboxSelectionComponent.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], CheckboxSelectionComponent.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], CheckboxSelectionComponent.prototype, "gridApi", void 0);
            __decorate([ context_1.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], CheckboxSelectionComponent.prototype, "columnApi", void 0);
            return CheckboxSelectionComponent;
        }(component_1.Component);
        exports.CheckboxSelectionComponent = CheckboxSelectionComponent;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var textCellEditor_1 = __webpack_require__(67);
        var context_1 = __webpack_require__(0);
        var dateFilter_1 = __webpack_require__(68);
        var headerComp_1 = __webpack_require__(125);
        var headerGroupComp_1 = __webpack_require__(126);
        var floatingFilter_1 = __webpack_require__(91);
        var componentResolver_1 = __webpack_require__(27);
        var groupCellRenderer_1 = __webpack_require__(72);
        var animateShowChangeCellRenderer_1 = __webpack_require__(71);
        var animateSlideCellRenderer_1 = __webpack_require__(70);
        var rowComp_1 = __webpack_require__(50);
        var selectCellEditor_1 = __webpack_require__(75);
        var popupTextCellEditor_1 = __webpack_require__(92);
        var popupSelectCellEditor_1 = __webpack_require__(93);
        var largeTextCellEditor_1 = __webpack_require__(94);
        var textFilter_1 = __webpack_require__(95);
        var numberFilter_1 = __webpack_require__(96);
        var loadingOverlayComponent_1 = __webpack_require__(127);
        var noRowsOverlayComponent_1 = __webpack_require__(128);
        var utils_1 = __webpack_require__(1);
        var RegisteredComponentSource;
        (function(RegisteredComponentSource) {
            RegisteredComponentSource[RegisteredComponentSource["DEFAULT"] = 0] = "DEFAULT";
            RegisteredComponentSource[RegisteredComponentSource["REGISTERED"] = 1] = "REGISTERED";
        })(RegisteredComponentSource = exports.RegisteredComponentSource || (exports.RegisteredComponentSource = {}));
        var ComponentProvider = function() {
            function ComponentProvider() {
                this.agGridDefaults = {
                    agDateInput: dateFilter_1.DefaultDateComponent,
                    agColumnHeader: headerComp_1.HeaderComp,
                    agColumnGroupHeader: headerGroupComp_1.HeaderGroupComp,
                    agSetColumnFloatingFilter: floatingFilter_1.SetFloatingFilterComp,
                    agTextColumnFloatingFilter: floatingFilter_1.TextFloatingFilterComp,
                    agNumberColumnFloatingFilter: floatingFilter_1.NumberFloatingFilterComp,
                    agDateColumnFloatingFilter: floatingFilter_1.DateFloatingFilterComp,
                    agAnimateShowChangeCellRenderer: animateShowChangeCellRenderer_1.AnimateShowChangeCellRenderer,
                    agAnimateSlideCellRenderer: animateSlideCellRenderer_1.AnimateSlideCellRenderer,
                    agGroupCellRenderer: groupCellRenderer_1.GroupCellRenderer,
                    agGroupRowRenderer: groupCellRenderer_1.GroupCellRenderer,
                    agLoadingCellRenderer: rowComp_1.LoadingCellRenderer,
                    agCellEditor: textCellEditor_1.TextCellEditor,
                    agTextCellEditor: textCellEditor_1.TextCellEditor,
                    agSelectCellEditor: selectCellEditor_1.SelectCellEditor,
                    agPopupTextCellEditor: popupTextCellEditor_1.PopupTextCellEditor,
                    agPopupSelectCellEditor: popupSelectCellEditor_1.PopupSelectCellEditor,
                    agLargeTextCellEditor: largeTextCellEditor_1.LargeTextCellEditor,
                    agTextColumnFilter: textFilter_1.TextFilter,
                    agNumberColumnFilter: numberFilter_1.NumberFilter,
                    agDateColumnFilter: dateFilter_1.DateFilter,
                    agLoadingOverlay: loadingOverlayComponent_1.LoadingOverlayComponent,
                    agNoRowsOverlay: noRowsOverlayComponent_1.NoRowsOverlayComponent
                };
                this.agDeprecatedNames = {
                    set: {
                        newComponentName: "agSetColumnFilter",
                        propertyHolder: "filter"
                    },
                    text: {
                        newComponentName: "agTextColumnFilter",
                        propertyHolder: "filter"
                    },
                    number: {
                        newComponentName: "agNumberColumnFilter",
                        propertyHolder: "filter"
                    },
                    date: {
                        newComponentName: "agDateColumnFilter",
                        propertyHolder: "filter"
                    },
                    group: {
                        newComponentName: "agGroupCellRenderer",
                        propertyHolder: "cellRenderer"
                    },
                    animateShowChange: {
                        newComponentName: "agAnimateShowChangeCellRenderer",
                        propertyHolder: "cellRenderer"
                    },
                    animateSlide: {
                        newComponentName: "agAnimateSlideCellRenderer",
                        propertyHolder: "cellRenderer"
                    },
                    select: {
                        newComponentName: "agSelectCellEditor",
                        propertyHolder: "cellEditor"
                    },
                    largeText: {
                        newComponentName: "agLargeTextCellEditor",
                        propertyHolder: "cellEditor"
                    },
                    popupSelect: {
                        newComponentName: "agPopupSelectCellEditor",
                        propertyHolder: "cellEditor"
                    },
                    popupText: {
                        newComponentName: "agPopupTextCellEditor",
                        propertyHolder: "cellEditor"
                    },
                    richSelect: {
                        newComponentName: "agRichSelectCellEditor",
                        propertyHolder: "cellEditor"
                    },
                    headerComponent: {
                        newComponentName: "agColumnHeader",
                        propertyHolder: "headerComponent"
                    }
                };
                this.jsComponents = {};
                this.frameworkComponents = {};
            }
            ComponentProvider.prototype.init = function() {
                var _this = this;
                if (this.gridOptions.components != null) {
                    Object.keys(this.gridOptions.components).forEach(function(it) {
                        _this.registerComponent(it, _this.gridOptions.components[it]);
                    });
                }
                if (this.gridOptions.frameworkComponents != null) {
                    Object.keys(this.gridOptions.frameworkComponents).forEach(function(it) {
                        _this.registerFwComponent(it, _this.gridOptions.frameworkComponents[it]);
                    });
                }
            };
            ComponentProvider.prototype.registerDefaultComponent = function(rawName, component, overridable) {
                if (overridable === void 0) {
                    overridable = true;
                }
                var name = this.translateIfDeprecated(rawName);
                if (this.agGridDefaults[name]) {
                    console.error("Trying to overwrite a default component. You should call registerComponent");
                    return;
                }
                this.agGridDefaults[name] = component;
            };
            ComponentProvider.prototype.registerComponent = function(rawName, component) {
                var name = this.translateIfDeprecated(rawName);
                if (this.frameworkComponents[name]) {
                    console.error("Trying to register a component that you have already registered for frameworks: " + name);
                    return;
                }
                this.jsComponents[name] = component;
            };
            ComponentProvider.prototype.registerFwComponent = function(rawName, component) {
                var name = this.translateIfDeprecated(rawName);
                if (this.jsComponents[name]) {
                    console.error("Trying to register a component that you have already registered for plain javascript: " + name);
                    return;
                }
                this.frameworkComponents[name] = component;
            };
            ComponentProvider.prototype.retrieve = function(rawName) {
                var name = this.translateIfDeprecated(rawName);
                if (this.frameworkComponents[name]) {
                    return {
                        type: componentResolver_1.ComponentType.FRAMEWORK,
                        component: this.frameworkComponents[name],
                        source: RegisteredComponentSource.REGISTERED
                    };
                }
                if (this.jsComponents[name]) {
                    return {
                        type: componentResolver_1.ComponentType.AG_GRID,
                        component: this.jsComponents[name],
                        source: RegisteredComponentSource.REGISTERED
                    };
                }
                if (this.agGridDefaults[name]) {
                    return this.agGridDefaults[name] ? {
                        type: componentResolver_1.ComponentType.AG_GRID,
                        component: this.agGridDefaults[name],
                        source: RegisteredComponentSource.DEFAULT
                    } : null;
                }
                if (Object.keys(this.agGridDefaults).indexOf(name) < 0) {
                    console.warn("ag-grid: Looking for component [" + name + "] but it wasn't found.");
                }
                return null;
            };
            ComponentProvider.prototype.translateIfDeprecated = function(raw) {
                var deprecatedInfo = this.agDeprecatedNames[raw];
                if (deprecatedInfo != null) {
                    utils_1._.doOnce(function() {
                        console.warn("ag-grid. Since v15.0 component names have been renamed to be namespaced. You should rename " + deprecatedInfo.propertyHolder + ":" + raw + " to " + deprecatedInfo.propertyHolder + ":" + deprecatedInfo.newComponentName);
                    }, "DEPREACTE_COMPONENT_" + raw);
                    return deprecatedInfo.newComponentName;
                }
                return raw;
            };
            __decorate([ context_1.Autowired("gridOptions"), __metadata("design:type", Object) ], ComponentProvider.prototype, "gridOptions", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], ComponentProvider.prototype, "init", null);
            ComponentProvider = __decorate([ context_1.Bean("componentProvider") ], ComponentProvider);
            return ComponentProvider;
        }();
        exports.ComponentProvider = ComponentProvider;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var constants_1 = __webpack_require__(9);
        var component_1 = __webpack_require__(8);
        var utils_1 = __webpack_require__(1);
        var TextCellEditor = function(_super) {
            __extends(TextCellEditor, _super);
            function TextCellEditor() {
                return _super.call(this, TextCellEditor.TEMPLATE) || this;
            }
            TextCellEditor.prototype.init = function(params) {
                this.params = params;
                var eInput = this.getGui();
                var startValue;
                if (params.cellStartedEdit) {
                    this.focusAfterAttached = true;
                    var keyPressBackspaceOrDelete = params.keyPress === constants_1.Constants.KEY_BACKSPACE || params.keyPress === constants_1.Constants.KEY_DELETE;
                    if (keyPressBackspaceOrDelete) {
                        startValue = "";
                    } else if (params.charPress) {
                        startValue = params.charPress;
                    } else {
                        startValue = this.getStartValue(params);
                        if (params.keyPress !== constants_1.Constants.KEY_F2) {
                            this.highlightAllOnFocus = true;
                        }
                    }
                } else {
                    this.focusAfterAttached = false;
                    startValue = this.getStartValue(params);
                }
                if (utils_1.Utils.exists(startValue)) {
                    eInput.value = startValue;
                }
                this.addDestroyableEventListener(eInput, "keydown", function(event) {
                    var isNavigationKey = event.keyCode === constants_1.Constants.KEY_LEFT || event.keyCode === constants_1.Constants.KEY_RIGHT || event.keyCode === constants_1.Constants.KEY_UP || event.keyCode === constants_1.Constants.KEY_DOWN || event.keyCode === constants_1.Constants.KEY_PAGE_DOWN || event.keyCode === constants_1.Constants.KEY_PAGE_UP || event.keyCode === constants_1.Constants.KEY_PAGE_HOME || event.keyCode === constants_1.Constants.KEY_PAGE_END;
                    if (isNavigationKey) {
                        event.stopPropagation();
                        var pageUp = event.keyCode === constants_1.Constants.KEY_PAGE_UP;
                        var pageDown = event.keyCode === constants_1.Constants.KEY_PAGE_DOWN;
                        if (pageUp || pageDown) {
                            event.preventDefault();
                        }
                    }
                });
            };
            TextCellEditor.prototype.afterGuiAttached = function() {
                if (!this.focusAfterAttached) {
                    return;
                }
                var eInput = this.getGui();
                eInput.focus();
                if (this.highlightAllOnFocus) {
                    eInput.select();
                } else {
                    var length_1 = eInput.value ? eInput.value.length : 0;
                    if (length_1 > 0) {
                        eInput.setSelectionRange(length_1, length_1);
                    }
                }
            };
            TextCellEditor.prototype.focusIn = function() {
                var eInput = this.getGui();
                eInput.focus();
                eInput.select();
            };
            TextCellEditor.prototype.getValue = function() {
                var eInput = this.getGui();
                return this.params.parseValue(eInput.value);
            };
            TextCellEditor.prototype.getStartValue = function(params) {
                var formatValue = params.useFormatter || params.column.getColDef().refData;
                return formatValue ? params.formatValue(params.value) : params.value;
            };
            TextCellEditor.TEMPLATE = '<input class="ag-cell-edit-input" type="text"/>';
            return TextCellEditor;
        }(component_1.Component);
        exports.TextCellEditor = TextCellEditor;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var component_1 = __webpack_require__(8);
        var componentAnnotations_1 = __webpack_require__(11);
        var utils_1 = __webpack_require__(1);
        var baseFilter_1 = __webpack_require__(51);
        var context_1 = __webpack_require__(0);
        var componentRecipes_1 = __webpack_require__(21);
        var DateFilter = function(_super) {
            __extends(DateFilter, _super);
            function DateFilter() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            DateFilter.prototype.modelFromFloatingFilter = function(from) {
                return {
                    dateFrom: from,
                    dateTo: this.getDateTo(),
                    type: this.filter,
                    filterType: "date"
                };
            };
            DateFilter.prototype.getApplicableFilterTypes = function() {
                return [ baseFilter_1.BaseFilter.EQUALS, baseFilter_1.BaseFilter.GREATER_THAN, baseFilter_1.BaseFilter.LESS_THAN, baseFilter_1.BaseFilter.NOT_EQUAL, baseFilter_1.BaseFilter.IN_RANGE ];
            };
            DateFilter.prototype.bodyTemplate = function(type) {
                var fromPanelId = type == baseFilter_1.FilterConditionType.MAIN ? "filterDateFromPanel" : "filterDateFromConditionPanel";
                var toPanelId = type == baseFilter_1.FilterConditionType.MAIN ? "filterDateToPanel" : "filterDateToConditionPanel";
                return '<div class="ag-filter-body">\n                    <div class="ag-filter-date-from" id="' + fromPanelId + '">\n                    </div>\n                    <div class="ag-filter-date-to" id="' + toPanelId + '">\n                    </div>\n                </div>';
            };
            DateFilter.prototype.initialiseFilterBodyUi = function(type) {
                _super.prototype.initialiseFilterBodyUi.call(this, type);
                this.createComponents(type);
                if (type === baseFilter_1.FilterConditionType.MAIN) {
                    this.setDateFrom_date(this.dateFrom, baseFilter_1.FilterConditionType.MAIN);
                    this.setDateTo_date(this.dateTo, baseFilter_1.FilterConditionType.MAIN);
                    this.setFilterType(this.filterCondition, baseFilter_1.FilterConditionType.MAIN);
                } else {
                    this.setDateFrom_date(this.dateFromCondition, baseFilter_1.FilterConditionType.CONDITION);
                    this.setDateTo_date(this.dateToCondition, baseFilter_1.FilterConditionType.CONDITION);
                    this.setFilterType(this.filterCondition, baseFilter_1.FilterConditionType.CONDITION);
                }
            };
            DateFilter.prototype.createComponents = function(type) {
                var _this = this;
                var dateComponentParams = {
                    onDateChanged: function() {
                        _this.onDateChanged(type);
                    },
                    filterParams: this.filterParams
                };
                this.componentRecipes.newDateComponent(dateComponentParams).then(function(dateToComponent) {
                    if (type === baseFilter_1.FilterConditionType.MAIN) {
                        _this.dateToComponent = dateToComponent;
                    } else {
                        _this.dateToConditionComponent = dateToComponent;
                    }
                    var dateToElement = dateToComponent.getGui();
                    if (type === baseFilter_1.FilterConditionType.MAIN) {
                        _this.eDateToPanel.appendChild(dateToElement);
                        if (_this.dateToComponent.afterGuiAttached) {
                            _this.dateToComponent.afterGuiAttached();
                        }
                    } else {
                        _this.eDateToConditionPanel.appendChild(dateToElement);
                        if (_this.dateToConditionComponent.afterGuiAttached) {
                            _this.dateToConditionComponent.afterGuiAttached();
                        }
                    }
                });
                this.componentRecipes.newDateComponent(dateComponentParams).then(function(dateComponent) {
                    if (type === baseFilter_1.FilterConditionType.MAIN) {
                        _this.dateFromComponent = dateComponent;
                    } else {
                        _this.dateFromConditionComponent = dateComponent;
                    }
                    var dateFromElement = dateComponent.getGui();
                    if (type === baseFilter_1.FilterConditionType.MAIN) {
                        _this.eDateFromPanel.appendChild(dateFromElement);
                        if (_this.dateFromComponent.afterGuiAttached) {
                            _this.dateFromComponent.afterGuiAttached();
                        }
                    } else {
                        _this.eDateFromConditionPanel.appendChild(dateFromElement);
                        if (_this.dateFromConditionComponent.afterGuiAttached) {
                            _this.dateFromConditionComponent.afterGuiAttached();
                        }
                    }
                });
            };
            DateFilter.prototype.onDateChanged = function(type) {
                if (type === baseFilter_1.FilterConditionType.MAIN) {
                    this.dateFrom = DateFilter.removeTimezone(this.dateFromComponent.getDate());
                    this.dateTo = DateFilter.removeTimezone(this.dateToComponent.getDate());
                } else {
                    this.dateFromCondition = DateFilter.removeTimezone(this.dateFromComponent.getDate());
                    this.dateToCondition = DateFilter.removeTimezone(this.dateToComponent.getDate());
                }
                this.onFilterChanged();
            };
            DateFilter.prototype.refreshFilterBodyUi = function(type) {
                var panel;
                var filterTypeValue;
                if (type === baseFilter_1.FilterConditionType.MAIN) {
                    panel = this.eDateToPanel;
                    filterTypeValue = this.filter;
                } else {
                    panel = this.eDateToConditionPanel;
                    filterTypeValue = this.filterCondition;
                }
                if (!panel) return;
                var visible = filterTypeValue === baseFilter_1.BaseFilter.IN_RANGE;
                utils_1.Utils.setVisible(panel, visible);
            };
            DateFilter.prototype.comparator = function() {
                return this.filterParams.comparator ? this.filterParams.comparator : this.defaultComparator.bind(this);
            };
            DateFilter.prototype.defaultComparator = function(filterDate, cellValue) {
                var cellAsDate = cellValue;
                if (cellAsDate < filterDate) {
                    return -1;
                }
                if (cellAsDate > filterDate) {
                    return 1;
                }
                return cellValue != null ? 0 : -1;
            };
            DateFilter.prototype.serialize = function(type) {
                var dateToComponent = type === baseFilter_1.FilterConditionType.MAIN ? this.dateToComponent : this.dateToConditionComponent;
                var dateFromComponent = type === baseFilter_1.FilterConditionType.MAIN ? this.dateFromComponent : this.dateFromConditionComponent;
                var filterType = type === baseFilter_1.FilterConditionType.MAIN ? this.filter : this.filterCondition;
                return {
                    dateTo: utils_1.Utils.serializeDateToYyyyMmDd(dateToComponent.getDate(), "-"),
                    dateFrom: utils_1.Utils.serializeDateToYyyyMmDd(dateFromComponent.getDate(), "-"),
                    type: filterType ? filterType : this.defaultFilter,
                    filterType: "date"
                };
            };
            DateFilter.prototype.filterValues = function(type) {
                if (type === baseFilter_1.FilterConditionType.MAIN) {
                    if (!this.dateFromComponent) return null;
                    return this.filter !== baseFilter_1.BaseFilter.IN_RANGE ? this.dateFromComponent.getDate() : [ this.dateFromComponent.getDate(), this.dateToComponent.getDate() ];
                }
                if (!this.dateFromConditionComponent) return null;
                return this.filterCondition !== baseFilter_1.BaseFilter.IN_RANGE ? this.dateFromConditionComponent.getDate() : [ this.dateFromConditionComponent.getDate(), this.dateToConditionComponent.getDate() ];
            };
            DateFilter.prototype.getDateFrom = function() {
                return utils_1.Utils.serializeDateToYyyyMmDd(this.dateFromComponent.getDate(), "-");
            };
            DateFilter.prototype.getDateTo = function() {
                return utils_1.Utils.serializeDateToYyyyMmDd(this.dateToComponent.getDate(), "-");
            };
            DateFilter.prototype.getFilterType = function() {
                return this.filter;
            };
            DateFilter.prototype.setDateFrom = function(date, type) {
                var parsedDate = utils_1.Utils.parseYyyyMmDdToDate(date, "-");
                this.setDateFrom_date(parsedDate, type);
            };
            DateFilter.prototype.setDateFrom_date = function(parsedDate, type) {
                if (type === baseFilter_1.FilterConditionType.MAIN) {
                    this.dateFrom = parsedDate;
                    if (!this.dateFromComponent) return;
                    this.dateFromComponent.setDate(this.dateFrom);
                } else {
                    this.dateFromCondition = parsedDate;
                    if (!this.dateFromConditionComponent) return;
                    this.dateFromConditionComponent.setDate(this.dateFromCondition);
                }
            };
            DateFilter.prototype.setDateTo = function(date, type) {
                var parsedDate = utils_1.Utils.parseYyyyMmDdToDate(date, "-");
                this.setDateTo_date(parsedDate, type);
            };
            DateFilter.prototype.setDateTo_date = function(parsedDate, type) {
                if (type === baseFilter_1.FilterConditionType.MAIN) {
                    this.dateTo = parsedDate;
                    if (!this.dateToComponent) return;
                    this.dateToComponent.setDate(this.dateTo);
                } else {
                    this.dateToCondition = parsedDate;
                    if (!this.dateToConditionComponent) return;
                    this.dateToConditionComponent.setDate(this.dateToCondition);
                }
            };
            DateFilter.prototype.resetState = function() {
                this.setDateFrom(null, baseFilter_1.FilterConditionType.MAIN);
                this.setDateTo(null, baseFilter_1.FilterConditionType.MAIN);
                this.setFilterType(this.defaultFilter, baseFilter_1.FilterConditionType.MAIN);
                this.setDateFrom(null, baseFilter_1.FilterConditionType.CONDITION);
                this.setDateTo(null, baseFilter_1.FilterConditionType.CONDITION);
                this.setFilterType(this.defaultFilter, baseFilter_1.FilterConditionType.MAIN);
            };
            DateFilter.prototype.parse = function(model, type) {
                this.setDateFrom(model.dateFrom, type);
                this.setDateTo(model.dateTo, type);
                this.setFilterType(model.type, type);
            };
            DateFilter.prototype.setType = function(filterType, type) {
                this.setFilterType(filterType, type);
            };
            DateFilter.removeTimezone = function(from) {
                if (!from) {
                    return null;
                }
                return new Date(from.getFullYear(), from.getMonth(), from.getDate());
            };
            __decorate([ context_1.Autowired("componentRecipes"), __metadata("design:type", componentRecipes_1.ComponentRecipes) ], DateFilter.prototype, "componentRecipes", void 0);
            __decorate([ componentAnnotations_1.QuerySelector("#filterDateFromPanel"), __metadata("design:type", HTMLElement) ], DateFilter.prototype, "eDateFromPanel", void 0);
            __decorate([ componentAnnotations_1.QuerySelector("#filterDateFromConditionPanel"), __metadata("design:type", HTMLElement) ], DateFilter.prototype, "eDateFromConditionPanel", void 0);
            __decorate([ componentAnnotations_1.QuerySelector("#filterDateToPanel"), __metadata("design:type", HTMLElement) ], DateFilter.prototype, "eDateToPanel", void 0);
            __decorate([ componentAnnotations_1.QuerySelector("#filterDateToConditionPanel"), __metadata("design:type", HTMLElement) ], DateFilter.prototype, "eDateToConditionPanel", void 0);
            return DateFilter;
        }(baseFilter_1.ScalarBaseFilter);
        exports.DateFilter = DateFilter;
        var DefaultDateComponent = function(_super) {
            __extends(DefaultDateComponent, _super);
            function DefaultDateComponent() {
                return _super.call(this, '<input class="ag-filter-filter" type="text" placeholder="yyyy-mm-dd">') || this;
            }
            DefaultDateComponent.prototype.init = function(params) {
                this.eDateInput = this.getGui();
                if (utils_1.Utils.isBrowserChrome() || params.filterParams.browserDatePicker) {
                    if (utils_1.Utils.isBrowserIE()) {
                        console.warn("ag-grid: browserDatePicker is specified to true, but it is not supported in IE 11, reverting to plain text date picker");
                    } else {
                        this.eDateInput.type = "date";
                    }
                }
                this.listener = params.onDateChanged;
                this.addGuiEventListener("input", this.listener);
            };
            DefaultDateComponent.prototype.getDate = function() {
                return utils_1.Utils.parseYyyyMmDdToDate(this.eDateInput.value, "-");
            };
            DefaultDateComponent.prototype.setDate = function(date) {
                this.eDateInput.value = utils_1.Utils.serializeDateToYyyyMmDd(date, "-");
            };
            return DefaultDateComponent;
        }(component_1.Component);
        exports.DefaultDateComponent = DefaultDateComponent;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var component_1 = __webpack_require__(8);
        var context_1 = __webpack_require__(0);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var PopupEditorWrapper = function(_super) {
            __extends(PopupEditorWrapper, _super);
            function PopupEditorWrapper(cellEditor) {
                var _this = _super.call(this, '<div class="ag-popup-editor" tabindex="-1"/>') || this;
                _this.getGuiCalledOnChild = false;
                _this.cellEditor = cellEditor;
                return _this;
            }
            PopupEditorWrapper.prototype.onKeyDown = function(event) {
                this.params.onKeyDown(event);
            };
            PopupEditorWrapper.prototype.getGui = function() {
                if (!this.getGuiCalledOnChild) {
                    this.appendChild(this.cellEditor.getGui());
                    this.getGuiCalledOnChild = true;
                }
                return _super.prototype.getGui.call(this);
            };
            PopupEditorWrapper.prototype.init = function(params) {
                var _this = this;
                this.params = params;
                this.gridOptionsWrapper.setDomData(this.getGui(), PopupEditorWrapper.DOM_KEY_POPUP_EDITOR_WRAPPER, true);
                this.addDestroyFunc(function() {
                    if (_this.cellEditor.destroy) {
                        _this.cellEditor.destroy();
                    }
                });
                this.addDestroyableEventListener(_super.prototype.getGui.call(this), "keydown", this.onKeyDown.bind(this));
            };
            PopupEditorWrapper.prototype.afterGuiAttached = function() {
                if (this.cellEditor.afterGuiAttached) {
                    this.cellEditor.afterGuiAttached();
                }
            };
            PopupEditorWrapper.prototype.getValue = function() {
                return this.cellEditor.getValue();
            };
            PopupEditorWrapper.prototype.isPopup = function() {
                return true;
            };
            PopupEditorWrapper.prototype.isCancelBeforeStart = function() {
                if (this.cellEditor.isCancelBeforeStart) {
                    return this.cellEditor.isCancelBeforeStart();
                }
            };
            PopupEditorWrapper.prototype.isCancelAfterEnd = function() {
                if (this.cellEditor.isCancelAfterEnd) {
                    return this.cellEditor.isCancelAfterEnd();
                }
            };
            PopupEditorWrapper.prototype.focusIn = function() {
                if (this.cellEditor.focusIn) {
                    this.cellEditor.focusIn();
                }
            };
            PopupEditorWrapper.prototype.focusOut = function() {
                if (this.cellEditor.focusOut) {
                    this.cellEditor.focusOut();
                }
            };
            PopupEditorWrapper.DOM_KEY_POPUP_EDITOR_WRAPPER = "popupEditorWrapper";
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], PopupEditorWrapper.prototype, "gridOptionsWrapper", void 0);
            return PopupEditorWrapper;
        }(component_1.Component);
        exports.PopupEditorWrapper = PopupEditorWrapper;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var component_1 = __webpack_require__(8);
        var AnimateSlideCellRenderer = function(_super) {
            __extends(AnimateSlideCellRenderer, _super);
            function AnimateSlideCellRenderer() {
                var _this = _super.call(this, AnimateSlideCellRenderer.TEMPLATE) || this;
                _this.refreshCount = 0;
                _this.eCurrent = _this.queryForHtmlElement(".ag-value-slide-current");
                return _this;
            }
            AnimateSlideCellRenderer.prototype.init = function(params) {
                this.params = params;
                this.refresh(params);
            };
            AnimateSlideCellRenderer.prototype.addSlideAnimation = function() {
                var _this = this;
                this.refreshCount++;
                var refreshCountCopy = this.refreshCount;
                if (this.ePrevious) {
                    this.getGui().removeChild(this.ePrevious);
                }
                this.ePrevious = utils_1.Utils.loadTemplate('<span class="ag-value-slide-previous ag-value-slide-out"></span>');
                this.ePrevious.innerHTML = this.eCurrent.innerHTML;
                this.getGui().insertBefore(this.ePrevious, this.eCurrent);
                setTimeout(function() {
                    if (refreshCountCopy !== _this.refreshCount) {
                        return;
                    }
                    utils_1.Utils.addCssClass(_this.ePrevious, "ag-value-slide-out-end");
                }, 50);
                setTimeout(function() {
                    if (refreshCountCopy !== _this.refreshCount) {
                        return;
                    }
                    _this.getGui().removeChild(_this.ePrevious);
                    _this.ePrevious = null;
                }, 3e3);
            };
            AnimateSlideCellRenderer.prototype.refresh = function(params) {
                var value = params.value;
                if (utils_1.Utils.missing(value)) {
                    value = "";
                }
                if (value === this.lastValue) {
                    return;
                }
                this.addSlideAnimation();
                this.lastValue = value;
                if (utils_1.Utils.exists(params.valueFormatted)) {
                    this.eCurrent.innerHTML = params.valueFormatted;
                } else if (utils_1.Utils.exists(params.value)) {
                    this.eCurrent.innerHTML = value;
                } else {
                    this.eCurrent.innerHTML = "";
                }
                return true;
            };
            AnimateSlideCellRenderer.TEMPLATE = "<span>" + '<span class="ag-value-slide-current"></span>' + "</span>";
            return AnimateSlideCellRenderer;
        }(component_1.Component);
        exports.AnimateSlideCellRenderer = AnimateSlideCellRenderer;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var component_1 = __webpack_require__(8);
        var ARROW_UP = "&#65514;";
        var ARROW_DOWN = "&#65516;";
        var AnimateShowChangeCellRenderer = function(_super) {
            __extends(AnimateShowChangeCellRenderer, _super);
            function AnimateShowChangeCellRenderer() {
                var _this = _super.call(this, AnimateShowChangeCellRenderer.TEMPLATE) || this;
                _this.refreshCount = 0;
                return _this;
            }
            AnimateShowChangeCellRenderer.prototype.init = function(params) {
                this.eValue = this.queryForHtmlElement(".ag-value-change-value");
                this.eDelta = this.queryForHtmlElement(".ag-value-change-delta");
                this.refresh(params);
            };
            AnimateShowChangeCellRenderer.prototype.showDelta = function(params, delta) {
                var absDelta = Math.abs(delta);
                var valueFormatted = params.formatValue(absDelta);
                var valueToUse = utils_1.Utils.exists(valueFormatted) ? valueFormatted : absDelta;
                var deltaUp = delta >= 0;
                if (deltaUp) {
                    this.eDelta.innerHTML = ARROW_UP + valueToUse;
                } else {
                    this.eDelta.innerHTML = ARROW_DOWN + valueToUse;
                }
                utils_1.Utils.addOrRemoveCssClass(this.eDelta, "ag-value-change-delta-up", deltaUp);
                utils_1.Utils.addOrRemoveCssClass(this.eDelta, "ag-value-change-delta-down", !deltaUp);
            };
            AnimateShowChangeCellRenderer.prototype.setTimerToRemoveDelta = function() {
                var _this = this;
                this.refreshCount++;
                var refreshCountCopy = this.refreshCount;
                setTimeout(function() {
                    if (refreshCountCopy === _this.refreshCount) {
                        _this.hideDeltaValue();
                    }
                }, 2e3);
            };
            AnimateShowChangeCellRenderer.prototype.hideDeltaValue = function() {
                utils_1.Utils.removeCssClass(this.eValue, "ag-value-change-value-highlight");
                this.eDelta.innerHTML = "";
            };
            AnimateShowChangeCellRenderer.prototype.refresh = function(params) {
                var value = params.value;
                if (value === this.lastValue) {
                    return;
                }
                if (utils_1.Utils.exists(params.valueFormatted)) {
                    this.eValue.innerHTML = params.valueFormatted;
                } else if (utils_1.Utils.exists(params.value)) {
                    this.eValue.innerHTML = value;
                } else {
                    this.eValue.innerHTML = "";
                }
                if (typeof value === "number" && typeof this.lastValue === "number") {
                    var delta = value - this.lastValue;
                    this.showDelta(params, delta);
                }
                if (this.lastValue) {
                    utils_1.Utils.addCssClass(this.eValue, "ag-value-change-value-highlight");
                }
                this.setTimerToRemoveDelta();
                this.lastValue = value;
                return true;
            };
            AnimateShowChangeCellRenderer.TEMPLATE = "<span>" + '<span class="ag-value-change-delta"></span>' + '<span class="ag-value-change-value"></span>' + "</span>";
            return AnimateShowChangeCellRenderer;
        }(component_1.Component);
        exports.AnimateShowChangeCellRenderer = AnimateShowChangeCellRenderer;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var expressionService_1 = __webpack_require__(19);
        var eventService_1 = __webpack_require__(3);
        var constants_1 = __webpack_require__(9);
        var utils_1 = __webpack_require__(1);
        var context_1 = __webpack_require__(0);
        var component_1 = __webpack_require__(8);
        var rowNode_1 = __webpack_require__(14);
        var cellRendererService_1 = __webpack_require__(56);
        var valueFormatterService_1 = __webpack_require__(43);
        var checkboxSelectionComponent_1 = __webpack_require__(65);
        var columnController_1 = __webpack_require__(4);
        var column_1 = __webpack_require__(10);
        var componentAnnotations_1 = __webpack_require__(11);
        var mouseEventService_1 = __webpack_require__(44);
        var GroupCellRenderer = function(_super) {
            __extends(GroupCellRenderer, _super);
            function GroupCellRenderer() {
                return _super.call(this, GroupCellRenderer.TEMPLATE) || this;
            }
            GroupCellRenderer.prototype.init = function(params) {
                this.params = params;
                if (this.gridOptionsWrapper.isGroupIncludeTotalFooter()) {
                    this.assignBlankValueToGroupFooterCell(params);
                }
                var embeddedRowMismatch = this.isEmbeddedRowMismatch();
                var cellIsEmpty = params.value == null;
                this.cellIsBlank = embeddedRowMismatch || cellIsEmpty;
                if (this.cellIsBlank) {
                    return;
                }
                this.setupDragOpenParents();
                this.addExpandAndContract();
                this.addCheckboxIfNeeded();
                this.addValueElement();
                this.setupIndent();
            };
            GroupCellRenderer.prototype.assignBlankValueToGroupFooterCell = function(params) {
                if (!params.value && params.node.level == -1) {
                    params.value = "";
                }
            };
            GroupCellRenderer.prototype.isEmbeddedRowMismatch = function() {
                if (this.params.fullWidth && this.gridOptionsWrapper.isEmbedFullWidthRows()) {
                    var pinnedLeftCell = this.params.pinned === column_1.Column.PINNED_LEFT;
                    var pinnedRightCell = this.params.pinned === column_1.Column.PINNED_RIGHT;
                    var bodyCell = !pinnedLeftCell && !pinnedRightCell;
                    if (this.gridOptionsWrapper.isEnableRtl()) {
                        if (this.columnController.isPinningLeft()) {
                            return !pinnedRightCell;
                        } else {
                            return !bodyCell;
                        }
                    } else {
                        if (this.columnController.isPinningLeft()) {
                            return !pinnedLeftCell;
                        } else {
                            return !bodyCell;
                        }
                    }
                } else {
                    return false;
                }
            };
            GroupCellRenderer.prototype.setIndent = function() {
                if (this.gridOptionsWrapper.isGroupHideOpenParents()) {
                    return;
                }
                var params = this.params;
                var rowNode = params.node;
                var paddingCount = rowNode.uiLevel;
                var userProvidedPaddingPixelsTheDeprecatedWay = params.padding >= 0;
                if (userProvidedPaddingPixelsTheDeprecatedWay) {
                    this.setPaddingDeprecatedWay(paddingCount, params.padding);
                    return;
                }
                if (this.indentClass) {
                    this.removeCssClass(this.indentClass);
                }
                this.indentClass = "ag-row-group-indent-" + paddingCount;
                this.addCssClass(this.indentClass);
            };
            GroupCellRenderer.prototype.setPaddingDeprecatedWay = function(paddingCount, padding) {
                utils_1.Utils.doOnce(function() {
                    return console.warn("ag-Grid: since v14.2, configuring padding for groupCellRenderer should be done with Sass variables and themes. Please see the ag-Grid documentation page for Themes, in particular the property $row-group-indent-size.");
                }, "groupCellRenderer->doDeprecatedWay");
                var paddingPx = paddingCount * padding;
                if (this.gridOptionsWrapper.isEnableRtl()) {
                    this.getGui().style.paddingRight = paddingPx + "px";
                } else {
                    this.getGui().style.paddingLeft = paddingPx + "px";
                }
            };
            GroupCellRenderer.prototype.setupIndent = function() {
                var node = this.params.node;
                var suppressPadding = this.params.suppressPadding;
                if (!suppressPadding) {
                    this.addDestroyableEventListener(node, rowNode_1.RowNode.EVENT_UI_LEVEL_CHANGED, this.setIndent.bind(this));
                    this.setIndent();
                }
            };
            GroupCellRenderer.prototype.addValueElement = function() {
                var params = this.params;
                var rowNode = this.displayedGroup;
                if (rowNode.footer) {
                    this.createFooterCell();
                } else if (rowNode.hasChildren() || utils_1.Utils.get(params.colDef, "cellRendererParams.innerRenderer", null) || utils_1.Utils.get(params.colDef, "cellRendererParams.innerRendererFramework", null)) {
                    this.createGroupCell();
                    if (rowNode.hasChildren()) {
                        this.addChildCount();
                    }
                } else {
                    this.createLeafCell();
                }
            };
            GroupCellRenderer.prototype.createFooterCell = function() {
                var footerValue;
                var footerValueGetter = this.params.footerValueGetter;
                if (footerValueGetter) {
                    var paramsClone = utils_1.Utils.cloneObject(this.params);
                    paramsClone.value = this.params.value;
                    if (typeof footerValueGetter === "function") {
                        footerValue = footerValueGetter(paramsClone);
                    } else if (typeof footerValueGetter === "string") {
                        footerValue = this.expressionService.evaluate(footerValueGetter, paramsClone);
                    } else {
                        console.warn("ag-Grid: footerValueGetter should be either a function or a string (expression)");
                    }
                } else {
                    footerValue = "Total " + this.params.value;
                }
                this.eValue.innerHTML = footerValue;
            };
            GroupCellRenderer.prototype.createGroupCell = function() {
                var _this = this;
                var params = this.params;
                var rowGroupColumn = this.displayedGroup.rowGroupColumn;
                var columnToUse = rowGroupColumn ? rowGroupColumn : params.column;
                var groupName = this.params.value;
                var valueFormatted = columnToUse ? this.valueFormatterService.formatValue(columnToUse, params.node, params.scope, groupName) : null;
                params.valueFormatted = valueFormatted;
                var rendererPromise;
                if (params.fullWidth == true) {
                    rendererPromise = this.cellRendererService.useFullWidthGroupRowInnerCellRenderer(this.eValue, params);
                } else {
                    rendererPromise = this.cellRendererService.useInnerCellRenderer(this.params.colDef.cellRendererParams, columnToUse.getColDef(), this.eValue, params);
                }
                if (rendererPromise) {
                    rendererPromise.then(function(value) {
                        _this.innerCellRenderer = value;
                    });
                }
            };
            GroupCellRenderer.prototype.addChildCount = function() {
                if (this.params.suppressCount) {
                    return;
                }
                this.addDestroyableEventListener(this.displayedGroup, rowNode_1.RowNode.EVENT_ALL_CHILDREN_COUNT_CHANGED, this.updateChildCount.bind(this));
                this.updateChildCount();
            };
            GroupCellRenderer.prototype.updateChildCount = function() {
                var allChildrenCount = this.displayedGroup.allChildrenCount;
                this.eChildCount.innerHTML = allChildrenCount >= 0 ? "(" + allChildrenCount + ")" : "";
            };
            GroupCellRenderer.prototype.createLeafCell = function() {
                if (utils_1.Utils.exists(this.params.value)) {
                    this.eValue.innerHTML = this.params.valueFormatted ? this.params.valueFormatted : this.params.value;
                }
            };
            GroupCellRenderer.prototype.isUserWantsSelected = function() {
                var paramsCheckbox = this.params.checkbox;
                if (typeof paramsCheckbox === "function") {
                    return paramsCheckbox(this.params);
                } else {
                    return paramsCheckbox === true;
                }
            };
            GroupCellRenderer.prototype.addCheckboxIfNeeded = function() {
                var rowNode = this.displayedGroup;
                var checkboxNeeded = this.isUserWantsSelected() && !rowNode.footer && !rowNode.rowPinned && !rowNode.detail;
                if (checkboxNeeded) {
                    var cbSelectionComponent_1 = new checkboxSelectionComponent_1.CheckboxSelectionComponent();
                    this.context.wireBean(cbSelectionComponent_1);
                    cbSelectionComponent_1.init({
                        rowNode: rowNode,
                        column: this.params.column
                    });
                    this.eCheckbox.appendChild(cbSelectionComponent_1.getGui());
                    this.addDestroyFunc(function() {
                        return cbSelectionComponent_1.destroy();
                    });
                }
            };
            GroupCellRenderer.prototype.addExpandAndContract = function() {
                var params = this.params;
                var eGroupCell = params.eGridCell;
                var eExpandedIcon = utils_1.Utils.createIconNoSpan("groupExpanded", this.gridOptionsWrapper, null);
                var eContractedIcon = utils_1.Utils.createIconNoSpan("groupContracted", this.gridOptionsWrapper, null);
                this.eExpanded.appendChild(eExpandedIcon);
                this.eContracted.appendChild(eContractedIcon);
                this.addDestroyableEventListener(this.eExpanded, "click", this.onExpandClicked.bind(this));
                this.addDestroyableEventListener(this.eContracted, "click", this.onExpandClicked.bind(this));
                this.addDestroyableEventListener(eGroupCell, "keydown", this.onKeyDown.bind(this));
                this.addDestroyableEventListener(params.node, rowNode_1.RowNode.EVENT_EXPANDED_CHANGED, this.showExpandAndContractIcons.bind(this));
                this.showExpandAndContractIcons();
                this.addDestroyableEventListener(this.displayedGroup, rowNode_1.RowNode.EVENT_ALL_CHILDREN_COUNT_CHANGED, this.onAllChildrenCountChanged.bind(this));
                if (!this.gridOptionsWrapper.isEnableGroupEdit() && this.isExpandable() && !params.suppressDoubleClickExpand) {
                    this.addDestroyableEventListener(eGroupCell, "dblclick", this.onCellDblClicked.bind(this));
                }
            };
            GroupCellRenderer.prototype.onAllChildrenCountChanged = function() {
                this.showExpandAndContractIcons();
                this.setIndent();
            };
            GroupCellRenderer.prototype.onKeyDown = function(event) {
                if (utils_1.Utils.isKeyPressed(event, constants_1.Constants.KEY_ENTER)) {
                    var cellEditable = this.params.column.isCellEditable(this.params.node);
                    if (cellEditable) {
                        return;
                    }
                    event.preventDefault();
                    this.onExpandOrContract();
                }
            };
            GroupCellRenderer.prototype.setupDragOpenParents = function() {
                var column = this.params.column;
                var rowNode = this.params.node;
                if (!this.gridOptionsWrapper.isGroupHideOpenParents()) {
                    this.draggedFromHideOpenParents = false;
                } else if (!rowNode.hasChildren()) {
                    this.draggedFromHideOpenParents = true;
                } else {
                    var rowGroupColumn = rowNode.rowGroupColumn;
                    this.draggedFromHideOpenParents = !column.isRowGroupDisplayed(rowGroupColumn.getId());
                }
                if (this.draggedFromHideOpenParents) {
                    var pointer = rowNode.parent;
                    while (true) {
                        if (utils_1.Utils.missing(pointer)) {
                            break;
                        }
                        if (pointer.rowGroupColumn && column.isRowGroupDisplayed(pointer.rowGroupColumn.getId())) {
                            this.displayedGroup = pointer;
                            break;
                        }
                        pointer = pointer.parent;
                    }
                }
                if (utils_1.Utils.missing(this.displayedGroup)) {
                    this.displayedGroup = rowNode;
                }
            };
            GroupCellRenderer.prototype.onExpandClicked = function(mouseEvent) {
                if (utils_1.Utils.isStopPropagationForAgGrid(mouseEvent)) {
                    return;
                }
                utils_1.Utils.stopPropagationForAgGrid(mouseEvent);
                this.onExpandOrContract();
            };
            GroupCellRenderer.prototype.onCellDblClicked = function(mouseEvent) {
                if (utils_1.Utils.isStopPropagationForAgGrid(mouseEvent)) {
                    return;
                }
                var targetIsExpandIcon = utils_1.Utils.isElementInEventPath(this.eExpanded, mouseEvent) || utils_1.Utils.isElementInEventPath(this.eContracted, mouseEvent);
                if (!targetIsExpandIcon) {
                    this.onExpandOrContract();
                }
            };
            GroupCellRenderer.prototype.onExpandOrContract = function() {
                var rowNode = this.displayedGroup;
                rowNode.setExpanded(!rowNode.expanded);
                if (this.gridOptionsWrapper.isGroupIncludeFooter()) {
                    this.params.api.redrawRows({
                        rowNodes: [ rowNode ]
                    });
                }
            };
            GroupCellRenderer.prototype.isExpandable = function() {
                var rowNode = this.params.node;
                var reducedLeafNode = this.columnController.isPivotMode() && rowNode.leafGroup;
                return this.draggedFromHideOpenParents || rowNode.isExpandable() && !rowNode.footer && !reducedLeafNode;
            };
            GroupCellRenderer.prototype.showExpandAndContractIcons = function() {
                var rowNode = this.params.node;
                if (this.isExpandable()) {
                    var expanded = this.draggedFromHideOpenParents ? true : rowNode.expanded;
                    utils_1.Utils.setVisible(this.eContracted, !expanded);
                    utils_1.Utils.setVisible(this.eExpanded, expanded);
                } else {
                    utils_1.Utils.setVisible(this.eExpanded, false);
                    utils_1.Utils.setVisible(this.eContracted, false);
                }
                var displayedGroup = this.displayedGroup;
                var pivotModeAndLeafGroup = this.columnController.isPivotMode() && displayedGroup.leafGroup;
                var notExpandable = !displayedGroup.isExpandable();
                var addLeafIndentClass = displayedGroup.footer || notExpandable || pivotModeAndLeafGroup;
                this.addOrRemoveCssClass("ag-row-group-leaf-indent", addLeafIndentClass);
            };
            GroupCellRenderer.prototype.destroy = function() {
                _super.prototype.destroy.call(this);
                if (this.innerCellRenderer && this.innerCellRenderer.destroy) {
                    this.innerCellRenderer.destroy();
                }
            };
            GroupCellRenderer.prototype.refresh = function() {
                return false;
            };
            GroupCellRenderer.TEMPLATE = "<span>" + '<span class="ag-group-expanded" ref="eExpanded"></span>' + '<span class="ag-group-contracted" ref="eContracted"></span>' + '<span class="ag-group-checkbox" ref="eCheckbox"></span>' + '<span class="ag-group-value" ref="eValue"></span>' + '<span class="ag-group-child-count" ref="eChildCount"></span>' + "</span>";
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], GroupCellRenderer.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("expressionService"), __metadata("design:type", expressionService_1.ExpressionService) ], GroupCellRenderer.prototype, "expressionService", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], GroupCellRenderer.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("cellRendererService"), __metadata("design:type", cellRendererService_1.CellRendererService) ], GroupCellRenderer.prototype, "cellRendererService", void 0);
            __decorate([ context_1.Autowired("valueFormatterService"), __metadata("design:type", valueFormatterService_1.ValueFormatterService) ], GroupCellRenderer.prototype, "valueFormatterService", void 0);
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], GroupCellRenderer.prototype, "context", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], GroupCellRenderer.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("mouseEventService"), __metadata("design:type", mouseEventService_1.MouseEventService) ], GroupCellRenderer.prototype, "mouseEventService", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eExpanded"), __metadata("design:type", HTMLElement) ], GroupCellRenderer.prototype, "eExpanded", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eContracted"), __metadata("design:type", HTMLElement) ], GroupCellRenderer.prototype, "eContracted", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eCheckbox"), __metadata("design:type", HTMLElement) ], GroupCellRenderer.prototype, "eCheckbox", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eValue"), __metadata("design:type", HTMLElement) ], GroupCellRenderer.prototype, "eValue", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eChildCount"), __metadata("design:type", HTMLElement) ], GroupCellRenderer.prototype, "eChildCount", void 0);
            return GroupCellRenderer;
        }(component_1.Component);
        exports.GroupCellRenderer = GroupCellRenderer;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var expressionService_1 = __webpack_require__(19);
        var StylingService = function() {
            function StylingService() {}
            StylingService.prototype.processAllCellClasses = function(colDef, params, onApplicableClass, onNotApplicableClass) {
                this.processClassRules(colDef.cellClassRules, params, onApplicableClass, onNotApplicableClass);
                this.processStaticCellClasses(colDef, params, onApplicableClass);
            };
            StylingService.prototype.processClassRules = function(classRules, params, onApplicableClass, onNotApplicableClass) {
                if (typeof classRules === "object" && classRules !== null) {
                    var classNames = Object.keys(classRules);
                    for (var i = 0; i < classNames.length; i++) {
                        var className = classNames[i];
                        var rule = classRules[className];
                        var resultOfRule = void 0;
                        if (typeof rule === "string") {
                            resultOfRule = this.expressionService.evaluate(rule, params);
                        } else if (typeof rule === "function") {
                            resultOfRule = rule(params);
                        }
                        if (resultOfRule) {
                            onApplicableClass(className);
                        } else if (onNotApplicableClass) {
                            onNotApplicableClass(className);
                        }
                    }
                }
            };
            StylingService.prototype.processStaticCellClasses = function(colDef, params, onApplicableClass) {
                var cellClass = colDef.cellClass;
                if (cellClass) {
                    var classOrClasses = void 0;
                    if (typeof colDef.cellClass === "function") {
                        var cellClassFunc = colDef.cellClass;
                        classOrClasses = cellClassFunc(params);
                    } else {
                        classOrClasses = colDef.cellClass;
                    }
                    if (typeof classOrClasses === "string") {
                        onApplicableClass(classOrClasses);
                    } else if (Array.isArray(classOrClasses)) {
                        classOrClasses.forEach(function(cssClassItem) {
                            onApplicableClass(cssClassItem);
                        });
                    }
                }
            };
            __decorate([ context_1.Autowired("expressionService"), __metadata("design:type", expressionService_1.ExpressionService) ], StylingService.prototype, "expressionService", void 0);
            StylingService = __decorate([ context_1.Bean("stylingService") ], StylingService);
            return StylingService;
        }();
        exports.StylingService = StylingService;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var beanStub_1 = __webpack_require__(13);
        var context_1 = __webpack_require__(0);
        var columnHoverService_1 = __webpack_require__(45);
        var HoverFeature = function(_super) {
            __extends(HoverFeature, _super);
            function HoverFeature(columns, element) {
                var _this = _super.call(this) || this;
                _this.columns = columns;
                _this.addMouseHoverListeners(element);
                return _this;
            }
            HoverFeature.prototype.addMouseHoverListeners = function(element) {
                this.addDestroyableEventListener(element, "mouseout", this.onMouseOut.bind(this));
                this.addDestroyableEventListener(element, "mouseover", this.onMouseOver.bind(this));
            };
            HoverFeature.prototype.onMouseOut = function() {
                this.columnHoverService.clearMouseOver();
            };
            HoverFeature.prototype.onMouseOver = function() {
                this.columnHoverService.setMouseOver(this.columns);
            };
            __decorate([ context_1.Autowired("columnHoverService"), __metadata("design:type", columnHoverService_1.ColumnHoverService) ], HoverFeature.prototype, "columnHoverService", void 0);
            return HoverFeature;
        }(beanStub_1.BeanStub);
        exports.HoverFeature = HoverFeature;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var component_1 = __webpack_require__(8);
        var utils_1 = __webpack_require__(1);
        var constants_1 = __webpack_require__(9);
        var context_1 = __webpack_require__(0);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var valueFormatterService_1 = __webpack_require__(43);
        var SelectCellEditor = function(_super) {
            __extends(SelectCellEditor, _super);
            function SelectCellEditor() {
                var _this = _super.call(this, '<div class="ag-cell-edit-input"><select class="ag-cell-edit-input"/></div>') || this;
                _this.eSelect = _this.getGui().querySelector("select");
                return _this;
            }
            SelectCellEditor.prototype.init = function(params) {
                var _this = this;
                this.focusAfterAttached = params.cellStartedEdit;
                if (utils_1.Utils.missing(params.values)) {
                    console.log("ag-Grid: no values found for select cellEditor");
                    return;
                }
                params.values.forEach(function(value) {
                    var option = document.createElement("option");
                    option.value = value;
                    var valueFormatted = _this.valueFormatterService.formatValue(params.column, null, null, value);
                    var valueFormattedExits = valueFormatted !== null && valueFormatted !== undefined;
                    option.text = valueFormattedExits ? valueFormatted : value;
                    if (params.value === value) {
                        option.selected = true;
                    }
                    _this.eSelect.appendChild(option);
                });
                if (!this.gridOptionsWrapper.isFullRowEdit()) {
                    this.addDestroyableEventListener(this.eSelect, "change", function() {
                        return params.stopEditing();
                    });
                }
                this.addDestroyableEventListener(this.eSelect, "keydown", function(event) {
                    var isNavigationKey = event.keyCode === constants_1.Constants.KEY_UP || event.keyCode === constants_1.Constants.KEY_DOWN;
                    if (isNavigationKey) {
                        event.stopPropagation();
                    }
                });
                this.addDestroyableEventListener(this.eSelect, "mousedown", function(event) {
                    event.stopPropagation();
                });
            };
            SelectCellEditor.prototype.afterGuiAttached = function() {
                if (this.focusAfterAttached) {
                    this.eSelect.focus();
                }
            };
            SelectCellEditor.prototype.focusIn = function() {
                this.eSelect.focus();
            };
            SelectCellEditor.prototype.getValue = function() {
                return this.eSelect.value;
            };
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], SelectCellEditor.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("valueFormatterService"), __metadata("design:type", valueFormatterService_1.ValueFormatterService) ], SelectCellEditor.prototype, "valueFormatterService", void 0);
            return SelectCellEditor;
        }(component_1.Component);
        exports.SelectCellEditor = SelectCellEditor;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var componentMetadataProvider_1 = __webpack_require__(77);
        var utils_1 = __webpack_require__(1);
        var AgComponentUtils = function() {
            function AgComponentUtils() {}
            AgComponentUtils.prototype.adaptFunction = function(propertyName, hardcodedJsFunction, type, source) {
                if (hardcodedJsFunction == null) return {
                    component: null,
                    type: type,
                    source: source,
                    dynamicParams: null
                };
                var metadata = this.componentMetadataProvider.retrieve(propertyName);
                if (metadata && metadata.functionAdapter) {
                    return {
                        type: type,
                        component: metadata.functionAdapter(hardcodedJsFunction),
                        source: source,
                        dynamicParams: null
                    };
                }
                return null;
            };
            AgComponentUtils.prototype.adaptCellRendererFunction = function(callback) {
                var Adapter = function() {
                    function Adapter() {}
                    Adapter.prototype.refresh = function(params) {
                        return false;
                    };
                    Adapter.prototype.getGui = function() {
                        var callbackResult = callback(this.params);
                        var type = typeof callbackResult;
                        if (type === "string" || type === "number" || type === "boolean") {
                            return utils_1._.loadTemplate("<span>" + callbackResult + "</span>");
                        } else {
                            return callbackResult;
                        }
                    };
                    Adapter.prototype.init = function(params) {
                        this.params = params;
                    };
                    return Adapter;
                }();
                return Adapter;
            };
            AgComponentUtils.prototype.doesImplementIComponent = function(candidate) {
                if (!candidate) return false;
                return candidate.prototype && "getGui" in candidate.prototype;
            };
            __decorate([ context_1.Autowired("componentMetadataProvider"), __metadata("design:type", componentMetadataProvider_1.ComponentMetadataProvider) ], AgComponentUtils.prototype, "componentMetadataProvider", void 0);
            AgComponentUtils = __decorate([ context_1.Bean("agComponentUtils") ], AgComponentUtils);
            return AgComponentUtils;
        }();
        exports.AgComponentUtils = AgComponentUtils;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var agComponentUtils_1 = __webpack_require__(76);
        var ComponentMetadataProvider = function() {
            function ComponentMetadataProvider() {}
            ComponentMetadataProvider.prototype.postConstruct = function() {
                this.componentMetaData = {
                    dateComponent: {
                        mandatoryMethodList: [ "getDate", "setDate" ],
                        optionalMethodList: [ "afterGuiAttached" ]
                    },
                    detailCellRenderer: {
                        mandatoryMethodList: [],
                        optionalMethodList: []
                    },
                    headerComponent: {
                        mandatoryMethodList: [],
                        optionalMethodList: []
                    },
                    headerGroupComponent: {
                        mandatoryMethodList: [],
                        optionalMethodList: []
                    },
                    loadingOverlayComponent: {
                        mandatoryMethodList: [],
                        optionalMethodList: []
                    },
                    noRowsOverlayComponent: {
                        mandatoryMethodList: [],
                        optionalMethodList: []
                    },
                    floatingFilterComponent: {
                        mandatoryMethodList: [ "onParentModelChanged" ],
                        optionalMethodList: [ "afterGuiAttached" ]
                    },
                    floatingFilterWrapperComponent: {
                        mandatoryMethodList: [],
                        optionalMethodList: []
                    },
                    cellRenderer: {
                        mandatoryMethodList: [],
                        optionalMethodList: [ "refresh", "afterGuiAttached" ],
                        functionAdapter: this.agComponentUtils.adaptCellRendererFunction.bind(this.agComponentUtils)
                    },
                    cellEditor: {
                        mandatoryMethodList: [ "getValue" ],
                        optionalMethodList: [ "isPopup", "isCancelBeforeStart", "isCancelAfterEnd", "focusIn", "focusOut", "afterGuiAttached" ]
                    },
                    innerRenderer: {
                        mandatoryMethodList: [],
                        optionalMethodList: [ "afterGuiAttached" ],
                        functionAdapter: this.agComponentUtils.adaptCellRendererFunction.bind(this.agComponentUtils)
                    },
                    fullWidthCellRenderer: {
                        mandatoryMethodList: [],
                        optionalMethodList: [ "afterGuiAttached" ],
                        functionAdapter: this.agComponentUtils.adaptCellRendererFunction.bind(this.agComponentUtils)
                    },
                    pinnedRowCellRenderer: {
                        mandatoryMethodList: [],
                        optionalMethodList: [ "afterGuiAttached" ],
                        functionAdapter: this.agComponentUtils.adaptCellRendererFunction.bind(this.agComponentUtils)
                    },
                    groupRowInnerRenderer: {
                        mandatoryMethodList: [],
                        optionalMethodList: [ "afterGuiAttached" ],
                        functionAdapter: this.agComponentUtils.adaptCellRendererFunction.bind(this.agComponentUtils)
                    },
                    groupRowRenderer: {
                        mandatoryMethodList: [],
                        optionalMethodList: [ "afterGuiAttached" ],
                        functionAdapter: this.agComponentUtils.adaptCellRendererFunction.bind(this.agComponentUtils)
                    },
                    filter: {
                        mandatoryMethodList: [ "isFilterActive", "doesFilterPass", "getModel", "setModel" ],
                        optionalMethodList: [ "afterGuiAttached", "onNewRowsLoaded", "getModelAsString", "onFloatingFilterChanged", "afterGuiAttached" ]
                    },
                    filterComponent: {
                        mandatoryMethodList: [ "isFilterActive", "doesFilterPass", "getModel", "setModel" ],
                        optionalMethodList: [ "afterGuiAttached", "onNewRowsLoaded", "getModelAsString", "onFloatingFilterChanged", "afterGuiAttached" ]
                    }
                };
            };
            ComponentMetadataProvider.prototype.retrieve = function(name) {
                return this.componentMetaData[name];
            };
            __decorate([ context_1.Autowired("agComponentUtils"), __metadata("design:type", agComponentUtils_1.AgComponentUtils) ], ComponentMetadataProvider.prototype, "agComponentUtils", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], ComponentMetadataProvider.prototype, "postConstruct", null);
            ComponentMetadataProvider = __decorate([ context_1.Bean("componentMetadataProvider") ], ComponentMetadataProvider);
            return ComponentMetadataProvider;
        }();
        exports.ComponentMetadataProvider = ComponentMetadataProvider;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var resizeObserver_1 = __webpack_require__(129);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var columnController_1 = __webpack_require__(4);
        var columnApi_1 = __webpack_require__(7);
        var rowRenderer_1 = __webpack_require__(20);
        var context_1 = __webpack_require__(0);
        var eventService_1 = __webpack_require__(3);
        var events_1 = __webpack_require__(5);
        var dragService_1 = __webpack_require__(40);
        var constants_1 = __webpack_require__(9);
        var selectionController_1 = __webpack_require__(17);
        var csvCreator_1 = __webpack_require__(47);
        var mouseEventService_1 = __webpack_require__(44);
        var focusedCellController_1 = __webpack_require__(22);
        var scrollVisibleService_1 = __webpack_require__(36);
        var rowContainerComponent_1 = __webpack_require__(130);
        var paginationProxy_1 = __webpack_require__(29);
        var popupEditorWrapper_1 = __webpack_require__(69);
        var alignedGridsService_1 = __webpack_require__(58);
        var pinnedRowModel_1 = __webpack_require__(30);
        var gridApi_1 = __webpack_require__(6);
        var animationFrameService_1 = __webpack_require__(37);
        var rowComp_1 = __webpack_require__(50);
        var navigationService_1 = __webpack_require__(97);
        var valueService_1 = __webpack_require__(16);
        var touchListener_1 = __webpack_require__(46);
        var componentRecipes_1 = __webpack_require__(21);
        var dragAndDropService_1 = __webpack_require__(15);
        var rowDragFeature_1 = __webpack_require__(131);
        var heightScaler_1 = __webpack_require__(57);
        var component_1 = __webpack_require__(8);
        var autoHeightCalculator_1 = __webpack_require__(79);
        var columnAnimationService_1 = __webpack_require__(53);
        var autoWidthCalculator_1 = __webpack_require__(39);
        var beans_1 = __webpack_require__(28);
        var componentAnnotations_1 = __webpack_require__(11);
        var headerRootComp_1 = __webpack_require__(80);
        var GRID_PANEL_NORMAL_TEMPLATE = '<div class="ag-root ag-font-style" role="grid">\n        <ag-header-root ref="headerRoot"></ag-header-root>\n        <div class="ag-floating-top" ref="eTop" role="presentation">\n            <div class="ag-pinned-left-floating-top" ref="eLeftTop" role="presentation"></div>\n            <div class="ag-floating-top-viewport" ref="eTopViewport" role="presentation">\n                <div class="ag-floating-top-container" ref="eTopContainer" role="presentation"></div>\n            </div>\n            <div class="ag-pinned-right-floating-top" ref="eRightTop" role="presentation"></div>\n            <div class="ag-floating-top-full-width-container" ref="eTopFullWidthContainer" role="presentation"></div>\n        </div>\n        <div class="ag-body" ref="eBody" role="presentation">\n            <div class="ag-pinned-left-cols-viewport-wrapper" ref="eLeftViewportWrapper" role="presentation">\n                <div class="ag-pinned-left-cols-viewport" ref="eLeftViewport" role="presentation">\n                    <div class="ag-pinned-left-cols-container" ref="eLeftContainer" role="presentation"></div>\n                </div>\n            </div>\n            <div class="ag-body-viewport-wrapper" role="presentation">\n                <div class="ag-body-viewport" ref="eBodyViewport" role="presentation">\n                    <div class="ag-body-container" ref="eBodyContainer" role="presentation"></div>\n                </div>\n            </div>\n            <div class="ag-pinned-right-cols-viewport-wrapper" ref="eRightViewportWrapper" role="presentation">\n                <div class="ag-pinned-right-cols-viewport" ref="eRightViewport" role="presentation">\n                    <div class="ag-pinned-right-cols-container" ref="eRightContainer" role="presentation"></div>\n                </div>\n            </div>\n            <div class="ag-full-width-viewport-wrapper" ref="eFullWidthViewportWrapper" role="presentation">\n                <div class="ag-full-width-viewport" ref="eFullWidthViewport" role="presentation">\n                    <div class="ag-full-width-container" ref="eFullWidthContainer" role="presentation"></div>\n                </div>\n            </div>\n        </div>\n        <div class="ag-floating-bottom" ref="eBottom" role="presentation">\n            <div class="ag-pinned-left-floating-bottom" ref="eLeftBottom" role="presentation"></div>\n            <div class="ag-floating-bottom-viewport" ref="eBottomViewport" role="presentation">\n                <div class="ag-floating-bottom-container" ref="eBottomContainer" role="presentation"></div>\n            </div>\n            <div class="ag-pinned-right-floating-bottom" ref="eRightBottom" role="presentation"></div>\n            <div class="ag-floating-bottom-full-width-container" ref="eBottomFullWidthContainer" role="presentation"></div>\n        </div>\n        <div class="ag-overlay" ref="eOverlay"></div>\n    </div>';
        var GridPanel = function(_super) {
            __extends(GridPanel, _super);
            function GridPanel() {
                var _this = _super.call(this, GRID_PANEL_NORMAL_TEMPLATE) || this;
                _this.scrollLeft = -1;
                _this.nextScrollLeft = -1;
                _this.scrollTop = -1;
                _this.nextScrollTop = -1;
                _this.verticalRedrawNeeded = false;
                return _this;
            }
            GridPanel.prototype.getVScrollPosition = function() {
                var result = {
                    top: this.eBodyViewport.scrollTop,
                    bottom: this.eBodyViewport.scrollTop + this.eBodyViewport.offsetHeight
                };
                return result;
            };
            GridPanel.prototype.getHScrollPosition = function() {
                var result = {
                    left: this.eBodyViewport.scrollLeft,
                    right: this.eBodyViewport.scrollTop + this.eBodyViewport.offsetWidth
                };
                return result;
            };
            GridPanel.prototype.destroy = function() {
                _super.prototype.destroy.call(this);
            };
            GridPanel.prototype.onRowDataChanged = function() {
                this.showOrHideOverlay();
            };
            GridPanel.prototype.showOrHideOverlay = function() {
                if (this.paginationProxy.isEmpty() && !this.gridOptionsWrapper.isSuppressNoRowsOverlay()) {
                    this.showNoRowsOverlay();
                } else {
                    this.hideOverlay();
                }
            };
            GridPanel.prototype.onNewColumnsLoaded = function() {
                if (this.columnController.isReady() && !this.paginationProxy.isEmpty()) {
                    this.hideOverlay();
                }
            };
            GridPanel.prototype.init = function() {
                this.instantiate(this.context);
                this.scrollWidth = this.gridOptionsWrapper.getScrollbarWidth();
                this.enableRtl = this.gridOptionsWrapper.isEnableRtl();
                this.useAnimationFrame = !this.gridOptionsWrapper.isSuppressAnimationFrame();
                this.scrollClipWidth = this.scrollWidth > 0 ? this.scrollWidth : 20;
                this.suppressScrollOnFloatingRow();
                this.setupRowAnimationCssClass();
                this.buildRowContainerComponents();
                this.addEventListeners();
                this.addDragListeners();
                this.addScrollListener();
                if (this.gridOptionsWrapper.isSuppressHorizontalScroll()) {
                    this.eBodyViewport.style.overflowX = "hidden";
                }
                this.setupOverlay();
                if (this.gridOptionsWrapper.isRowModelDefault() && !this.gridOptionsWrapper.getRowData()) {
                    this.showLoadingOverlay();
                }
                this.setPinnedContainersVisible();
                this.setBodyAndHeaderHeights();
                this.disableBrowserDragging();
                this.addShortcutKeyListeners();
                this.addMouseListeners();
                this.addKeyboardEvents();
                this.addBodyViewportListener();
                this.addStopEditingWhenGridLosesFocus();
                this.mockContextMenuForIPad();
                this.addRowDragListener();
                if (this.$scope) {
                    this.addAngularApplyCheck();
                }
                this.onDisplayedColumnsWidthChanged();
                this.gridApi.registerGridComp(this);
                this.alignedGridsService.registerGridComp(this);
                this.headerRootComp.registerGridComp(this);
                this.animationFrameService.registerGridComp(this);
                this.navigationService.registerGridComp(this);
                this.heightScaler.registerGridComp(this);
                this.autoHeightCalculator.registerGridComp(this);
                this.columnAnimationService.registerGridComp(this);
                this.autoWidthCalculator.registerGridComp(this);
                this.paginationAutoPageSizeService.registerGridComp(this);
                this.beans.registerGridComp(this);
                this.rowRenderer.registerGridComp(this);
                if (this.rangeController) {
                    this.rangeController.registerGridComp(this);
                }
                var unsubscribeFromResize = resizeObserver_1.observeResize(this.eBodyViewport, this.checkViewportAndScrolls.bind(this));
                this.addDestroyFunc(function() {
                    return unsubscribeFromResize();
                });
            };
            GridPanel.prototype.setColumnMovingCss = function(moving) {
                this.addOrRemoveCssClass("ag-column-moving", moving);
            };
            GridPanel.prototype.setupOverlay = function() {
                this.overlayWrapper = this.componentRecipes.newOverlayWrapperComponent();
                this.eOverlay = this.queryForHtmlElement('[ref="eOverlay"]');
                this.overlayWrapper.hideOverlay(this.eOverlay);
            };
            GridPanel.prototype.addRowDragListener = function() {
                var rowDragFeature = new rowDragFeature_1.RowDragFeature(this.eBody, this);
                this.context.wireBean(rowDragFeature);
                this.dragAndDropService.addDropTarget(rowDragFeature);
            };
            GridPanel.prototype.addStopEditingWhenGridLosesFocus = function() {
                var _this = this;
                if (this.gridOptionsWrapper.isStopEditingWhenGridLosesFocus()) {
                    this.addDestroyableEventListener(this.eBody, "focusout", function(event) {
                        var elementWithFocus = event.relatedTarget;
                        var clickInsideGrid = false;
                        var pointer = elementWithFocus;
                        while (utils_1.Utils.exists(pointer) && !clickInsideGrid) {
                            var isPopup = !!_this.gridOptionsWrapper.getDomData(pointer, popupEditorWrapper_1.PopupEditorWrapper.DOM_KEY_POPUP_EDITOR_WRAPPER);
                            var isBody = _this.eBody == pointer;
                            clickInsideGrid = isPopup || isBody;
                            pointer = pointer.parentNode;
                        }
                        if (!clickInsideGrid) {
                            _this.rowRenderer.stopEditing();
                        }
                    });
                }
            };
            GridPanel.prototype.addAngularApplyCheck = function() {
                var _this = this;
                var applyTriggered = false;
                var listener = function() {
                    if (applyTriggered) {
                        return;
                    }
                    applyTriggered = true;
                    setTimeout(function() {
                        applyTriggered = false;
                        _this.$scope.$apply();
                    }, 0);
                };
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_DISPLAYED_COLUMNS_CHANGED, listener);
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_VIRTUAL_COLUMNS_CHANGED, listener);
            };
            GridPanel.prototype.disableBrowserDragging = function() {
                this.getGui().addEventListener("dragstart", function(event) {
                    if (event.target instanceof HTMLImageElement) {
                        event.preventDefault();
                        return false;
                    }
                });
            };
            GridPanel.prototype.addEventListeners = function() {
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_DISPLAYED_COLUMNS_CHANGED, this.onDisplayedColumnsChanged.bind(this));
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_DISPLAYED_COLUMNS_WIDTH_CHANGED, this.onDisplayedColumnsWidthChanged.bind(this));
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_PINNED_ROW_DATA_CHANGED, this.setBodyAndHeaderHeights.bind(this));
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_ROW_DATA_CHANGED, this.onRowDataChanged.bind(this));
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_ROW_DATA_UPDATED, this.onRowDataChanged.bind(this));
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_NEW_COLUMNS_LOADED, this.onNewColumnsLoaded.bind(this));
                this.addDestroyableEventListener(this.gridOptionsWrapper, gridOptionsWrapper_1.GridOptionsWrapper.PROP_HEADER_HEIGHT, this.setBodyAndHeaderHeights.bind(this));
                this.addDestroyableEventListener(this.gridOptionsWrapper, gridOptionsWrapper_1.GridOptionsWrapper.PROP_PIVOT_HEADER_HEIGHT, this.setBodyAndHeaderHeights.bind(this));
                this.addDestroyableEventListener(this.gridOptionsWrapper, gridOptionsWrapper_1.GridOptionsWrapper.PROP_GROUP_HEADER_HEIGHT, this.setBodyAndHeaderHeights.bind(this));
                this.addDestroyableEventListener(this.gridOptionsWrapper, gridOptionsWrapper_1.GridOptionsWrapper.PROP_PIVOT_GROUP_HEADER_HEIGHT, this.setBodyAndHeaderHeights.bind(this));
                this.addDestroyableEventListener(this.gridOptionsWrapper, gridOptionsWrapper_1.GridOptionsWrapper.PROP_FLOATING_FILTERS_HEIGHT, this.setBodyAndHeaderHeights.bind(this));
            };
            GridPanel.prototype.addDragListeners = function() {
                var _this = this;
                if (!this.gridOptionsWrapper.isEnableRangeSelection() || utils_1.Utils.missing(this.rangeController)) {
                    return;
                }
                var containers = [ this.eLeftContainer, this.eRightContainer, this.eBodyContainer, this.eTop, this.eBottom ];
                containers.forEach(function(container) {
                    var params = {
                        eElement: container,
                        onDragStart: _this.rangeController.onDragStart.bind(_this.rangeController),
                        onDragStop: _this.rangeController.onDragStop.bind(_this.rangeController),
                        onDragging: _this.rangeController.onDragging.bind(_this.rangeController),
                        skipMouseEvent: function(mouseEvent) {
                            return mouseEvent.shiftKey;
                        }
                    };
                    _this.dragService.addDragSource(params);
                    _this.addDestroyFunc(function() {
                        return _this.dragService.removeDragSource(params);
                    });
                });
            };
            GridPanel.prototype.addMouseListeners = function() {
                var _this = this;
                var eventNames = [ "click", "mousedown", "dblclick", "contextmenu", "mouseover", "mouseout" ];
                eventNames.forEach(function(eventName) {
                    var listener = _this.processMouseEvent.bind(_this, eventName);
                    _this.eAllCellContainers.forEach(function(container) {
                        return _this.addDestroyableEventListener(container, eventName, listener);
                    });
                });
            };
            GridPanel.prototype.addKeyboardEvents = function() {
                var _this = this;
                var eventNames = [ "keydown", "keypress" ];
                eventNames.forEach(function(eventName) {
                    var listener = _this.processKeyboardEvent.bind(_this, eventName);
                    _this.eAllCellContainers.forEach(function(container) {
                        _this.addDestroyableEventListener(container, eventName, listener);
                    });
                });
            };
            GridPanel.prototype.addBodyViewportListener = function() {
                var _this = this;
                var listener = function(mouseEvent) {
                    var target = utils_1.Utils.getTarget(mouseEvent);
                    if (target === _this.eBodyViewport || target === _this.eLeftViewport || target === _this.eRightViewport) {
                        _this.onContextMenu(mouseEvent, null, null, null, null);
                        _this.preventDefaultOnContextMenu(mouseEvent);
                    }
                };
                this.addDestroyableEventListener(this.eBodyViewport, "contextmenu", listener);
                this.addDestroyableEventListener(this.eRightViewport, "contextmenu", listener);
                this.addDestroyableEventListener(this.eLeftViewport, "contextmenu", listener);
            };
            GridPanel.prototype.getBodyClientRect = function() {
                if (this.eBody) {
                    return this.eBody.getBoundingClientRect();
                }
            };
            GridPanel.prototype.getRowForEvent = function(event) {
                var sourceElement = utils_1.Utils.getTarget(event);
                while (sourceElement) {
                    var renderedRow = this.gridOptionsWrapper.getDomData(sourceElement, rowComp_1.RowComp.DOM_DATA_KEY_RENDERED_ROW);
                    if (renderedRow) {
                        return renderedRow;
                    }
                    sourceElement = sourceElement.parentElement;
                }
                return null;
            };
            GridPanel.prototype.processKeyboardEvent = function(eventName, keyboardEvent) {
                var renderedCell = this.mouseEventService.getRenderedCellForEvent(keyboardEvent);
                if (!renderedCell) {
                    return;
                }
                switch (eventName) {
                  case "keydown":
                    var wasScrollKey = this.navigationService.handlePageScrollingKey(keyboardEvent);
                    if (!wasScrollKey) {
                        renderedCell.onKeyDown(keyboardEvent);
                    }
                    break;

                  case "keypress":
                    renderedCell.onKeyPress(keyboardEvent);
                    break;
                }
            };
            GridPanel.prototype.scrollToTop = function() {
                this.eBodyViewport.scrollTop = 0;
            };
            GridPanel.prototype.processMouseEvent = function(eventName, mouseEvent) {
                if (!this.mouseEventService.isEventFromThisGrid(mouseEvent)) {
                    return;
                }
                if (utils_1.Utils.isStopPropagationForAgGrid(mouseEvent)) {
                    return;
                }
                var rowComp = this.getRowForEvent(mouseEvent);
                var cellComp = this.mouseEventService.getRenderedCellForEvent(mouseEvent);
                if (eventName === "contextmenu") {
                    this.handleContextMenuMouseEvent(mouseEvent, null, rowComp, cellComp);
                } else {
                    if (cellComp) {
                        cellComp.onMouseEvent(eventName, mouseEvent);
                    }
                    if (rowComp) {
                        rowComp.onMouseEvent(eventName, mouseEvent);
                    }
                }
                this.preventDefaultOnContextMenu(mouseEvent);
            };
            GridPanel.prototype.mockContextMenuForIPad = function() {
                var _this = this;
                if (!utils_1.Utils.isUserAgentIPad()) {
                    return;
                }
                this.eAllCellContainers.forEach(function(container) {
                    var touchListener = new touchListener_1.TouchListener(container);
                    var longTapListener = function(event) {
                        var rowComp = _this.getRowForEvent(event.touchEvent);
                        var cellComp = _this.mouseEventService.getRenderedCellForEvent(event.touchEvent);
                        _this.handleContextMenuMouseEvent(null, event.touchEvent, rowComp, cellComp);
                    };
                    _this.addDestroyableEventListener(touchListener, touchListener_1.TouchListener.EVENT_LONG_TAP, longTapListener);
                    _this.addDestroyFunc(function() {
                        return touchListener.destroy();
                    });
                });
            };
            GridPanel.prototype.handleContextMenuMouseEvent = function(mouseEvent, touchEvent, rowComp, cellComp) {
                var rowNode = rowComp ? rowComp.getRowNode() : null;
                var column = cellComp ? cellComp.getColumn() : null;
                var value = null;
                if (column) {
                    var event_1 = mouseEvent ? mouseEvent : touchEvent;
                    cellComp.dispatchCellContextMenuEvent(event_1);
                    value = this.valueService.getValue(column, rowNode);
                }
                this.onContextMenu(mouseEvent, touchEvent, rowNode, column, value);
            };
            GridPanel.prototype.onContextMenu = function(mouseEvent, touchEvent, rowNode, column, value) {
                if (!this.gridOptionsWrapper.isAllowContextMenuWithControlKey()) {
                    if (mouseEvent && (mouseEvent.ctrlKey || mouseEvent.metaKey)) {
                        return;
                    }
                }
                if (this.contextMenuFactory && !this.gridOptionsWrapper.isSuppressContextMenu()) {
                    var eventOrTouch = mouseEvent ? mouseEvent : touchEvent.touches[0];
                    this.contextMenuFactory.showMenu(rowNode, column, value, eventOrTouch);
                    var event_2 = mouseEvent ? mouseEvent : touchEvent;
                    event_2.preventDefault();
                }
            };
            GridPanel.prototype.preventDefaultOnContextMenu = function(mouseEvent) {
                if (this.gridOptionsWrapper.isSuppressMiddleClickScrolls() && mouseEvent.which === 2) {
                    mouseEvent.preventDefault();
                }
            };
            GridPanel.prototype.addShortcutKeyListeners = function() {
                var _this = this;
                this.eAllCellContainers.forEach(function(container) {
                    container.addEventListener("keydown", function(event) {
                        var renderedCell = _this.mouseEventService.getRenderedCellForEvent(event);
                        if (renderedCell && renderedCell.isEditing()) {
                            return;
                        }
                        if (!_this.mouseEventService.isEventFromThisGrid(event)) {
                            return;
                        }
                        if (event.ctrlKey || event.metaKey) {
                            switch (event.which) {
                              case constants_1.Constants.KEY_A:
                                return _this.onCtrlAndA(event);

                              case constants_1.Constants.KEY_C:
                                return _this.onCtrlAndC(event);

                              case constants_1.Constants.KEY_V:
                                return _this.onCtrlAndV(event);

                              case constants_1.Constants.KEY_D:
                                return _this.onCtrlAndD(event);
                            }
                        }
                    });
                });
            };
            GridPanel.prototype.onCtrlAndA = function(event) {
                if (this.rangeController && this.paginationProxy.isRowsToRender()) {
                    var rowEnd = void 0;
                    var floatingStart = void 0;
                    var floatingEnd = void 0;
                    if (this.pinnedRowModel.isEmpty(constants_1.Constants.PINNED_TOP)) {
                        floatingStart = null;
                    } else {
                        floatingStart = constants_1.Constants.PINNED_TOP;
                    }
                    if (this.pinnedRowModel.isEmpty(constants_1.Constants.PINNED_BOTTOM)) {
                        floatingEnd = null;
                        rowEnd = this.paginationProxy.getTotalRowCount() - 1;
                    } else {
                        floatingEnd = constants_1.Constants.PINNED_BOTTOM;
                        rowEnd = this.pinnedRowModel.getPinnedBottomRowData().length - 1;
                    }
                    var allDisplayedColumns = this.columnController.getAllDisplayedColumns();
                    if (utils_1.Utils.missingOrEmpty(allDisplayedColumns)) {
                        return;
                    }
                    this.rangeController.setRange({
                        rowStart: 0,
                        floatingStart: floatingStart,
                        rowEnd: rowEnd,
                        floatingEnd: floatingEnd,
                        columnStart: allDisplayedColumns[0],
                        columnEnd: allDisplayedColumns[allDisplayedColumns.length - 1]
                    });
                }
                event.preventDefault();
                return false;
            };
            GridPanel.prototype.onCtrlAndC = function(event) {
                if (!this.clipboardService) {
                    return;
                }
                var focusedCell = this.focusedCellController.getFocusedCell();
                this.clipboardService.copyToClipboard();
                event.preventDefault();
                if (focusedCell) {
                    this.focusedCellController.setFocusedCell(focusedCell.rowIndex, focusedCell.column, focusedCell.floating, true);
                }
                return false;
            };
            GridPanel.prototype.onCtrlAndV = function(event) {
                if (!this.enterprise) {
                    return;
                }
                if (this.gridOptionsWrapper.isSuppressClipboardPaste()) {
                    return;
                }
                this.clipboardService.pasteFromClipboard();
                return false;
            };
            GridPanel.prototype.onCtrlAndD = function(event) {
                if (!this.enterprise) {
                    return;
                }
                this.clipboardService.copyRangeDown();
                event.preventDefault();
                return false;
            };
            GridPanel.prototype.ensureIndexVisible = function(index, position) {
                if (this.gridOptionsWrapper.isGridAutoHeight()) {
                    return;
                }
                var rowCount = this.paginationProxy.getTotalRowCount();
                if (typeof index !== "number" || index < 0 || index >= rowCount) {
                    console.warn("invalid row index for ensureIndexVisible: " + index);
                    return;
                }
                this.paginationProxy.goToPageWithIndex(index);
                var rowNode = this.paginationProxy.getRow(index);
                var paginationOffset = this.paginationProxy.getPixelOffset();
                var rowTopPixel = rowNode.rowTop - paginationOffset;
                var rowBottomPixel = rowTopPixel + rowNode.rowHeight;
                var scrollPosition = this.getVScrollPosition();
                var heightOffset = this.heightScaler.getOffset();
                var vScrollTop = scrollPosition.top + heightOffset;
                var vScrollBottom = scrollPosition.bottom + heightOffset;
                if (this.isHorizontalScrollShowing()) {
                    vScrollBottom -= this.scrollWidth;
                }
                var viewportHeight = vScrollBottom - vScrollTop;
                var newScrollPosition = null;
                var pxTop = this.heightScaler.getScrollPositionForPixel(rowTopPixel);
                var pxBottom = this.heightScaler.getScrollPositionForPixel(rowBottomPixel - viewportHeight);
                var pxMiddle = (pxTop + pxBottom) / 2;
                if (pxMiddle > rowTopPixel) {
                    pxMiddle = rowTopPixel;
                }
                var rowBelowViewport = vScrollTop > rowTopPixel;
                var rowAboveViewport = vScrollBottom < rowBottomPixel;
                if (position === "top") {
                    newScrollPosition = pxTop;
                } else if (position === "bottom") {
                    newScrollPosition = pxBottom;
                } else if (position === "middle") {
                    newScrollPosition = pxMiddle;
                } else if (rowBelowViewport) {
                    newScrollPosition = pxTop;
                } else if (rowAboveViewport) {
                    newScrollPosition = pxBottom;
                }
                if (newScrollPosition !== null) {
                    this.eBodyViewport.scrollTop = newScrollPosition;
                    this.rowRenderer.redrawAfterScroll();
                }
            };
            GridPanel.prototype.getCenterWidth = function() {
                return this.eBodyViewport.clientWidth;
            };
            GridPanel.prototype.isHorizontalScrollShowing = function() {
                return utils_1.Utils.isHorizontalScrollShowing(this.eBodyViewport);
            };
            GridPanel.prototype.isVerticalScrollShowing = function() {
                return utils_1.Utils.isVerticalScrollShowing(this.eBodyViewport);
            };
            GridPanel.prototype.checkViewportAndScrolls = function() {
                this.updateScrollVisibleService();
                this.checkBodyHeight();
                this.onHorizontalViewportChanged();
                this.setPinnedLeftWidth();
                this.setPinnedRightWidth();
                this.setBottomPaddingOnPinned();
                this.hideVerticalScrollOnCenter();
                this.hideFullWidthViewportScrollbars();
            };
            GridPanel.prototype.updateScrollVisibleService = function() {
                var params = {
                    bodyHorizontalScrollShowing: false,
                    leftVerticalScrollShowing: false,
                    rightVerticalScrollShowing: false
                };
                if (this.enableRtl && this.columnController.isPinningLeft()) {
                    params.leftVerticalScrollShowing = utils_1.Utils.isVerticalScrollShowing(this.eLeftViewport);
                }
                if (!this.enableRtl && this.columnController.isPinningRight()) {
                    params.rightVerticalScrollShowing = utils_1.Utils.isVerticalScrollShowing(this.eRightViewport);
                }
                params.bodyHorizontalScrollShowing = this.isHorizontalScrollShowing();
                this.scrollVisibleService.setScrollsVisible(params);
            };
            GridPanel.prototype.setBottomPaddingOnPinned = function() {
                if (this.scrollWidth <= 0) {
                    return;
                }
                if (this.isHorizontalScrollShowing()) {
                    this.eRightContainer.style.marginBottom = this.scrollWidth + "px";
                    this.eLeftContainer.style.marginBottom = this.scrollWidth + "px";
                } else {
                    this.eRightContainer.style.marginBottom = "";
                    this.eLeftContainer.style.marginBottom = "";
                }
            };
            GridPanel.prototype.hideFullWidthViewportScrollbars = function() {
                var scrollWidthPx = this.scrollClipWidth > 0 ? this.scrollWidth + "px" : "";
                this.eFullWidthViewportWrapper.style.paddingBottom = this.isHorizontalScrollShowing() ? scrollWidthPx : "";
                var takeOutVScroll = this.isVerticalScrollShowing();
                if (this.enableRtl) {
                    this.eFullWidthViewportWrapper.style.marginLeft = takeOutVScroll ? scrollWidthPx : "";
                    this.eFullWidthViewport.style.marginLeft = takeOutVScroll ? "-" + scrollWidthPx : "";
                } else {
                    this.eFullWidthViewportWrapper.style.width = takeOutVScroll ? "calc(100% - " + scrollWidthPx + ")" : "";
                    this.eFullWidthViewport.style.width = takeOutVScroll ? "calc(100% + " + scrollWidthPx + ")" : "";
                }
            };
            GridPanel.prototype.ensureColumnVisible = function(key) {
                var column = this.columnController.getGridColumn(key);
                if (!column) {
                    return;
                }
                if (column.isPinned()) {
                    console.warn("calling ensureIndexVisible on a " + column.getPinned() + " pinned column doesn't make sense for column " + column.getColId());
                    return;
                }
                if (!this.columnController.isColumnDisplayed(column)) {
                    console.warn("column is not currently visible");
                    return;
                }
                var colLeftPixel = column.getLeft();
                var colRightPixel = colLeftPixel + column.getActualWidth();
                var viewportWidth = this.eBodyViewport.clientWidth;
                var scrollPosition = this.getBodyViewportScrollLeft();
                var bodyWidth = this.columnController.getBodyContainerWidth();
                var viewportLeftPixel;
                var viewportRightPixel;
                if (this.enableRtl) {
                    viewportLeftPixel = bodyWidth - scrollPosition - viewportWidth;
                    viewportRightPixel = bodyWidth - scrollPosition;
                } else {
                    viewportLeftPixel = scrollPosition;
                    viewportRightPixel = viewportWidth + scrollPosition;
                }
                var viewportScrolledPastCol = viewportLeftPixel > colLeftPixel;
                var viewportScrolledBeforeCol = viewportRightPixel < colRightPixel;
                var colToSmallForViewport = viewportWidth < column.getActualWidth();
                var alignColToLeft = viewportScrolledPastCol || colToSmallForViewport;
                var alignColToRight = viewportScrolledBeforeCol;
                if (alignColToLeft) {
                    if (this.enableRtl) {
                        var newScrollPosition = bodyWidth - viewportWidth - colLeftPixel;
                        this.setBodyViewportScrollLeft(newScrollPosition);
                    } else {
                        this.setBodyViewportScrollLeft(colLeftPixel);
                    }
                } else if (alignColToRight) {
                    if (this.enableRtl) {
                        var newScrollPosition = bodyWidth - colRightPixel;
                        this.setBodyViewportScrollLeft(newScrollPosition);
                    } else {
                        var newScrollPosition = colRightPixel - viewportWidth;
                        this.setBodyViewportScrollLeft(newScrollPosition);
                    }
                } else {}
                this.onHorizontalViewportChanged();
            };
            GridPanel.prototype.showLoadingOverlay = function() {
                this.overlayWrapper.showLoadingOverlay(this.eOverlay);
            };
            GridPanel.prototype.showNoRowsOverlay = function() {
                this.overlayWrapper.showNoRowsOverlay(this.eOverlay);
            };
            GridPanel.prototype.hideOverlay = function() {
                this.overlayWrapper.hideOverlay(this.eOverlay);
            };
            GridPanel.prototype.getWidthForSizeColsToFit = function() {
                var availableWidth = this.eBody.clientWidth;
                var removeVerticalScrollWidth = this.isVerticalScrollShowing();
                if (removeVerticalScrollWidth) {
                    availableWidth -= this.scrollWidth;
                }
                return availableWidth;
            };
            GridPanel.prototype.sizeColumnsToFit = function(nextTimeout) {
                var _this = this;
                var availableWidth = this.getWidthForSizeColsToFit();
                if (availableWidth > 0) {
                    this.columnController.sizeColumnsToFit(availableWidth, "sizeColumnsToFit");
                } else {
                    if (nextTimeout === undefined) {
                        setTimeout(function() {
                            _this.sizeColumnsToFit(100);
                        }, 0);
                    } else if (nextTimeout === 100) {
                        setTimeout(function() {
                            _this.sizeColumnsToFit(500);
                        }, 100);
                    } else if (nextTimeout === 500) {
                        setTimeout(function() {
                            _this.sizeColumnsToFit(-1);
                        }, 500);
                    } else {
                        console.log("ag-Grid: tried to call sizeColumnsToFit() but the grid is coming back with " + "zero width, maybe the grid is not visible yet on the screen?");
                    }
                }
            };
            GridPanel.prototype.getBodyContainer = function() {
                return this.eBodyContainer;
            };
            GridPanel.prototype.getDropTargetBodyContainers = function() {
                return [ this.eBodyViewport, this.eTopViewport, this.eBottomViewport ];
            };
            GridPanel.prototype.getDropTargetLeftContainers = function() {
                return [ this.eLeftViewport, this.eLeftBottom, this.eLeftTop ];
            };
            GridPanel.prototype.getDropTargetRightContainers = function() {
                return [ this.eRightViewport, this.eRightBottom, this.eRightTop ];
            };
            GridPanel.prototype.buildRowContainerComponents = function() {
                var _this = this;
                this.eAllCellContainers = [ this.eLeftContainer, this.eRightContainer, this.eBodyContainer, this.eTop, this.eBottom, this.eFullWidthContainer ];
                this.rowContainerComponents = {
                    body: new rowContainerComponent_1.RowContainerComponent({
                        eContainer: this.eBodyContainer,
                        eViewport: this.eBodyViewport
                    }),
                    fullWidth: new rowContainerComponent_1.RowContainerComponent({
                        eContainer: this.eFullWidthContainer,
                        hideWhenNoChildren: true,
                        eViewport: this.eFullWidthViewport
                    }),
                    pinnedLeft: new rowContainerComponent_1.RowContainerComponent({
                        eContainer: this.eLeftContainer,
                        eViewport: this.eLeftViewport
                    }),
                    pinnedRight: new rowContainerComponent_1.RowContainerComponent({
                        eContainer: this.eRightContainer,
                        eViewport: this.eRightViewport
                    }),
                    floatingTop: new rowContainerComponent_1.RowContainerComponent({
                        eContainer: this.eTopContainer
                    }),
                    floatingTopPinnedLeft: new rowContainerComponent_1.RowContainerComponent({
                        eContainer: this.eLeftTop
                    }),
                    floatingTopPinnedRight: new rowContainerComponent_1.RowContainerComponent({
                        eContainer: this.eRightTop
                    }),
                    floatingTopFullWidth: new rowContainerComponent_1.RowContainerComponent({
                        eContainer: this.eTopFullWidthContainer,
                        hideWhenNoChildren: true
                    }),
                    floatingBottom: new rowContainerComponent_1.RowContainerComponent({
                        eContainer: this.eBottomContainer
                    }),
                    floatingBottomPinnedLeft: new rowContainerComponent_1.RowContainerComponent({
                        eContainer: this.eLeftBottom
                    }),
                    floatingBottomPinnedRight: new rowContainerComponent_1.RowContainerComponent({
                        eContainer: this.eRightBottom
                    }),
                    floatingBottomFullWith: new rowContainerComponent_1.RowContainerComponent({
                        eContainer: this.eBottomFullWidthContainer,
                        hideWhenNoChildren: true
                    })
                };
                utils_1.Utils.iterateObject(this.rowContainerComponents, function(key, container) {
                    if (container) {
                        _this.context.wireBean(container);
                    }
                });
            };
            GridPanel.prototype.setupRowAnimationCssClass = function() {
                var _this = this;
                var listener = function() {
                    var animateRows = _this.gridOptionsWrapper.isAnimateRows() && !_this.heightScaler.isScaling();
                    utils_1.Utils.addOrRemoveCssClass(_this.eBody, "ag-row-animation", animateRows);
                    utils_1.Utils.addOrRemoveCssClass(_this.eBody, "ag-row-no-animation", !animateRows);
                };
                listener();
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_HEIGHT_SCALE_CHANGED, listener);
            };
            GridPanel.prototype.suppressScrollOnFloatingRow = function() {
                var _this = this;
                var resetTopScroll = function() {
                    return _this.eTopViewport.scrollLeft = 0;
                };
                var resetBottomScroll = function() {
                    return _this.eTopViewport.scrollLeft = 0;
                };
                this.addDestroyableEventListener(this.eTopViewport, "scroll", resetTopScroll);
                this.addDestroyableEventListener(this.eBottomViewport, "scroll", resetBottomScroll);
            };
            GridPanel.prototype.getRowContainers = function() {
                return this.rowContainerComponents;
            };
            GridPanel.prototype.onDisplayedColumnsChanged = function() {
                this.setPinnedContainersVisible();
                this.setBodyAndHeaderHeights();
                this.onHorizontalViewportChanged();
            };
            GridPanel.prototype.onDisplayedColumnsWidthChanged = function() {
                this.setWidthsOfContainers();
                this.onHorizontalViewportChanged();
                if (this.enableRtl) {
                    this.horizontallyScrollHeaderCenterAndFloatingCenter();
                }
            };
            GridPanel.prototype.setWidthsOfContainers = function() {
                this.setCenterWidth();
                this.setPinnedLeftWidth();
                this.setPinnedRightWidth();
            };
            GridPanel.prototype.setCenterWidth = function() {
                var widthPx = this.columnController.getBodyContainerWidth() + "px";
                this.eBodyContainer.style.width = widthPx;
                this.eBottomContainer.style.width = widthPx;
                this.eTopContainer.style.width = widthPx;
            };
            GridPanel.prototype.setPinnedLeftWidth = function() {
                var widthOfCols = this.columnController.getPinnedLeftContainerWidth();
                var widthOfColsAndScroll = widthOfCols + this.scrollWidth;
                var widthOfColsAndClippedScroll = widthOfCols + this.scrollClipWidth;
                var viewportWidth;
                var wrapperWidth;
                if (utils_1.Utils.isVerticalScrollShowing(this.eLeftViewport)) {
                    if (this.enableRtl) {
                        viewportWidth = widthOfColsAndScroll;
                        wrapperWidth = widthOfColsAndScroll;
                    } else {
                        viewportWidth = widthOfColsAndClippedScroll;
                        wrapperWidth = widthOfCols;
                    }
                } else {
                    viewportWidth = widthOfCols;
                    wrapperWidth = widthOfCols;
                }
                this.setElementWidth(this.eLeftViewportWrapper, wrapperWidth);
                this.setElementWidth(this.eLeftViewport, viewportWidth);
                this.setElementWidth(this.eLeftContainer, widthOfCols);
                this.setElementWidth(this.eLeftBottom, wrapperWidth);
                this.setElementWidth(this.eLeftTop, wrapperWidth);
            };
            GridPanel.prototype.setPinnedRightWidth = function() {
                var widthOfCols = this.columnController.getPinnedRightContainerWidth();
                var widthOfColsAndScroll = widthOfCols + this.scrollWidth;
                var widthOfColsAndClippedScroll = widthOfCols + this.scrollClipWidth;
                var viewportWidth;
                var wrapperWidth;
                if (utils_1.Utils.isVerticalScrollShowing(this.eRightViewport)) {
                    if (!this.enableRtl) {
                        viewportWidth = widthOfColsAndScroll;
                        wrapperWidth = widthOfColsAndScroll;
                    } else {
                        viewportWidth = widthOfColsAndClippedScroll;
                        wrapperWidth = widthOfCols;
                    }
                } else {
                    viewportWidth = widthOfCols;
                    wrapperWidth = widthOfCols;
                }
                this.setElementWidth(this.eRightViewportWrapper, wrapperWidth);
                this.setElementWidth(this.eRightViewport, viewportWidth);
                this.setElementWidth(this.eRightContainer, widthOfCols);
                this.setElementWidth(this.eRightBottom, wrapperWidth);
                this.setElementWidth(this.eRightTop, wrapperWidth);
            };
            GridPanel.prototype.setElementWidth = function(element, width) {
                element.style.width = width + "px";
                element.style.minWidth = width + "px";
            };
            GridPanel.prototype.setPinnedContainersVisible = function() {
                var changeDetected = false;
                var showLeftPinned = this.columnController.isPinningLeft();
                if (showLeftPinned !== this.pinningLeft) {
                    this.pinningLeft = showLeftPinned;
                    this.headerRootComp.setLeftVisible(showLeftPinned);
                    utils_1.Utils.setVisible(this.eLeftViewportWrapper, showLeftPinned);
                    changeDetected = true;
                    if (showLeftPinned) {
                        this.eLeftViewport.scrollTop = this.eBodyViewport.scrollTop;
                    }
                }
                var showRightPinned = this.columnController.isPinningRight();
                if (showRightPinned !== this.pinningRight) {
                    this.pinningRight = showRightPinned;
                    this.headerRootComp.setRightVisible(showRightPinned);
                    utils_1.Utils.setVisible(this.eRightViewportWrapper, showRightPinned);
                    if (showRightPinned) {
                        this.eRightViewport.scrollTop = this.eBodyViewport.scrollTop;
                    }
                    changeDetected = true;
                }
                if (changeDetected) {
                    this.hideVerticalScrollOnCenter();
                    this.setPinnedLeftWidth();
                    this.setPinnedRightWidth();
                }
            };
            GridPanel.prototype.hideVerticalScrollOnCenter = function() {
                var neverShowScroll = this.enableRtl ? this.columnController.isPinningLeft() : this.columnController.isPinningRight();
                var scrollActive = utils_1.Utils.isVerticalScrollShowing(this.eBodyViewport);
                var hideScroll = neverShowScroll && scrollActive;
                var margin = hideScroll ? "-" + this.scrollClipWidth + "px" : "";
                if (this.enableRtl) {
                    this.eBodyViewport.style.marginLeft = margin;
                } else {
                    this.eBodyViewport.style.marginRight = margin;
                }
            };
            GridPanel.prototype.checkBodyHeight = function() {
                var bodyHeight = this.eBody.clientHeight;
                if (this.bodyHeight !== bodyHeight) {
                    this.bodyHeight = bodyHeight;
                    var event_3 = {
                        type: events_1.Events.EVENT_BODY_HEIGHT_CHANGED,
                        api: this.gridApi,
                        columnApi: this.columnApi
                    };
                    this.eventService.dispatchEvent(event_3);
                }
            };
            GridPanel.prototype.setBodyAndHeaderHeights = function() {
                var headerRowCount = this.columnController.getHeaderRowCount();
                var totalHeaderHeight;
                var numberOfFloating = 0;
                var groupHeight;
                var headerHeight;
                if (!this.columnController.isPivotMode()) {
                    if (this.gridOptionsWrapper.isFloatingFilter()) {
                        headerRowCount++;
                    }
                    numberOfFloating = this.gridOptionsWrapper.isFloatingFilter() ? 1 : 0;
                    groupHeight = this.gridOptionsWrapper.getGroupHeaderHeight();
                    headerHeight = this.gridOptionsWrapper.getHeaderHeight();
                } else {
                    numberOfFloating = 0;
                    groupHeight = this.gridOptionsWrapper.getPivotGroupHeaderHeight();
                    headerHeight = this.gridOptionsWrapper.getPivotHeaderHeight();
                }
                var numberOfNonGroups = 1 + numberOfFloating;
                var numberOfGroups = headerRowCount - numberOfNonGroups;
                totalHeaderHeight = numberOfFloating * this.gridOptionsWrapper.getFloatingFiltersHeight();
                totalHeaderHeight += numberOfGroups * groupHeight;
                totalHeaderHeight += headerHeight;
                this.headerRootComp.setHeight(totalHeaderHeight);
                var floatingTopHeight = this.pinnedRowModel.getPinnedTopTotalHeight();
                var floatingBottomHeight = this.pinnedRowModel.getPinnedBottomTotalHeight();
                this.eTop.style.minHeight = floatingTopHeight + "px";
                this.eTop.style.height = floatingTopHeight + "px";
                this.eBottom.style.minHeight = floatingBottomHeight + "px";
                this.eBottom.style.height = floatingBottomHeight + "px";
                this.checkBodyHeight();
            };
            GridPanel.prototype.getBodyHeight = function() {
                return this.bodyHeight;
            };
            GridPanel.prototype.setHorizontalScrollPosition = function(hScrollPosition) {
                this.eBodyViewport.scrollLeft = hScrollPosition;
                if (this.nextScrollLeft !== hScrollPosition) {
                    this.nextScrollLeft = hScrollPosition;
                    this.doHorizontalScroll();
                }
            };
            GridPanel.prototype.setVerticalScrollPosition = function(vScrollPosition) {
                this.eBodyViewport.scrollTop = vScrollPosition;
            };
            GridPanel.prototype.scrollHorizontally = function(pixels) {
                var oldScrollPosition = this.eBodyViewport.scrollLeft;
                this.setHorizontalScrollPosition(oldScrollPosition + pixels);
                var newScrollPosition = this.eBodyViewport.scrollLeft;
                return newScrollPosition - oldScrollPosition;
            };
            GridPanel.prototype.scrollVertically = function(pixels) {
                var oldScrollPosition = this.eBodyViewport.scrollTop;
                this.setVerticalScrollPosition(oldScrollPosition + pixels);
                var newScrollPosition = this.eBodyViewport.scrollTop;
                return newScrollPosition - oldScrollPosition;
            };
            GridPanel.prototype.addScrollListener = function() {
                var _this = this;
                this.addDestroyableEventListener(this.eBodyViewport, "scroll", function() {
                    _this.onBodyHorizontalScroll();
                    _this.onAnyBodyScroll(_this.eBodyViewport);
                });
                this.addDestroyableEventListener(this.eRightViewport, "scroll", this.onAnyBodyScroll.bind(this, this.eRightViewport));
                this.addDestroyableEventListener(this.eLeftViewport, "scroll", this.onAnyBodyScroll.bind(this, this.eLeftViewport));
                this.addDestroyableEventListener(this.eFullWidthViewport, "scroll", this.onAnyBodyScroll.bind(this, this.eFullWidthViewport));
            };
            GridPanel.prototype.onAnyBodyScroll = function(source) {
                var now = new Date().getTime();
                var diff = now - this.lastVScrollTime;
                var elementIsNotControllingTheScroll = source !== this.lastVScrollElement && diff < 500;
                if (elementIsNotControllingTheScroll) {
                    return;
                }
                this.lastVScrollElement = source;
                this.lastVScrollTime = now;
                var scrollTop = source.scrollTop;
                if (this.useAnimationFrame) {
                    if (this.nextScrollTop !== scrollTop) {
                        this.nextScrollTop = scrollTop;
                        this.animationFrameService.schedule();
                    }
                } else {
                    if (scrollTop !== this.scrollTop) {
                        this.scrollTop = scrollTop;
                        this.synchroniseVerticalScrollPositions(scrollTop);
                        this.redrawRowsAfterScroll();
                    }
                }
            };
            GridPanel.prototype.onBodyHorizontalScroll = function() {
                var scrollLeft = this.eBodyViewport.scrollLeft;
                if (this.nextScrollLeft !== scrollLeft) {
                    this.nextScrollLeft = scrollLeft;
                    if (this.useAnimationFrame) {
                        this.animationFrameService.schedule();
                    } else {
                        this.doHorizontalScroll();
                    }
                }
            };
            GridPanel.prototype.doHorizontalScroll = function() {
                this.scrollLeft = this.nextScrollLeft;
                var event = {
                    type: events_1.Events.EVENT_BODY_SCROLL,
                    api: this.gridApi,
                    columnApi: this.columnApi,
                    direction: "horizontal",
                    left: this.scrollLeft,
                    top: this.scrollTop
                };
                this.eventService.dispatchEvent(event);
                this.horizontallyScrollHeaderCenterAndFloatingCenter();
                this.onHorizontalViewportChanged();
            };
            GridPanel.prototype.executeFrame = function() {
                if (this.scrollLeft !== this.nextScrollLeft) {
                    this.doHorizontalScroll();
                    return true;
                } else if (this.scrollTop !== this.nextScrollTop) {
                    this.scrollTop = this.nextScrollTop;
                    this.synchroniseVerticalScrollPositions(this.scrollTop);
                    this.verticalRedrawNeeded = true;
                    return true;
                } else if (this.verticalRedrawNeeded) {
                    this.redrawRowsAfterScroll();
                    this.verticalRedrawNeeded = false;
                    return true;
                } else {
                    return false;
                }
            };
            GridPanel.prototype.redrawRowsAfterScroll = function() {
                var event = {
                    type: events_1.Events.EVENT_BODY_SCROLL,
                    direction: "vertical",
                    api: this.gridApi,
                    columnApi: this.columnApi,
                    left: this.scrollLeft,
                    top: this.scrollTop
                };
                this.eventService.dispatchEvent(event);
            };
            GridPanel.prototype.onHorizontalViewportChanged = function() {
                var scrollWidth = this.eBodyViewport.clientWidth;
                var scrollPosition = this.getBodyViewportScrollLeft();
                this.columnController.setVirtualViewportPosition(scrollWidth, scrollPosition);
            };
            GridPanel.prototype.getBodyViewportScrollLeft = function() {
                return utils_1.Utils.getScrollLeft(this.eBodyViewport, this.enableRtl);
            };
            GridPanel.prototype.setBodyViewportScrollLeft = function(value) {
                utils_1.Utils.setScrollLeft(this.eBodyViewport, value, this.enableRtl);
            };
            GridPanel.prototype.horizontallyScrollHeaderCenterAndFloatingCenter = function() {
                var scrollLeft = this.getBodyViewportScrollLeft();
                var offset = this.enableRtl ? scrollLeft : -scrollLeft;
                this.headerRootComp.setHorizontalScroll(offset);
                this.eBottomContainer.style.left = offset + "px";
                this.eTopContainer.style.left = offset + "px";
            };
            GridPanel.prototype.synchroniseVerticalScrollPositions = function(position) {
                if (this.lastVScrollElement !== this.eBodyViewport) {
                    this.eBodyViewport.scrollTop = position;
                }
                if (this.lastVScrollElement !== this.eLeftViewport && this.pinningLeft) {
                    this.eLeftViewport.scrollTop = position;
                }
                if (this.lastVScrollElement !== this.eRightViewport && this.pinningRight) {
                    this.eRightViewport.scrollTop = position;
                }
                if (this.lastVScrollElement !== this.eFullWidthViewport) {
                    this.eFullWidthViewport.scrollTop = position;
                }
                this.rowContainerComponents.body.setVerticalScrollPosition(position);
                this.rowContainerComponents.pinnedLeft.setVerticalScrollPosition(position);
                this.rowContainerComponents.pinnedRight.setVerticalScrollPosition(position);
                this.rowContainerComponents.fullWidth.setVerticalScrollPosition(position);
                this.redrawRowsAfterScroll();
            };
            GridPanel.prototype.addScrollEventListener = function(listener) {
                this.eBodyViewport.addEventListener("scroll", listener);
            };
            GridPanel.prototype.removeScrollEventListener = function(listener) {
                this.eBodyViewport.removeEventListener("scroll", listener);
            };
            __decorate([ context_1.Autowired("alignedGridsService"), __metadata("design:type", alignedGridsService_1.AlignedGridsService) ], GridPanel.prototype, "alignedGridsService", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], GridPanel.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], GridPanel.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("rowRenderer"), __metadata("design:type", rowRenderer_1.RowRenderer) ], GridPanel.prototype, "rowRenderer", void 0);
            __decorate([ context_1.Autowired("pinnedRowModel"), __metadata("design:type", pinnedRowModel_1.PinnedRowModel) ], GridPanel.prototype, "pinnedRowModel", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], GridPanel.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], GridPanel.prototype, "context", void 0);
            __decorate([ context_1.Autowired("animationFrameService"), __metadata("design:type", animationFrameService_1.AnimationFrameService) ], GridPanel.prototype, "animationFrameService", void 0);
            __decorate([ context_1.Autowired("navigationService"), __metadata("design:type", navigationService_1.NavigationService) ], GridPanel.prototype, "navigationService", void 0);
            __decorate([ context_1.Autowired("autoHeightCalculator"), __metadata("design:type", autoHeightCalculator_1.AutoHeightCalculator) ], GridPanel.prototype, "autoHeightCalculator", void 0);
            __decorate([ context_1.Autowired("columnAnimationService"), __metadata("design:type", columnAnimationService_1.ColumnAnimationService) ], GridPanel.prototype, "columnAnimationService", void 0);
            __decorate([ context_1.Autowired("autoWidthCalculator"), __metadata("design:type", autoWidthCalculator_1.AutoWidthCalculator) ], GridPanel.prototype, "autoWidthCalculator", void 0);
            __decorate([ context_1.Autowired("paginationAutoPageSizeService"), __metadata("design:type", paginationProxy_1.PaginationAutoPageSizeService) ], GridPanel.prototype, "paginationAutoPageSizeService", void 0);
            __decorate([ context_1.Autowired("beans"), __metadata("design:type", beans_1.Beans) ], GridPanel.prototype, "beans", void 0);
            __decorate([ context_1.Autowired("paginationProxy"), __metadata("design:type", paginationProxy_1.PaginationProxy) ], GridPanel.prototype, "paginationProxy", void 0);
            __decorate([ context_1.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], GridPanel.prototype, "columnApi", void 0);
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], GridPanel.prototype, "gridApi", void 0);
            __decorate([ context_1.Autowired("dragService"), __metadata("design:type", dragService_1.DragService) ], GridPanel.prototype, "dragService", void 0);
            __decorate([ context_1.Autowired("selectionController"), __metadata("design:type", selectionController_1.SelectionController) ], GridPanel.prototype, "selectionController", void 0);
            __decorate([ context_1.Autowired("csvCreator"), __metadata("design:type", csvCreator_1.CsvCreator) ], GridPanel.prototype, "csvCreator", void 0);
            __decorate([ context_1.Autowired("mouseEventService"), __metadata("design:type", mouseEventService_1.MouseEventService) ], GridPanel.prototype, "mouseEventService", void 0);
            __decorate([ context_1.Autowired("focusedCellController"), __metadata("design:type", focusedCellController_1.FocusedCellController) ], GridPanel.prototype, "focusedCellController", void 0);
            __decorate([ context_1.Autowired("$scope"), __metadata("design:type", Object) ], GridPanel.prototype, "$scope", void 0);
            __decorate([ context_1.Autowired("scrollVisibleService"), __metadata("design:type", scrollVisibleService_1.ScrollVisibleService) ], GridPanel.prototype, "scrollVisibleService", void 0);
            __decorate([ context_1.Autowired("frameworkFactory"), __metadata("design:type", Object) ], GridPanel.prototype, "frameworkFactory", void 0);
            __decorate([ context_1.Autowired("valueService"), __metadata("design:type", valueService_1.ValueService) ], GridPanel.prototype, "valueService", void 0);
            __decorate([ context_1.Autowired("componentRecipes"), __metadata("design:type", componentRecipes_1.ComponentRecipes) ], GridPanel.prototype, "componentRecipes", void 0);
            __decorate([ context_1.Autowired("dragAndDropService"), __metadata("design:type", dragAndDropService_1.DragAndDropService) ], GridPanel.prototype, "dragAndDropService", void 0);
            __decorate([ context_1.Autowired("heightScaler"), __metadata("design:type", heightScaler_1.HeightScaler) ], GridPanel.prototype, "heightScaler", void 0);
            __decorate([ context_1.Autowired("enterprise"), __metadata("design:type", Boolean) ], GridPanel.prototype, "enterprise", void 0);
            __decorate([ context_1.Optional("rangeController"), __metadata("design:type", Object) ], GridPanel.prototype, "rangeController", void 0);
            __decorate([ context_1.Optional("contextMenuFactory"), __metadata("design:type", Object) ], GridPanel.prototype, "contextMenuFactory", void 0);
            __decorate([ context_1.Optional("clipboardService"), __metadata("design:type", Object) ], GridPanel.prototype, "clipboardService", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eBody"), __metadata("design:type", HTMLElement) ], GridPanel.prototype, "eBody", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eBodyViewport"), __metadata("design:type", HTMLElement) ], GridPanel.prototype, "eBodyViewport", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eBodyContainer"), __metadata("design:type", HTMLElement) ], GridPanel.prototype, "eBodyContainer", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eLeftContainer"), __metadata("design:type", HTMLElement) ], GridPanel.prototype, "eLeftContainer", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eRightContainer"), __metadata("design:type", HTMLElement) ], GridPanel.prototype, "eRightContainer", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eFullWidthViewportWrapper"), __metadata("design:type", HTMLElement) ], GridPanel.prototype, "eFullWidthViewportWrapper", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eFullWidthViewport"), __metadata("design:type", HTMLElement) ], GridPanel.prototype, "eFullWidthViewport", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eFullWidthContainer"), __metadata("design:type", HTMLElement) ], GridPanel.prototype, "eFullWidthContainer", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eLeftViewport"), __metadata("design:type", HTMLElement) ], GridPanel.prototype, "eLeftViewport", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eLeftViewportWrapper"), __metadata("design:type", HTMLElement) ], GridPanel.prototype, "eLeftViewportWrapper", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eRightViewport"), __metadata("design:type", HTMLElement) ], GridPanel.prototype, "eRightViewport", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eRightViewportWrapper"), __metadata("design:type", HTMLElement) ], GridPanel.prototype, "eRightViewportWrapper", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eTop"), __metadata("design:type", HTMLElement) ], GridPanel.prototype, "eTop", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eLeftTop"), __metadata("design:type", HTMLElement) ], GridPanel.prototype, "eLeftTop", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eRightTop"), __metadata("design:type", HTMLElement) ], GridPanel.prototype, "eRightTop", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eTopContainer"), __metadata("design:type", HTMLElement) ], GridPanel.prototype, "eTopContainer", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eTopViewport"), __metadata("design:type", HTMLElement) ], GridPanel.prototype, "eTopViewport", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eTopFullWidthContainer"), __metadata("design:type", HTMLElement) ], GridPanel.prototype, "eTopFullWidthContainer", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eBottom"), __metadata("design:type", HTMLElement) ], GridPanel.prototype, "eBottom", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eLeftBottom"), __metadata("design:type", HTMLElement) ], GridPanel.prototype, "eLeftBottom", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eRightBottom"), __metadata("design:type", HTMLElement) ], GridPanel.prototype, "eRightBottom", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eBottomContainer"), __metadata("design:type", HTMLElement) ], GridPanel.prototype, "eBottomContainer", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eBottomViewport"), __metadata("design:type", HTMLElement) ], GridPanel.prototype, "eBottomViewport", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eBottomFullWidthContainer"), __metadata("design:type", HTMLElement) ], GridPanel.prototype, "eBottomFullWidthContainer", void 0);
            __decorate([ componentAnnotations_1.RefSelector("headerRoot"), __metadata("design:type", headerRootComp_1.HeaderRootComp) ], GridPanel.prototype, "headerRootComp", void 0);
            __decorate([ context_1.PreDestroy, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], GridPanel.prototype, "destroy", null);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], GridPanel.prototype, "init", null);
            return GridPanel;
        }(component_1.Component);
        exports.GridPanel = GridPanel;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var beans_1 = __webpack_require__(28);
        var cellComp_1 = __webpack_require__(34);
        var columnController_1 = __webpack_require__(4);
        var utils_1 = __webpack_require__(1);
        var AutoHeightCalculator = function() {
            function AutoHeightCalculator() {}
            AutoHeightCalculator.prototype.registerGridComp = function(gridPanel) {
                this.gridPanel = gridPanel;
            };
            AutoHeightCalculator.prototype.getPreferredHeightForRow = function(rowNode) {
                var _this = this;
                if (!this.eDummyContainer) {
                    this.eDummyContainer = document.createElement("div");
                    utils_1._.addCssClass(this.eDummyContainer, "ag-row ag-row-no-focus");
                }
                var eBodyContainer = this.gridPanel.getBodyContainer();
                eBodyContainer.appendChild(this.eDummyContainer);
                var cellComps = [];
                var cols = this.columnController.getAllAutoRowHeightCols();
                console.log();
                cols.forEach(function(col) {
                    var cellComp = new cellComp_1.CellComp(_this.$scope, _this.beans, col, rowNode, null, true);
                    cellComp.setParentRow(_this.eDummyContainer);
                    cellComps.push(cellComp);
                });
                var template = cellComps.map(function(cellComp) {
                    return cellComp.getCreateTemplate();
                }).join(" ");
                this.eDummyContainer.innerHTML = template;
                cellComps.forEach(function(cellComp) {
                    return cellComp.afterAttached();
                });
                var maxCellHeight = 0;
                for (var i = 0; i < this.eDummyContainer.children.length; i++) {
                    var child = this.eDummyContainer.children[i];
                    if (child.offsetHeight > maxCellHeight) {
                        maxCellHeight = child.offsetHeight;
                    }
                }
                eBodyContainer.removeChild(this.eDummyContainer);
                cellComps.forEach(function(cellComp) {
                    cellComp.detach();
                    cellComp.destroy();
                });
                utils_1._.removeAllChildren(this.eDummyContainer);
                return maxCellHeight;
            };
            __decorate([ context_1.Autowired("beans"), __metadata("design:type", beans_1.Beans) ], AutoHeightCalculator.prototype, "beans", void 0);
            __decorate([ context_1.Autowired("$scope"), __metadata("design:type", Object) ], AutoHeightCalculator.prototype, "$scope", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], AutoHeightCalculator.prototype, "columnController", void 0);
            AutoHeightCalculator = __decorate([ context_1.Bean("autoHeightCalculator") ], AutoHeightCalculator);
            return AutoHeightCalculator;
        }();
        exports.AutoHeightCalculator = AutoHeightCalculator;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var columnController_1 = __webpack_require__(4);
        var column_1 = __webpack_require__(10);
        var context_1 = __webpack_require__(0);
        var headerContainer_1 = __webpack_require__(98);
        var eventService_1 = __webpack_require__(3);
        var events_1 = __webpack_require__(5);
        var scrollVisibleService_1 = __webpack_require__(36);
        var component_1 = __webpack_require__(8);
        var componentAnnotations_1 = __webpack_require__(11);
        var utils_1 = __webpack_require__(1);
        var gridApi_1 = __webpack_require__(6);
        var autoWidthCalculator_1 = __webpack_require__(39);
        var HeaderRootComp = function(_super) {
            __extends(HeaderRootComp, _super);
            function HeaderRootComp() {
                return _super.call(this, HeaderRootComp.TEMPLATE) || this;
            }
            HeaderRootComp.prototype.registerGridComp = function(gridPanel) {
                this.gridPanel = gridPanel;
                this.centerContainer.registerGridComp(gridPanel);
                this.pinnedLeftContainer.registerGridComp(gridPanel);
                this.pinnedRightContainer.registerGridComp(gridPanel);
            };
            HeaderRootComp.prototype.postConstruct = function() {
                var _this = this;
                this.gridApi.registerHeaderRootComp(this);
                this.autoWidthCalculator.registerHeaderRootComp(this);
                this.centerContainer = new headerContainer_1.HeaderContainer(this.eHeaderContainer, this.eHeaderViewport, null);
                this.childContainers = [ this.centerContainer ];
                this.pinnedLeftContainer = new headerContainer_1.HeaderContainer(this.ePinnedLeftHeader, null, column_1.Column.PINNED_LEFT);
                this.pinnedRightContainer = new headerContainer_1.HeaderContainer(this.ePinnedRightHeader, null, column_1.Column.PINNED_RIGHT);
                this.childContainers.push(this.pinnedLeftContainer);
                this.childContainers.push(this.pinnedRightContainer);
                this.childContainers.forEach(function(container) {
                    return _this.context.wireBean(container);
                });
                this.eventService.addEventListener(events_1.Events.EVENT_COLUMN_VALUE_CHANGED, this.refreshHeader.bind(this));
                this.eventService.addEventListener(events_1.Events.EVENT_COLUMN_PIVOT_MODE_CHANGED, this.onPivotModeChanged.bind(this));
                this.addPreventHeaderScroll();
                if (this.columnController.isReady()) {
                    this.refreshHeader();
                }
            };
            HeaderRootComp.prototype.setHorizontalScroll = function(offset) {
                this.eHeaderContainer.style.left = offset + "px";
            };
            HeaderRootComp.prototype.forEachHeaderElement = function(callback) {
                this.childContainers.forEach(function(childContainer) {
                    return childContainer.forEachHeaderElement(callback);
                });
            };
            HeaderRootComp.prototype.destroy = function() {
                this.childContainers.forEach(function(container) {
                    return container.destroy();
                });
            };
            HeaderRootComp.prototype.refreshHeader = function() {
                this.childContainers.forEach(function(container) {
                    return container.refresh();
                });
            };
            HeaderRootComp.prototype.onPivotModeChanged = function() {
                var pivotMode = this.columnController.isPivotMode();
                utils_1.Utils.addOrRemoveCssClass(this.getGui(), "ag-pivot-on", pivotMode);
                utils_1.Utils.addOrRemoveCssClass(this.getGui(), "ag-pivot-off", !pivotMode);
            };
            HeaderRootComp.prototype.setHeight = function(height) {
                this.getGui().style.height = height + "px";
                this.getGui().style.minHeight = height + "px";
            };
            HeaderRootComp.prototype.addPreventHeaderScroll = function() {
                var _this = this;
                this.addDestroyableEventListener(this.eHeaderViewport, "scroll", function() {
                    var scrollLeft = _this.eHeaderViewport.scrollLeft;
                    if (scrollLeft !== 0) {
                        _this.gridPanel.scrollHorizontally(scrollLeft);
                        _this.eHeaderViewport.scrollLeft = 0;
                    }
                });
            };
            HeaderRootComp.prototype.setLeftVisible = function(visible) {
                utils_1.Utils.setVisible(this.ePinnedLeftHeader, visible);
            };
            HeaderRootComp.prototype.setRightVisible = function(visible) {
                utils_1.Utils.setVisible(this.ePinnedRightHeader, visible);
            };
            HeaderRootComp.TEMPLATE = '<div class="ag-header" role="row">\n            <div class="ag-pinned-left-header" ref="ePinnedLeftHeader" role="presentation"></div>\n            <div class="ag-header-viewport" ref="eHeaderViewport" role="presentation">\n                <div class="ag-header-container" ref="eHeaderContainer" role="presentation"></div>\n            </div>\n            <div class="ag-pinned-right-header" ref="ePinnedRightHeader" role="presentation"></div>\n        </div>';
            __decorate([ componentAnnotations_1.RefSelector("ePinnedLeftHeader"), __metadata("design:type", HTMLElement) ], HeaderRootComp.prototype, "ePinnedLeftHeader", void 0);
            __decorate([ componentAnnotations_1.RefSelector("ePinnedRightHeader"), __metadata("design:type", HTMLElement) ], HeaderRootComp.prototype, "ePinnedRightHeader", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eHeaderContainer"), __metadata("design:type", HTMLElement) ], HeaderRootComp.prototype, "eHeaderContainer", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eHeaderViewport"), __metadata("design:type", HTMLElement) ], HeaderRootComp.prototype, "eHeaderViewport", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], HeaderRootComp.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], HeaderRootComp.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], HeaderRootComp.prototype, "context", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], HeaderRootComp.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("scrollVisibleService"), __metadata("design:type", scrollVisibleService_1.ScrollVisibleService) ], HeaderRootComp.prototype, "scrollVisibleService", void 0);
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], HeaderRootComp.prototype, "gridApi", void 0);
            __decorate([ context_1.Autowired("autoWidthCalculator"), __metadata("design:type", autoWidthCalculator_1.AutoWidthCalculator) ], HeaderRootComp.prototype, "autoWidthCalculator", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], HeaderRootComp.prototype, "postConstruct", null);
            __decorate([ context_1.PreDestroy, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], HeaderRootComp.prototype, "destroy", null);
            return HeaderRootComp;
        }(component_1.Component);
        exports.HeaderRootComp = HeaderRootComp;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var CssClassApplier = function() {
            function CssClassApplier() {}
            CssClassApplier.addHeaderClassesFromColDef = function(abstractColDef, eHeaderCell, gridOptionsWrapper, column, columnGroup) {
                if (utils_1.Utils.missing(abstractColDef)) {
                    return;
                }
                this.addColumnClassesFromCollDef(abstractColDef.headerClass, abstractColDef, eHeaderCell, gridOptionsWrapper, column, columnGroup);
            };
            CssClassApplier.addToolPanelClassesFromColDef = function(abstractColDef, eHeaderCell, gridOptionsWrapper, column, columnGroup) {
                if (utils_1.Utils.missing(abstractColDef)) {
                    return;
                }
                this.addColumnClassesFromCollDef(abstractColDef.toolPanelClass, abstractColDef, eHeaderCell, gridOptionsWrapper, column, columnGroup);
            };
            CssClassApplier.addColumnClassesFromCollDef = function(classesOrFunc, abstractColDef, eHeaderCell, gridOptionsWrapper, column, columnGroup) {
                if (utils_1.Utils.missing(classesOrFunc)) {
                    return;
                }
                var classToUse;
                if (typeof classesOrFunc === "function") {
                    var params = {
                        colDef: abstractColDef,
                        column: column,
                        columnGroup: columnGroup,
                        context: gridOptionsWrapper.getContext(),
                        api: gridOptionsWrapper.getApi()
                    };
                    var headerClassFunc = classesOrFunc;
                    classToUse = headerClassFunc(params);
                } else {
                    classToUse = classesOrFunc;
                }
                if (typeof classToUse === "string") {
                    utils_1.Utils.addCssClass(eHeaderCell, classToUse);
                } else if (Array.isArray(classToUse)) {
                    classToUse.forEach(function(cssClassItem) {
                        utils_1.Utils.addCssClass(eHeaderCell, cssClassItem);
                    });
                }
            };
            return CssClassApplier;
        }();
        exports.CssClassApplier = CssClassApplier;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var constants_1 = __webpack_require__(9);
        var columnController_1 = __webpack_require__(4);
        var utils_1 = __webpack_require__(1);
        var gridRow_1 = __webpack_require__(64);
        var gridCell_1 = __webpack_require__(23);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var pinnedRowModel_1 = __webpack_require__(30);
        var CellNavigationService = function() {
            function CellNavigationService() {}
            CellNavigationService.prototype.getNextCellToFocus = function(key, lastCellToFocus) {
                var pointer = lastCellToFocus;
                var finished = false;
                while (!finished) {
                    switch (key) {
                      case constants_1.Constants.KEY_UP:
                        pointer = this.getCellAbove(pointer);
                        break;

                      case constants_1.Constants.KEY_DOWN:
                        pointer = this.getCellBelow(pointer);
                        break;

                      case constants_1.Constants.KEY_RIGHT:
                        if (this.gridOptionsWrapper.isEnableRtl()) {
                            pointer = this.getCellToLeft(pointer);
                        } else {
                            pointer = this.getCellToRight(pointer);
                        }
                        break;

                      case constants_1.Constants.KEY_LEFT:
                        if (this.gridOptionsWrapper.isEnableRtl()) {
                            pointer = this.getCellToRight(pointer);
                        } else {
                            pointer = this.getCellToLeft(pointer);
                        }
                        break;

                      default:
                        console.log("ag-Grid: unknown key for navigation " + key);
                        pointer = null;
                        break;
                    }
                    if (pointer) {
                        finished = this.isCellGoodToFocusOn(pointer);
                    } else {
                        finished = true;
                    }
                }
                return pointer;
            };
            CellNavigationService.prototype.isCellGoodToFocusOn = function(gridCell) {
                var column = gridCell.column;
                var rowNode;
                switch (gridCell.floating) {
                  case constants_1.Constants.PINNED_TOP:
                    rowNode = this.pinnedRowModel.getPinnedTopRow(gridCell.rowIndex);
                    break;

                  case constants_1.Constants.PINNED_BOTTOM:
                    rowNode = this.pinnedRowModel.getPinnedBottomRow(gridCell.rowIndex);
                    break;

                  default:
                    rowNode = this.rowModel.getRow(gridCell.rowIndex);
                    break;
                }
                var suppressNavigable = column.isSuppressNavigable(rowNode);
                return !suppressNavigable;
            };
            CellNavigationService.prototype.getCellToLeft = function(lastCell) {
                var colToLeft = this.columnController.getDisplayedColBefore(lastCell.column);
                if (!colToLeft) {
                    return null;
                } else {
                    var gridCellDef = {
                        rowIndex: lastCell.rowIndex,
                        column: colToLeft,
                        floating: lastCell.floating
                    };
                    return new gridCell_1.GridCell(gridCellDef);
                }
            };
            CellNavigationService.prototype.getCellToRight = function(lastCell) {
                var colToRight = this.columnController.getDisplayedColAfter(lastCell.column);
                if (!colToRight) {
                    return null;
                } else {
                    var gridCellDef = {
                        rowIndex: lastCell.rowIndex,
                        column: colToRight,
                        floating: lastCell.floating
                    };
                    return new gridCell_1.GridCell(gridCellDef);
                }
            };
            CellNavigationService.prototype.getRowBelow = function(lastRow) {
                if (this.isLastRowInContainer(lastRow)) {
                    if (lastRow.isFloatingBottom()) {
                        return null;
                    } else if (lastRow.isNotFloating()) {
                        if (this.pinnedRowModel.isRowsToRender(constants_1.Constants.PINNED_BOTTOM)) {
                            return new gridRow_1.GridRow(0, constants_1.Constants.PINNED_BOTTOM);
                        } else {
                            return null;
                        }
                    } else {
                        if (this.rowModel.isRowsToRender()) {
                            return new gridRow_1.GridRow(0, null);
                        } else if (this.pinnedRowModel.isRowsToRender(constants_1.Constants.PINNED_BOTTOM)) {
                            return new gridRow_1.GridRow(0, constants_1.Constants.PINNED_BOTTOM);
                        } else {
                            return null;
                        }
                    }
                } else {
                    return new gridRow_1.GridRow(lastRow.rowIndex + 1, lastRow.floating);
                }
            };
            CellNavigationService.prototype.getCellBelow = function(lastCell) {
                var rowBelow = this.getRowBelow(lastCell.getGridRow());
                if (rowBelow) {
                    var gridCellDef = {
                        rowIndex: rowBelow.rowIndex,
                        column: lastCell.column,
                        floating: rowBelow.floating
                    };
                    return new gridCell_1.GridCell(gridCellDef);
                } else {
                    return null;
                }
            };
            CellNavigationService.prototype.isLastRowInContainer = function(gridRow) {
                if (gridRow.isFloatingTop()) {
                    var lastTopIndex = this.pinnedRowModel.getPinnedTopRowData().length - 1;
                    return lastTopIndex <= gridRow.rowIndex;
                } else if (gridRow.isFloatingBottom()) {
                    var lastBottomIndex = this.pinnedRowModel.getPinnedBottomRowData().length - 1;
                    return lastBottomIndex <= gridRow.rowIndex;
                } else {
                    var lastBodyIndex = this.rowModel.getPageLastRow();
                    return lastBodyIndex <= gridRow.rowIndex;
                }
            };
            CellNavigationService.prototype.getRowAbove = function(lastRow) {
                if (lastRow.rowIndex === 0) {
                    if (lastRow.isFloatingTop()) {
                        return null;
                    } else if (lastRow.isNotFloating()) {
                        if (this.pinnedRowModel.isRowsToRender(constants_1.Constants.PINNED_TOP)) {
                            return this.getLastFloatingTopRow();
                        } else {
                            return null;
                        }
                    } else {
                        if (this.rowModel.isRowsToRender()) {
                            return this.getLastBodyCell();
                        } else if (this.pinnedRowModel.isRowsToRender(constants_1.Constants.PINNED_TOP)) {
                            return this.getLastFloatingTopRow();
                        } else {
                            return null;
                        }
                    }
                } else {
                    return new gridRow_1.GridRow(lastRow.rowIndex - 1, lastRow.floating);
                }
            };
            CellNavigationService.prototype.getCellAbove = function(lastCell) {
                var rowAbove = this.getRowAbove(lastCell.getGridRow());
                if (rowAbove) {
                    var gridCellDef = {
                        rowIndex: rowAbove.rowIndex,
                        column: lastCell.column,
                        floating: rowAbove.floating
                    };
                    return new gridCell_1.GridCell(gridCellDef);
                } else {
                    return null;
                }
            };
            CellNavigationService.prototype.getLastBodyCell = function() {
                var lastBodyRow = this.rowModel.getPageLastRow();
                return new gridRow_1.GridRow(lastBodyRow, null);
            };
            CellNavigationService.prototype.getLastFloatingTopRow = function() {
                var lastFloatingRow = this.pinnedRowModel.getPinnedTopRowData().length - 1;
                return new gridRow_1.GridRow(lastFloatingRow, constants_1.Constants.PINNED_TOP);
            };
            CellNavigationService.prototype.getNextTabbedCell = function(gridCell, backwards) {
                if (backwards) {
                    return this.getNextTabbedCellBackwards(gridCell);
                } else {
                    return this.getNextTabbedCellForwards(gridCell);
                }
            };
            CellNavigationService.prototype.getNextTabbedCellForwards = function(gridCell) {
                var displayedColumns = this.columnController.getAllDisplayedColumns();
                var newRowIndex = gridCell.rowIndex;
                var newFloating = gridCell.floating;
                var newColumn = this.columnController.getDisplayedColAfter(gridCell.column);
                if (!newColumn) {
                    newColumn = displayedColumns[0];
                    var rowBelow = this.getRowBelow(gridCell.getGridRow());
                    if (utils_1.Utils.missing(rowBelow)) {
                        return;
                    }
                    newRowIndex = rowBelow.rowIndex;
                    newFloating = rowBelow.floating;
                }
                var gridCellDef = {
                    rowIndex: newRowIndex,
                    column: newColumn,
                    floating: newFloating
                };
                return new gridCell_1.GridCell(gridCellDef);
            };
            CellNavigationService.prototype.getNextTabbedCellBackwards = function(gridCell) {
                var displayedColumns = this.columnController.getAllDisplayedColumns();
                var newRowIndex = gridCell.rowIndex;
                var newFloating = gridCell.floating;
                var newColumn = this.columnController.getDisplayedColBefore(gridCell.column);
                if (!newColumn) {
                    newColumn = displayedColumns[displayedColumns.length - 1];
                    var rowAbove = this.getRowAbove(gridCell.getGridRow());
                    if (utils_1.Utils.missing(rowAbove)) {
                        return;
                    }
                    newRowIndex = rowAbove.rowIndex;
                    newFloating = rowAbove.floating;
                }
                var gridCellDef = {
                    rowIndex: newRowIndex,
                    column: newColumn,
                    floating: newFloating
                };
                return new gridCell_1.GridCell(gridCellDef);
            };
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], CellNavigationService.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("rowModel"), __metadata("design:type", Object) ], CellNavigationService.prototype, "rowModel", void 0);
            __decorate([ context_1.Autowired("pinnedRowModel"), __metadata("design:type", pinnedRowModel_1.PinnedRowModel) ], CellNavigationService.prototype, "pinnedRowModel", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], CellNavigationService.prototype, "gridOptionsWrapper", void 0);
            CellNavigationService = __decorate([ context_1.Bean("cellNavigationService") ], CellNavigationService);
            return CellNavigationService;
        }();
        exports.CellNavigationService = CellNavigationService;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var GroupInstanceIdCreator = function() {
            function GroupInstanceIdCreator() {
                this.existingIds = {};
            }
            GroupInstanceIdCreator.prototype.getInstanceIdForKey = function(key) {
                var lastResult = this.existingIds[key];
                var result;
                if (typeof lastResult !== "number") {
                    result = 0;
                } else {
                    result = lastResult + 1;
                }
                this.existingIds[key] = result;
                return result;
            };
            return GroupInstanceIdCreator;
        }();
        exports.GroupInstanceIdCreator = GroupInstanceIdCreator;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var Downloader = function() {
            function Downloader() {}
            Downloader.prototype.download = function(fileName, content, mimeType) {
                var blobObject = new Blob([ "\ufeff", content ], {
                    type: mimeType
                });
                if (window.navigator.msSaveOrOpenBlob) {
                    window.navigator.msSaveOrOpenBlob(blobObject, fileName);
                } else {
                    var downloadLink = document.createElement("a");
                    downloadLink.href = window.URL.createObjectURL(blobObject);
                    downloadLink.download = fileName;
                    document.body.appendChild(downloadLink);
                    downloadLink.click();
                    document.body.removeChild(downloadLink);
                }
            };
            Downloader = __decorate([ context_1.Bean("downloader") ], Downloader);
            return Downloader;
        }();
        exports.Downloader = Downloader;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var selectionController_1 = __webpack_require__(17);
        var columnApi_1 = __webpack_require__(7);
        var columnController_1 = __webpack_require__(4);
        var rowRenderer_1 = __webpack_require__(20);
        var headerRootComp_1 = __webpack_require__(80);
        var filterManager_1 = __webpack_require__(18);
        var valueService_1 = __webpack_require__(16);
        var eventService_1 = __webpack_require__(3);
        var gridPanel_1 = __webpack_require__(78);
        var gridApi_1 = __webpack_require__(6);
        var balancedColumnTreeBuilder_1 = __webpack_require__(38);
        var displayedGroupCreator_1 = __webpack_require__(48);
        var expressionService_1 = __webpack_require__(19);
        var templateService_1 = __webpack_require__(49);
        var popupService_1 = __webpack_require__(35);
        var logger_1 = __webpack_require__(12);
        var columnUtils_1 = __webpack_require__(31);
        var autoWidthCalculator_1 = __webpack_require__(39);
        var horizontalResizeService_1 = __webpack_require__(59);
        var context_1 = __webpack_require__(0);
        var csvCreator_1 = __webpack_require__(47);
        var gridCore_1 = __webpack_require__(42);
        var standardMenu_1 = __webpack_require__(108);
        var dragAndDropService_1 = __webpack_require__(15);
        var dragService_1 = __webpack_require__(40);
        var sortController_1 = __webpack_require__(24);
        var focusedCellController_1 = __webpack_require__(22);
        var mouseEventService_1 = __webpack_require__(44);
        var cellNavigationService_1 = __webpack_require__(82);
        var utils_1 = __webpack_require__(1);
        var filterStage_1 = __webpack_require__(109);
        var sortStage_1 = __webpack_require__(111);
        var flattenStage_1 = __webpack_require__(113);
        var cellEditorFactory_1 = __webpack_require__(54);
        var events_1 = __webpack_require__(5);
        var infiniteRowModel_1 = __webpack_require__(114);
        var clientSideRowModel_1 = __webpack_require__(116);
        var cellRendererFactory_1 = __webpack_require__(55);
        var cellRendererService_1 = __webpack_require__(56);
        var valueFormatterService_1 = __webpack_require__(43);
        var agCheckbox_1 = __webpack_require__(60);
        var baseFrameworkFactory_1 = __webpack_require__(117);
        var scrollVisibleService_1 = __webpack_require__(36);
        var downloader_1 = __webpack_require__(84);
        var xmlFactory_1 = __webpack_require__(118);
        var gridSerializer_1 = __webpack_require__(63);
        var stylingService_1 = __webpack_require__(73);
        var columnHoverService_1 = __webpack_require__(45);
        var columnAnimationService_1 = __webpack_require__(53);
        var sortService_1 = __webpack_require__(112);
        var filterService_1 = __webpack_require__(110);
        var rowNodeFactory_1 = __webpack_require__(138);
        var autoGroupColService_1 = __webpack_require__(104);
        var paginationProxy_1 = __webpack_require__(29);
        var immutableService_1 = __webpack_require__(105);
        var constants_1 = __webpack_require__(9);
        var valueCache_1 = __webpack_require__(33);
        var changeDetectionService_1 = __webpack_require__(139);
        var alignedGridsService_1 = __webpack_require__(58);
        var pinnedRowModel_1 = __webpack_require__(30);
        var componentResolver_1 = __webpack_require__(27);
        var componentRecipes_1 = __webpack_require__(21);
        var componentProvider_1 = __webpack_require__(66);
        var agComponentUtils_1 = __webpack_require__(76);
        var componentMetadataProvider_1 = __webpack_require__(77);
        var beans_1 = __webpack_require__(28);
        var environment_1 = __webpack_require__(41);
        var animationFrameService_1 = __webpack_require__(37);
        var navigationService_1 = __webpack_require__(97);
        var heightScaler_1 = __webpack_require__(57);
        var selectableService_1 = __webpack_require__(86);
        var autoHeightCalculator_1 = __webpack_require__(79);
        var paginationComp_1 = __webpack_require__(140);
        var Grid = function() {
            function Grid(eGridDiv, gridOptions, params) {
                if (!eGridDiv) {
                    console.error("ag-Grid: no div element provided to the grid");
                }
                if (!gridOptions) {
                    console.error("ag-Grid: no gridOptions provided to the grid");
                }
                var rowModelClass = this.getRowModelClass(gridOptions);
                var enterprise = utils_1.Utils.exists(Grid.enterpriseBeans);
                var frameworkFactory = params ? params.frameworkFactory : null;
                if (utils_1.Utils.missing(frameworkFactory)) {
                    frameworkFactory = new baseFrameworkFactory_1.BaseFrameworkFactory();
                }
                var overrideBeans = [];
                if (Grid.enterpriseBeans) {
                    overrideBeans = overrideBeans.concat(Grid.enterpriseBeans);
                }
                if (Grid.frameworkBeans) {
                    overrideBeans = overrideBeans.concat(Grid.frameworkBeans);
                }
                var seed = {
                    enterprise: enterprise,
                    gridOptions: gridOptions,
                    eGridDiv: eGridDiv,
                    $scope: params ? params.$scope : null,
                    $compile: params ? params.$compile : null,
                    quickFilterOnScope: params ? params.quickFilterOnScope : null,
                    globalEventListener: params ? params.globalEventListener : null,
                    frameworkFactory: frameworkFactory
                };
                if (params && params.seedBeanInstances) {
                    utils_1.Utils.assign(seed, params.seedBeanInstances);
                }
                var components = [ {
                    componentName: "AgCheckbox",
                    theClass: agCheckbox_1.AgCheckbox
                }, {
                    componentName: "AgGridComp",
                    theClass: gridPanel_1.GridPanel
                }, {
                    componentName: "AgHeaderRoot",
                    theClass: headerRootComp_1.HeaderRootComp
                }, {
                    componentName: "AgPagination",
                    theClass: paginationComp_1.PaginationComp
                } ];
                if (Grid.enterpriseComponents) {
                    components = components.concat(Grid.enterpriseComponents);
                }
                var contextParams = {
                    overrideBeans: overrideBeans,
                    seed: seed,
                    beans: [ rowModelClass, beans_1.Beans, paginationProxy_1.PaginationAutoPageSizeService, gridApi_1.GridApi, componentProvider_1.ComponentProvider, agComponentUtils_1.AgComponentUtils, componentMetadataProvider_1.ComponentMetadataProvider, componentProvider_1.ComponentProvider, componentResolver_1.ComponentResolver, componentRecipes_1.ComponentRecipes, heightScaler_1.HeightScaler, autoHeightCalculator_1.AutoHeightCalculator, cellRendererFactory_1.CellRendererFactory, horizontalResizeService_1.HorizontalResizeService, pinnedRowModel_1.PinnedRowModel, dragService_1.DragService, displayedGroupCreator_1.DisplayedGroupCreator, eventService_1.EventService, gridOptionsWrapper_1.GridOptionsWrapper, selectionController_1.SelectionController, filterManager_1.FilterManager, columnController_1.ColumnController, paginationProxy_1.PaginationProxy, rowRenderer_1.RowRenderer, expressionService_1.ExpressionService, balancedColumnTreeBuilder_1.BalancedColumnTreeBuilder, csvCreator_1.CsvCreator, downloader_1.Downloader, xmlFactory_1.XmlFactory, gridSerializer_1.GridSerializer, templateService_1.TemplateService, navigationService_1.NavigationService, popupService_1.PopupService, valueCache_1.ValueCache, valueService_1.ValueService, alignedGridsService_1.AlignedGridsService, logger_1.LoggerFactory, columnUtils_1.ColumnUtils, autoWidthCalculator_1.AutoWidthCalculator, popupService_1.PopupService, gridCore_1.GridCore, standardMenu_1.StandardMenuFactory, dragAndDropService_1.DragAndDropService, columnApi_1.ColumnApi, focusedCellController_1.FocusedCellController, mouseEventService_1.MouseEventService, cellNavigationService_1.CellNavigationService, filterStage_1.FilterStage, sortStage_1.SortStage, flattenStage_1.FlattenStage, filterService_1.FilterService, rowNodeFactory_1.RowNodeFactory, cellEditorFactory_1.CellEditorFactory, cellRendererService_1.CellRendererService, valueFormatterService_1.ValueFormatterService, stylingService_1.StylingService, scrollVisibleService_1.ScrollVisibleService, columnHoverService_1.ColumnHoverService, columnAnimationService_1.ColumnAnimationService, sortService_1.SortService, selectableService_1.SelectableService, autoGroupColService_1.AutoGroupColService, immutableService_1.ImmutableService, changeDetectionService_1.ChangeDetectionService, environment_1.Environment, animationFrameService_1.AnimationFrameService, sortController_1.SortController ],
                    components: components,
                    debug: !!gridOptions.debug
                };
                var isLoggingFunc = function() {
                    return contextParams.debug;
                };
                this.context = new context_1.Context(contextParams, new logger_1.Logger("Context", isLoggingFunc));
                this.setColumnsAndData();
                this.dispatchGridReadyEvent(gridOptions);
                if (gridOptions.debug) {
                    console.log("ag-Grid -> initialised successfully, enterprise = " + enterprise);
                }
            }
            Grid.setEnterpriseBeans = function(enterpriseBeans, rowModelClasses) {
                this.enterpriseBeans = enterpriseBeans;
                utils_1.Utils.iterateObject(rowModelClasses, function(key, value) {
                    return Grid.RowModelClasses[key] = value;
                });
            };
            Grid.setEnterpriseComponents = function(components) {
                this.enterpriseComponents = components;
            };
            Grid.setFrameworkBeans = function(frameworkBeans) {
                this.frameworkBeans = frameworkBeans;
            };
            Grid.prototype.setColumnsAndData = function() {
                var gridOptionsWrapper = this.context.getBean("gridOptionsWrapper");
                var columnController = this.context.getBean("columnController");
                var rowModel = this.context.getBean("rowModel");
                var columnDefs = gridOptionsWrapper.getColumnDefs();
                var rowData = gridOptionsWrapper.getRowData();
                var nothingToSet = utils_1.Utils.missing(columnDefs) && utils_1.Utils.missing(rowData);
                if (nothingToSet) {
                    return;
                }
                if (utils_1.Utils.exists(columnDefs)) {
                    columnController.setColumnDefs(columnDefs, "gridInitializing");
                }
                if (utils_1.Utils.exists(rowData) && rowModel.getType() === constants_1.Constants.ROW_MODEL_TYPE_CLIENT_SIDE) {
                    var clientSideRowModel = rowModel;
                    clientSideRowModel.setRowData(rowData);
                }
            };
            Grid.prototype.dispatchGridReadyEvent = function(gridOptions) {
                var eventService = this.context.getBean("eventService");
                var readyEvent = {
                    type: events_1.Events.EVENT_GRID_READY,
                    api: gridOptions.api,
                    columnApi: gridOptions.columnApi
                };
                eventService.dispatchEvent(readyEvent);
            };
            Grid.prototype.getRowModelClass = function(gridOptions) {
                var rowModelType = gridOptions.rowModelType;
                rowModelType = rowModelType === "enterprise" ? constants_1.Constants.ROW_MODEL_TYPE_SERVER_SIDE : rowModelType;
                if (utils_1.Utils.exists(rowModelType)) {
                    var rowModelClass = Grid.RowModelClasses[rowModelType];
                    if (utils_1.Utils.exists(rowModelClass)) {
                        return rowModelClass;
                    } else {
                        if (rowModelType === "normal") {
                            console.warn("ag-Grid: normal rowModel deprecated. Should now be called client side row model instead.");
                            return clientSideRowModel_1.ClientSideRowModel;
                        }
                        console.error("ag-Grid: could not find matching row model for rowModelType " + rowModelType);
                        if (rowModelType === constants_1.Constants.ROW_MODEL_TYPE_VIEWPORT) {
                            console.error("ag-Grid: rowModelType viewport is only available in ag-Grid Enterprise");
                        }
                        if (rowModelType === constants_1.Constants.ROW_MODEL_TYPE_SERVER_SIDE) {
                            console.error("ag-Grid: rowModelType server side is only available in ag-Grid Enterprise");
                        }
                    }
                }
                return clientSideRowModel_1.ClientSideRowModel;
            };
            Grid.prototype.destroy = function() {
                this.context.destroy();
            };
            Grid.RowModelClasses = {
                infinite: infiniteRowModel_1.InfiniteRowModel,
                clientSide: clientSideRowModel_1.ClientSideRowModel
            };
            return Grid;
        }();
        exports.Grid = Grid;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var utils_1 = __webpack_require__(1);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var SelectableService = function() {
            function SelectableService() {}
            SelectableService.prototype.init = function() {
                this.groupSelectsChildren = this.gridOptionsWrapper.isGroupSelectsChildren();
                this.isRowSelectableFunc = this.gridOptionsWrapper.getIsRowSelectableFunc();
            };
            SelectableService.prototype.updateSelectableAfterGrouping = function(rowNode) {
                if (this.isRowSelectableFunc) {
                    var nextChildrenFunc = function(rowNode) {
                        return rowNode.childrenAfterGroup;
                    };
                    this.recurseDown(rowNode.childrenAfterGroup, nextChildrenFunc);
                }
            };
            SelectableService.prototype.updateSelectableAfterFiltering = function(rowNode) {
                if (this.isRowSelectableFunc) {
                    var nextChildrenFunc = function(rowNode) {
                        return rowNode.childrenAfterFilter;
                    };
                    this.recurseDown(rowNode.childrenAfterGroup, nextChildrenFunc);
                }
            };
            SelectableService.prototype.recurseDown = function(children, nextChildrenFunc) {
                var _this = this;
                children.forEach(function(child) {
                    if (!child.group) {
                        return;
                    }
                    if (child.hasChildren()) {
                        _this.recurseDown(nextChildrenFunc(child), nextChildrenFunc);
                    }
                    var rowSelectable;
                    if (_this.groupSelectsChildren) {
                        var firstSelectable = utils_1._.find(nextChildrenFunc(child), "selectable", true);
                        rowSelectable = utils_1._.exists(firstSelectable);
                    } else {
                        rowSelectable = _this.isRowSelectableFunc(child);
                    }
                    child.setRowSelectable(rowSelectable);
                });
            };
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], SelectableService.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], SelectableService.prototype, "init", null);
            SelectableService = __decorate([ context_1.Bean("selectableService") ], SelectableService);
            return SelectableService;
        }();
        exports.SelectableService = SelectableService;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var beanStub_1 = __webpack_require__(13);
        var rowNodeBlock_1 = __webpack_require__(61);
        var RowNodeCache = function(_super) {
            __extends(RowNodeCache, _super);
            function RowNodeCache(cacheParams) {
                var _this = _super.call(this) || this;
                _this.maxRowFound = false;
                _this.blocks = {};
                _this.blockCount = 0;
                _this.virtualRowCount = cacheParams.initialRowCount;
                _this.cacheParams = cacheParams;
                return _this;
            }
            RowNodeCache.prototype.destroy = function() {
                var _this = this;
                _super.prototype.destroy.call(this);
                this.forEachBlockInOrder(function(block) {
                    return _this.destroyBlock(block);
                });
            };
            RowNodeCache.prototype.init = function() {
                var _this = this;
                this.active = true;
                this.addDestroyFunc(function() {
                    return _this.active = false;
                });
            };
            RowNodeCache.prototype.isActive = function() {
                return this.active;
            };
            RowNodeCache.prototype.getVirtualRowCount = function() {
                return this.virtualRowCount;
            };
            RowNodeCache.prototype.hack_setVirtualRowCount = function(virtualRowCount) {
                this.virtualRowCount = virtualRowCount;
            };
            RowNodeCache.prototype.isMaxRowFound = function() {
                return this.maxRowFound;
            };
            RowNodeCache.prototype.onPageLoaded = function(event) {
                this.cacheParams.rowNodeBlockLoader.loadComplete();
                this.checkBlockToLoad();
                if (!this.isActive()) {
                    return;
                }
                this.logger.log("onPageLoaded: page = " + event.page.getBlockNumber() + ", lastRow = " + event.lastRow);
                if (event.success) {
                    this.checkVirtualRowCount(event.page, event.lastRow);
                }
            };
            RowNodeCache.prototype.purgeBlocksIfNeeded = function(blockToExclude) {
                var _this = this;
                if (utils_1.Utils.missing(this.cacheParams.maxBlocksInCache)) {
                    return;
                }
                if (this.blockCount <= this.cacheParams.maxBlocksInCache) {
                    return;
                }
                var blocksForPurging = [];
                this.forEachBlockInOrder(function(block) {
                    if (block === blockToExclude) {
                        return;
                    }
                    blocksForPurging.push(block);
                });
                blocksForPurging.sort(function(a, b) {
                    return b.getLastAccessed() - a.getLastAccessed();
                });
                var blocksToKeep = this.cacheParams.maxBlocksInCache - 1;
                blocksForPurging.splice(0, blocksToKeep);
                blocksForPurging.forEach(function(block) {
                    if (block.isAnyNodeOpen(_this.virtualRowCount)) {
                        return;
                    }
                    _this.removeBlockFromCache(block);
                });
            };
            RowNodeCache.prototype.postCreateBlock = function(newBlock) {
                newBlock.addEventListener(rowNodeBlock_1.RowNodeBlock.EVENT_LOAD_COMPLETE, this.onPageLoaded.bind(this));
                this.setBlock(newBlock.getBlockNumber(), newBlock);
                this.purgeBlocksIfNeeded(newBlock);
                this.checkBlockToLoad();
            };
            RowNodeCache.prototype.removeBlockFromCache = function(blockToRemove) {
                if (!blockToRemove) {
                    return;
                }
                this.destroyBlock(blockToRemove);
            };
            RowNodeCache.prototype.checkBlockToLoad = function() {
                this.cacheParams.rowNodeBlockLoader.checkBlockToLoad();
            };
            RowNodeCache.prototype.checkVirtualRowCount = function(block, lastRow) {
                if (typeof lastRow === "number" && lastRow >= 0) {
                    this.virtualRowCount = lastRow;
                    this.maxRowFound = true;
                    this.onCacheUpdated();
                } else if (!this.maxRowFound) {
                    var lastRowIndex = (block.getBlockNumber() + 1) * this.cacheParams.blockSize;
                    var lastRowIndexPlusOverflow = lastRowIndex + this.cacheParams.overflowSize;
                    if (this.virtualRowCount < lastRowIndexPlusOverflow) {
                        this.virtualRowCount = lastRowIndexPlusOverflow;
                        this.onCacheUpdated();
                    } else if (this.cacheParams.dynamicRowHeight) {
                        this.onCacheUpdated();
                    }
                }
            };
            RowNodeCache.prototype.setVirtualRowCount = function(rowCount, maxRowFound) {
                this.virtualRowCount = rowCount;
                if (utils_1.Utils.exists(maxRowFound)) {
                    this.maxRowFound = maxRowFound;
                }
                if (!this.maxRowFound) {
                    if (this.virtualRowCount % this.cacheParams.blockSize === 0) {
                        this.virtualRowCount++;
                    }
                }
                this.onCacheUpdated();
            };
            RowNodeCache.prototype.forEachNodeDeep = function(callback, sequence) {
                var _this = this;
                this.forEachBlockInOrder(function(block) {
                    block.forEachNodeDeep(callback, sequence, _this.virtualRowCount);
                });
            };
            RowNodeCache.prototype.forEachBlockInOrder = function(callback) {
                var ids = this.getBlockIdsSorted();
                this.forEachBlockId(ids, callback);
            };
            RowNodeCache.prototype.forEachBlockInReverseOrder = function(callback) {
                var ids = this.getBlockIdsSorted().reverse();
                this.forEachBlockId(ids, callback);
            };
            RowNodeCache.prototype.forEachBlockId = function(ids, callback) {
                var _this = this;
                ids.forEach(function(id) {
                    var block = _this.blocks[id];
                    callback(block, id);
                });
            };
            RowNodeCache.prototype.getBlockIdsSorted = function() {
                var numberComparator = function(a, b) {
                    return a - b;
                };
                var blockIds = Object.keys(this.blocks).map(function(idStr) {
                    return parseInt(idStr);
                }).sort(numberComparator);
                return blockIds;
            };
            RowNodeCache.prototype.getBlock = function(blockId) {
                return this.blocks[blockId];
            };
            RowNodeCache.prototype.setBlock = function(id, block) {
                this.blocks[id] = block;
                this.blockCount++;
                this.cacheParams.rowNodeBlockLoader.addBlock(block);
            };
            RowNodeCache.prototype.destroyBlock = function(block) {
                delete this.blocks[block.getBlockNumber()];
                block.destroy();
                this.blockCount--;
                this.cacheParams.rowNodeBlockLoader.removeBlock(block);
            };
            RowNodeCache.prototype.onCacheUpdated = function() {
                if (this.isActive()) {
                    var event_1 = {
                        type: RowNodeCache.EVENT_CACHE_UPDATED
                    };
                    this.dispatchEvent(event_1);
                }
            };
            RowNodeCache.prototype.purgeCache = function() {
                var _this = this;
                this.forEachBlockInOrder(function(block) {
                    return _this.removeBlockFromCache(block);
                });
                this.onCacheUpdated();
            };
            RowNodeCache.prototype.getRowNodesInRange = function(firstInRange, lastInRange) {
                var _this = this;
                var result = [];
                var lastBlockId = -1;
                var inActiveRange = false;
                var numberSequence = new utils_1.NumberSequence();
                if (utils_1.Utils.missing(firstInRange)) {
                    inActiveRange = true;
                }
                var foundGapInSelection = false;
                this.forEachBlockInOrder(function(block, id) {
                    if (foundGapInSelection) return;
                    if (inActiveRange && lastBlockId + 1 !== id) {
                        foundGapInSelection = true;
                        return;
                    }
                    lastBlockId = id;
                    block.forEachNodeShallow(function(rowNode) {
                        var hitFirstOrLast = rowNode === firstInRange || rowNode === lastInRange;
                        if (inActiveRange || hitFirstOrLast) {
                            result.push(rowNode);
                        }
                        if (hitFirstOrLast) {
                            inActiveRange = !inActiveRange;
                        }
                    }, numberSequence, _this.virtualRowCount);
                });
                var invalidRange = foundGapInSelection || inActiveRange;
                return invalidRange ? [] : result;
            };
            RowNodeCache.EVENT_CACHE_UPDATED = "cacheUpdated";
            return RowNodeCache;
        }(beanStub_1.BeanStub);
        exports.RowNodeCache = RowNodeCache;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var rowNode_1 = __webpack_require__(14);
        var utils_1 = __webpack_require__(1);
        var ClientSideNodeManager = function() {
            function ClientSideNodeManager(rootNode, gridOptionsWrapper, context, eventService, columnController) {
                this.nextId = 0;
                this.allNodesMap = {};
                this.rootNode = rootNode;
                this.gridOptionsWrapper = gridOptionsWrapper;
                this.context = context;
                this.eventService = eventService;
                this.columnController = columnController;
                this.rootNode.group = true;
                this.rootNode.level = -1;
                this.rootNode.id = ClientSideNodeManager.ROOT_NODE_ID;
                this.rootNode.allLeafChildren = [];
                this.rootNode.childrenAfterGroup = [];
                this.rootNode.childrenAfterSort = [];
                this.rootNode.childrenAfterFilter = [];
                this.postConstruct();
            }
            ClientSideNodeManager.prototype.postConstruct = function() {
                this.getNodeChildDetails = this.gridOptionsWrapper.getNodeChildDetailsFunc();
                this.suppressParentsInRowNodes = this.gridOptionsWrapper.isSuppressParentsInRowNodes();
                this.doesDataFlower = this.gridOptionsWrapper.getDoesDataFlowerFunc();
                this.isRowMasterFunc = this.gridOptionsWrapper.getIsRowMasterFunc();
                this.doingLegacyTreeData = utils_1.Utils.exists(this.getNodeChildDetails);
                this.doingMasterDetail = this.gridOptionsWrapper.isMasterDetail();
            };
            ClientSideNodeManager.prototype.getCopyOfNodesMap = function() {
                var result = utils_1.Utils.cloneObject(this.allNodesMap);
                return result;
            };
            ClientSideNodeManager.prototype.getRowNode = function(id) {
                return this.allNodesMap[id];
            };
            ClientSideNodeManager.prototype.setRowData = function(rowData) {
                this.rootNode.childrenAfterFilter = null;
                this.rootNode.childrenAfterGroup = null;
                this.rootNode.childrenAfterSort = null;
                this.rootNode.childrenMapped = null;
                this.nextId = 0;
                this.allNodesMap = {};
                if (!rowData) {
                    this.rootNode.allLeafChildren = [];
                    this.rootNode.childrenAfterGroup = [];
                    return;
                }
                var result = this.recursiveFunction(rowData, null, ClientSideNodeManager.TOP_LEVEL);
                if (this.doingLegacyTreeData) {
                    this.rootNode.childrenAfterGroup = result;
                    this.setLeafChildren(this.rootNode);
                } else {
                    this.rootNode.allLeafChildren = result;
                }
            };
            ClientSideNodeManager.prototype.updateRowData = function(rowDataTran, rowNodeOrder) {
                var _this = this;
                if (this.isLegacyTreeData()) {
                    return null;
                }
                var add = rowDataTran.add, addIndex = rowDataTran.addIndex, remove = rowDataTran.remove, update = rowDataTran.update;
                var rowNodeTransaction = {
                    remove: [],
                    update: [],
                    add: []
                };
                if (utils_1.Utils.exists(add)) {
                    var useIndex = typeof addIndex === "number" && addIndex >= 0;
                    if (useIndex) {
                        add.reverse().forEach(function(item) {
                            var newRowNode = _this.addRowNode(item, addIndex);
                            rowNodeTransaction.add.push(newRowNode);
                        });
                    } else {
                        add.forEach(function(item) {
                            var newRowNode = _this.addRowNode(item);
                            rowNodeTransaction.add.push(newRowNode);
                        });
                    }
                }
                if (utils_1.Utils.exists(remove)) {
                    remove.forEach(function(item) {
                        var removedRowNode = _this.updatedRowNode(item, false);
                        if (removedRowNode) {
                            rowNodeTransaction.remove.push(removedRowNode);
                        }
                    });
                }
                if (utils_1.Utils.exists(update)) {
                    update.forEach(function(item) {
                        var updatedRowNode = _this.updatedRowNode(item, true);
                        if (updatedRowNode) {
                            rowNodeTransaction.update.push(updatedRowNode);
                        }
                    });
                }
                if (rowNodeOrder) {
                    utils_1.Utils.sortRowNodesByOrder(this.rootNode.allLeafChildren, rowNodeOrder);
                }
                return rowNodeTransaction;
            };
            ClientSideNodeManager.prototype.addRowNode = function(data, index) {
                var newNode = this.createNode(data, null, ClientSideNodeManager.TOP_LEVEL);
                if (utils_1.Utils.exists(index)) {
                    utils_1.Utils.insertIntoArray(this.rootNode.allLeafChildren, newNode, index);
                } else {
                    this.rootNode.allLeafChildren.push(newNode);
                }
                return newNode;
            };
            ClientSideNodeManager.prototype.updatedRowNode = function(data, update) {
                var rowNodeIdFunc = this.gridOptionsWrapper.getRowNodeIdFunc();
                var rowNode;
                if (utils_1.Utils.exists(rowNodeIdFunc)) {
                    var id = rowNodeIdFunc(data);
                    rowNode = this.allNodesMap[id];
                    if (!rowNode) {
                        console.error("ag-Grid: could not find row id=" + id + ", data item was not found for this id");
                        return null;
                    }
                } else {
                    rowNode = utils_1.Utils.find(this.rootNode.allLeafChildren, function(rowNode) {
                        return rowNode.data === data;
                    });
                    if (!rowNode) {
                        console.error("ag-Grid: could not find data item as object was not found", data);
                        return null;
                    }
                }
                if (update) {
                    rowNode.updateData(data);
                } else {
                    rowNode.setSelected(false);
                    rowNode.clearRowTop();
                    utils_1.Utils.removeFromArray(this.rootNode.allLeafChildren, rowNode);
                    this.allNodesMap[rowNode.id] = undefined;
                }
                return rowNode;
            };
            ClientSideNodeManager.prototype.recursiveFunction = function(rowData, parent, level) {
                var _this = this;
                if (typeof rowData === "string") {
                    console.warn("ag-Grid: rowData must be an array, however you passed in a string. If you are loading JSON, make sure you convert the JSON string to JavaScript objects first");
                    return;
                }
                var rowNodes = [];
                rowData.forEach(function(dataItem) {
                    var node = _this.createNode(dataItem, parent, level);
                    rowNodes.push(node);
                });
                return rowNodes;
            };
            ClientSideNodeManager.prototype.createNode = function(dataItem, parent, level) {
                var node = new rowNode_1.RowNode();
                this.context.wireBean(node);
                var doingTreeData = this.gridOptionsWrapper.isTreeData();
                var doingLegacyTreeData = !doingTreeData && utils_1.Utils.exists(this.getNodeChildDetails);
                var nodeChildDetails = doingLegacyTreeData ? this.getNodeChildDetails(dataItem) : null;
                if (nodeChildDetails && nodeChildDetails.group) {
                    node.group = true;
                    node.childrenAfterGroup = this.recursiveFunction(nodeChildDetails.children, node, level + 1);
                    node.expanded = nodeChildDetails.expanded === true;
                    node.field = nodeChildDetails.field;
                    node.key = nodeChildDetails.key;
                    node.canFlower = node.master;
                    this.setLeafChildren(node);
                } else {
                    node.group = false;
                    if (doingTreeData) {
                        node.master = false;
                        node.expanded = false;
                    } else {
                        if (this.doesDataFlower) {
                            node.master = this.doesDataFlower(dataItem);
                        } else if (this.doingMasterDetail) {
                            if (this.isRowMasterFunc) {
                                node.master = this.isRowMasterFunc(dataItem);
                            } else {
                                node.master = true;
                            }
                        } else {
                            node.master = false;
                        }
                        var rowGroupColumns = this.columnController.getRowGroupColumns();
                        var numRowGroupColumns = rowGroupColumns ? rowGroupColumns.length : 0;
                        var masterRowLevel = level + numRowGroupColumns;
                        node.expanded = node.master ? this.isExpanded(masterRowLevel) : false;
                    }
                }
                node.canFlower = node.master;
                if (parent && !this.suppressParentsInRowNodes) {
                    node.parent = parent;
                }
                node.level = level;
                node.setDataAndId(dataItem, this.nextId.toString());
                this.allNodesMap[node.id] = node;
                this.nextId++;
                return node;
            };
            ClientSideNodeManager.prototype.isExpanded = function(level) {
                var expandByDefault = this.gridOptionsWrapper.getGroupDefaultExpanded();
                if (expandByDefault === -1) {
                    return true;
                } else {
                    return level < expandByDefault;
                }
            };
            ClientSideNodeManager.prototype.setLeafChildren = function(node) {
                node.allLeafChildren = [];
                if (node.childrenAfterGroup) {
                    node.childrenAfterGroup.forEach(function(childAfterGroup) {
                        if (childAfterGroup.group) {
                            if (childAfterGroup.allLeafChildren) {
                                childAfterGroup.allLeafChildren.forEach(function(leafChild) {
                                    return node.allLeafChildren.push(leafChild);
                                });
                            }
                        } else {
                            node.allLeafChildren.push(childAfterGroup);
                        }
                    });
                }
            };
            ClientSideNodeManager.prototype.insertItemsAtIndex = function(index, rowData) {
                if (this.isLegacyTreeData()) {
                    return null;
                }
                var nodeList = this.rootNode.allLeafChildren;
                if (index > nodeList.length) {
                    console.warn("ag-Grid: invalid index " + index + ", max index is " + nodeList.length);
                    return;
                }
                var newNodes = [];
                for (var i = rowData.length - 1; i >= 0; i--) {
                    var data = rowData[i];
                    var newNode = this.createNode(data, null, ClientSideNodeManager.TOP_LEVEL);
                    utils_1.Utils.insertIntoArray(nodeList, newNode, index);
                    newNodes.push(newNode);
                }
                return newNodes.length > 0 ? newNodes : null;
            };
            ClientSideNodeManager.prototype.addItems = function(items) {
                var nodeList = this.rootNode.allLeafChildren;
                return this.insertItemsAtIndex(nodeList.length, items);
            };
            ClientSideNodeManager.prototype.isLegacyTreeData = function() {
                var rowsAlreadyGrouped = utils_1.Utils.exists(this.gridOptionsWrapper.getNodeChildDetailsFunc());
                if (rowsAlreadyGrouped) {
                    console.warn("ag-Grid: adding and removing rows is not supported when using nodeChildDetailsFunc, ie it is not " + "supported for legacy tree data. Please see the docs on the new preferred way of providing tree data that works with delta updates.");
                    return true;
                } else {
                    return false;
                }
            };
            ClientSideNodeManager.TOP_LEVEL = 0;
            ClientSideNodeManager.ROOT_NODE_ID = "ROOT_NODE_ID";
            return ClientSideNodeManager;
        }();
        exports.ClientSideNodeManager = ClientSideNodeManager;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var ChangedPath = function() {
            function ChangedPath(keepingColumns) {
                this.active = true;
                this.nodeIdsToBoolean = {};
                this.nodeIdsToColumns = {};
                this.keepingColumns = keepingColumns;
            }
            ChangedPath.prototype.setInactive = function() {
                this.active = false;
            };
            ChangedPath.prototype.isActive = function() {
                return this.active;
            };
            ChangedPath.prototype.addParentNode = function(rowNode, columns) {
                var _this = this;
                this.validateActive();
                var pointer = rowNode;
                while (pointer) {
                    this.nodeIdsToBoolean[pointer.id] = true;
                    if (this.keepingColumns && columns) {
                        if (!this.nodeIdsToColumns[pointer.id]) {
                            this.nodeIdsToColumns[pointer.id] = {};
                        }
                        columns.forEach(function(col) {
                            return _this.nodeIdsToColumns[pointer.id][col.getId()] = true;
                        });
                    }
                    pointer = pointer.parent;
                }
            };
            ChangedPath.prototype.isInPath = function(rowNode) {
                this.validateActive();
                return this.nodeIdsToBoolean[rowNode.id];
            };
            ChangedPath.prototype.getValueColumnsForNode = function(rowNode, valueColumns) {
                this.validateActive();
                if (!this.keepingColumns) {
                    return valueColumns;
                }
                var colsForThisNode = this.nodeIdsToColumns[rowNode.id];
                var result = valueColumns.filter(function(col) {
                    return colsForThisNode[col.getId()];
                });
                return result;
            };
            ChangedPath.prototype.getNotValueColumnsForNode = function(rowNode, valueColumns) {
                this.validateActive();
                if (!this.keepingColumns) {
                    return null;
                }
                var colsForThisNode = this.nodeIdsToColumns[rowNode.id];
                var result = valueColumns.filter(function(col) {
                    return !colsForThisNode[col.getId()];
                });
                return result;
            };
            ChangedPath.prototype.validateActive = function() {
                if (!this.active) {
                    throw "ag-Grid: tried to work on an invalid changed path";
                }
            };
            return ChangedPath;
        }();
        exports.ChangedPath = ChangedPath;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var PropertyKeys = function() {
            function PropertyKeys() {}
            PropertyKeys.STRING_PROPERTIES = [ "sortingOrder", "rowClass", "rowSelection", "overlayLoadingTemplate", "overlayNoRowsTemplate", "quickFilterText", "rowModelType", "editType", "domLayout", "clipboardDeliminator", "rowGroupPanelShow", "multiSortKey", "pivotColumnGroupTotals", "pivotRowTotals" ];
            PropertyKeys.OBJECT_PROPERTIES = [ "components", "frameworkComponents", "rowStyle", "context", "autoGroupColumnDef", "groupColumnDef", "localeText", "icons", "datasource", "serverSideDatasource", "viewportDatasource", "groupRowRendererParams", "aggFuncs", "fullWidthCellRendererParams", "defaultColGroupDef", "defaultColDef", "defaultExportParams", "columnTypes", "rowClassRules", "detailGridOptions", "detailCellRendererParams", "loadingOverlayComponentParams", "noRowsOverlayComponentParams", "popupParent" ];
            PropertyKeys.ARRAY_PROPERTIES = [ "slaveGrids", "alignedGrids", "rowData", "columnDefs", "excelStyles", "pinnedTopRowData", "pinnedBottomRowData" ];
            PropertyKeys.NUMBER_PROPERTIES = [ "rowHeight", "detailRowHeight", "rowBuffer", "colWidth", "headerHeight", "groupHeaderHeight", "floatingFiltersHeight", "pivotHeaderHeight", "pivotGroupHeaderHeight", "groupDefaultExpanded", "minColWidth", "maxColWidth", "viewportRowModelPageSize", "viewportRowModelBufferSize", "layoutInterval", "autoSizePadding", "maxBlocksInCache", "maxConcurrentDatasourceRequests", "cacheOverflowSize", "paginationPageSize", "cacheBlockSize", "infiniteInitialRowCount", "scrollbarWidth", "paginationStartPage", "infiniteBlockSize", "batchUpdateWaitMillis" ];
            PropertyKeys.BOOLEAN_PROPERTIES = [ "toolPanelSuppressRowGroups", "toolPanelSuppressValues", "toolPanelSuppressPivots", "toolPanelSuppressPivotMode", "toolPanelSuppressSideButtons", "toolPanelSuppressColumnFilter", "toolPanelSuppressColumnSelectAll", "toolPanelSuppressColumnExpandAll", "suppressMakeColumnVisibleAfterUnGroup", "suppressRowClickSelection", "suppressCellSelection", "suppressHorizontalScroll", "debug", "enableColResize", "enableCellExpressions", "enableSorting", "enableServerSideSorting", "enableFilter", "enableServerSideFilter", "angularCompileRows", "angularCompileFilters", "angularCompileHeaders", "groupSuppressAutoColumn", "groupSelectsChildren", "groupIncludeFooter", "groupIncludeTotalFooter", "groupUseEntireRow", "groupSuppressRow", "groupSuppressBlankHeader", "forPrint", "suppressMenuHide", "rowDeselection", "unSortIcon", "suppressMultiSort", "singleClickEdit", "suppressLoadingOverlay", "suppressNoRowsOverlay", "suppressAutoSize", "suppressParentsInRowNodes", "showToolPanel", "suppressColumnMoveAnimation", "suppressMovableColumns", "suppressFieldDotNotation", "enableRangeSelection", "pivotPanelShow", "suppressTouch", "suppressAsyncEvents", "allowContextMenuWithControlKey", "suppressContextMenu", "suppressMenuFilterPanel", "suppressMenuMainPanel", "suppressMenuColumnPanel", "enableStatusBar", "alwaysShowStatusBar", "rememberGroupStateWhenNewData", "enableCellChangeFlash", "suppressDragLeaveHidesColumns", "suppressMiddleClickScrolls", "suppressPreventDefaultOnMouseWheel", "suppressUseColIdForGroups", "suppressCopyRowsToClipboard", "pivotMode", "suppressAggFuncInHeader", "suppressColumnVirtualisation", "suppressAggAtRootLevel", "suppressFocusAfterRefresh", "functionsPassive", "functionsReadOnly", "animateRows", "groupSelectsFiltered", "groupRemoveSingleChildren", "groupRemoveLowestSingleChildren", "enableRtl", "suppressClickEdit", "rowDragManaged", "suppressRowDrag", "enableGroupEdit", "embedFullWidthRows", "suppressTabbing", "suppressPaginationPanel", "floatingFilter", "groupHideOpenParents", "groupMultiAutoColumn", "pagination", "stopEditingWhenGridLosesFocus", "paginationAutoPageSize", "suppressScrollOnNewData", "purgeClosedRowNodes", "cacheQuickFilter", "deltaRowDataMode", "ensureDomOrder", "accentedSort", "pivotTotals", "suppressChangeDetection", "valueCache", "valueCacheNeverExpires", "aggregateOnlyChangedColumns", "suppressAnimationFrame", "suppressExcelExport", "suppressCsvExport", "treeData", "masterDetail", "suppressMultiRangeSelection", "enterMovesDownAfterEdit", "enterMovesDown", "suppressPropertyNamesCheck", "rowMultiSelectWithClick", "contractColumnSelection", "suppressEnterpriseResetOnNewColumns", "enableOldSetFilterModel", "suppressRowHoverHighlight", "gridAutoHeight", "suppressRowTransform", "suppressClipboardPaste" ];
            PropertyKeys.FUNCTION_PROPERTIES = [ "localeTextFunc", "groupRowInnerRenderer", "groupRowInnerRendererFramework", "dateComponent", "dateComponentFramework", "groupRowRenderer", "groupRowRendererFramework", "isExternalFilterPresent", "getRowHeight", "doesExternalFilterPass", "getRowClass", "getRowStyle", "getRowClassRules", "traverseNode", "getContextMenuItems", "getMainMenuItems", "processRowPostCreate", "processCellForClipboard", "getNodeChildDetails", "groupRowAggNodes", "getRowNodeId", "isFullWidthCell", "fullWidthCellRenderer", "fullWidthCellRendererFramework", "doesDataFlower", "processSecondaryColDef", "processSecondaryColGroupDef", "getBusinessKeyForNode", "sendToClipboard", "navigateToNextCell", "tabToNextCell", "getDetailRowData", "processCellFromClipboard", "getDocument", "postProcessPopup", "getChildCount", "getDataPath", "loadingOverlayComponent", "loadingOverlayComponentFramework", "noRowsOverlayComponent", "noRowsOverlayComponentFramework", "detailCellRenderer", "detailCellRendererFramework", "onGridReady", "defaultGroupSortComparator", "isRowMaster", "isRowSelectable", "postSort", "processHeaderForClipboard", "paginationNumberFormatter", "processDataFromClipboard" ];
            PropertyKeys.ALL_PROPERTIES = PropertyKeys.ARRAY_PROPERTIES.concat(PropertyKeys.OBJECT_PROPERTIES).concat(PropertyKeys.STRING_PROPERTIES).concat(PropertyKeys.NUMBER_PROPERTIES).concat(PropertyKeys.FUNCTION_PROPERTIES).concat(PropertyKeys.BOOLEAN_PROPERTIES);
            return PropertyKeys;
        }();
        exports.PropertyKeys = PropertyKeys;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var dateFilter_1 = __webpack_require__(68);
        var componentAnnotations_1 = __webpack_require__(11);
        var utils_1 = __webpack_require__(1);
        var componentRecipes_1 = __webpack_require__(21);
        var component_1 = __webpack_require__(8);
        var constants_1 = __webpack_require__(9);
        var InputTextFloatingFilterComp = function(_super) {
            __extends(InputTextFloatingFilterComp, _super);
            function InputTextFloatingFilterComp() {
                var _this = _super.call(this, '<div><input  ref="eColumnFloatingFilter" class="ag-floating-filter-input"></div>') || this;
                _this.lastKnownModel = null;
                return _this;
            }
            InputTextFloatingFilterComp.prototype.init = function(params) {
                this.onFloatingFilterChanged = params.onFloatingFilterChanged;
                this.currentParentModel = params.currentParentModel;
                var debounceMs = params.debounceMs != null ? params.debounceMs : 500;
                var toDebounce = utils_1._.debounce(this.syncUpWithParentFilter.bind(this), debounceMs);
                this.addDestroyableEventListener(this.eColumnFloatingFilter, "input", toDebounce);
                this.addDestroyableEventListener(this.eColumnFloatingFilter, "keypress", toDebounce);
                this.addDestroyableEventListener(this.eColumnFloatingFilter, "keydown", toDebounce);
                var columnDef = params.column.getDefinition();
                if (columnDef.filterParams && columnDef.filterParams.filterOptions && columnDef.filterParams.filterOptions.length === 1 && columnDef.filterParams.filterOptions[0] === "inRange") {
                    this.eColumnFloatingFilter.readOnly = true;
                }
            };
            InputTextFloatingFilterComp.prototype.onParentModelChanged = function(parentModel, combinedFilter) {
                if (combinedFilter != null) {
                    this.eColumnFloatingFilter.value = this.parseAsText(combinedFilter.condition1) + " " + combinedFilter.operator + " " + this.parseAsText(combinedFilter.condition2);
                    this.eColumnFloatingFilter.readOnly = true;
                    this.lastKnownModel = null;
                    this.eColumnFloatingFilter.title = this.eColumnFloatingFilter.value;
                    this.eColumnFloatingFilter.style.cursor = "default";
                    return;
                } else {
                    this.eColumnFloatingFilter.readOnly = false;
                }
                if (this.equalModels(this.lastKnownModel, parentModel)) {
                    if (!this.lastKnownModel && !parentModel) {
                        this.eColumnFloatingFilter.value = "";
                    }
                    return;
                }
                this.lastKnownModel = parentModel;
                var incomingTextValue = this.asFloatingFilterText(parentModel);
                if (incomingTextValue === this.eColumnFloatingFilter.value) {
                    return;
                }
                this.eColumnFloatingFilter.value = incomingTextValue;
                this.eColumnFloatingFilter.title = "";
            };
            InputTextFloatingFilterComp.prototype.syncUpWithParentFilter = function(e) {
                var model = this.asParentModel();
                if (this.equalModels(this.lastKnownModel, model)) {
                    return;
                }
                var modelUpdated = null;
                if (utils_1._.isKeyPressed(e, constants_1.Constants.KEY_ENTER)) {
                    modelUpdated = this.onFloatingFilterChanged({
                        model: model,
                        apply: true
                    });
                } else {
                    modelUpdated = this.onFloatingFilterChanged({
                        model: model,
                        apply: false
                    });
                }
                if (modelUpdated) {
                    this.lastKnownModel = model;
                }
            };
            InputTextFloatingFilterComp.prototype.equalModels = function(left, right) {
                if (utils_1._.referenceCompare(left, right)) {
                    return true;
                }
                if (!left || !right) {
                    return false;
                }
                if (Array.isArray(left) || Array.isArray(right)) {
                    return false;
                }
                return utils_1._.referenceCompare(left.type, right.type) && utils_1._.referenceCompare(left.filter, right.filter) && utils_1._.referenceCompare(left.filterTo, right.filterTo) && utils_1._.referenceCompare(left.filterType, right.filterType);
            };
            __decorate([ componentAnnotations_1.RefSelector("eColumnFloatingFilter"), __metadata("design:type", HTMLInputElement) ], InputTextFloatingFilterComp.prototype, "eColumnFloatingFilter", void 0);
            return InputTextFloatingFilterComp;
        }(component_1.Component);
        exports.InputTextFloatingFilterComp = InputTextFloatingFilterComp;
        var TextFloatingFilterComp = function(_super) {
            __extends(TextFloatingFilterComp, _super);
            function TextFloatingFilterComp() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            TextFloatingFilterComp.prototype.asFloatingFilterText = function(parentModel) {
                if (!parentModel) {
                    return "";
                }
                return parentModel.filter;
            };
            TextFloatingFilterComp.prototype.asParentModel = function() {
                var currentParentModel = this.currentParentModel();
                return {
                    type: currentParentModel.type,
                    filter: this.eColumnFloatingFilter.value,
                    filterType: "text"
                };
            };
            TextFloatingFilterComp.prototype.parseAsText = function(model) {
                return this.asFloatingFilterText(model);
            };
            return TextFloatingFilterComp;
        }(InputTextFloatingFilterComp);
        exports.TextFloatingFilterComp = TextFloatingFilterComp;
        var DateFloatingFilterComp = function(_super) {
            __extends(DateFloatingFilterComp, _super);
            function DateFloatingFilterComp() {
                var _this = _super !== null && _super.apply(this, arguments) || this;
                _this.lastKnownModel = null;
                return _this;
            }
            DateFloatingFilterComp.prototype.init = function(params) {
                this.onFloatingFilterChanged = params.onFloatingFilterChanged;
                this.currentParentModel = params.currentParentModel;
                var debounceMs = params.debounceMs != null ? params.debounceMs : 500;
                var toDebounce = utils_1._.debounce(this.onDateChanged.bind(this), debounceMs);
                var dateComponentParams = {
                    onDateChanged: toDebounce,
                    filterParams: params.column.getColDef().filterParams
                };
                this.dateComponentPromise = this.componentRecipes.newDateComponent(dateComponentParams);
                var body = utils_1._.loadTemplate("<div></div>");
                this.dateComponentPromise.then(function(dateComponent) {
                    body.appendChild(dateComponent.getGui());
                });
                this.setTemplateFromElement(body);
            };
            DateFloatingFilterComp.prototype.onDateChanged = function() {
                var parentModel = this.currentParentModel();
                var model = this.asParentModel();
                if (this.equalModels(parentModel, model)) {
                    return;
                }
                this.onFloatingFilterChanged({
                    model: model,
                    apply: true
                });
                this.lastKnownModel = model;
            };
            DateFloatingFilterComp.prototype.equalModels = function(left, right) {
                if (utils_1._.referenceCompare(left, right)) {
                    return true;
                }
                if (!left || !right) {
                    return false;
                }
                if (Array.isArray(left) || Array.isArray(right)) {
                    return false;
                }
                return utils_1._.referenceCompare(left.type, right.type) && utils_1._.referenceCompare(left.dateFrom, right.dateFrom) && utils_1._.referenceCompare(left.dateTo, right.dateTo) && utils_1._.referenceCompare(left.filterType, right.filterType);
            };
            DateFloatingFilterComp.prototype.asParentModel = function() {
                var currentParentModel = this.currentParentModel();
                var filterValueDate = this.dateComponentPromise.resolveNow(null, function(dateComponent) {
                    return dateComponent.getDate();
                });
                var filterValueText = utils_1._.serializeDateToYyyyMmDd(dateFilter_1.DateFilter.removeTimezone(filterValueDate), "-");
                return {
                    type: currentParentModel.type,
                    dateFrom: filterValueText,
                    dateTo: currentParentModel ? currentParentModel.dateTo : null,
                    filterType: "date"
                };
            };
            DateFloatingFilterComp.prototype.onParentModelChanged = function(parentModel) {
                this.lastKnownModel = parentModel;
                this.dateComponentPromise.then(function(dateComponent) {
                    if (!parentModel || !parentModel.dateFrom) {
                        dateComponent.setDate(null);
                        return;
                    }
                    dateComponent.setDate(utils_1._.parseYyyyMmDdToDate(parentModel.dateFrom, "-"));
                });
            };
            __decorate([ context_1.Autowired("componentRecipes"), __metadata("design:type", componentRecipes_1.ComponentRecipes) ], DateFloatingFilterComp.prototype, "componentRecipes", void 0);
            return DateFloatingFilterComp;
        }(component_1.Component);
        exports.DateFloatingFilterComp = DateFloatingFilterComp;
        var NumberFloatingFilterComp = function(_super) {
            __extends(NumberFloatingFilterComp, _super);
            function NumberFloatingFilterComp() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            NumberFloatingFilterComp.prototype.asFloatingFilterText = function(toParse) {
                var currentParentModel = this.currentParentModel();
                if (toParse == null && currentParentModel == null) {
                    return "";
                }
                if (toParse == null && currentParentModel != null && currentParentModel.type !== "inRange") {
                    this.eColumnFloatingFilter.readOnly = false;
                    return "";
                }
                if (currentParentModel != null && currentParentModel.type === "inRange") {
                    this.eColumnFloatingFilter.readOnly = true;
                    return this.parseAsText(currentParentModel);
                }
                this.eColumnFloatingFilter.readOnly = false;
                return this.parseAsText(toParse);
            };
            NumberFloatingFilterComp.prototype.parseAsText = function(model) {
                if (model.type && model.type === "inRange") {
                    var number_1 = this.asNumber(model.filter);
                    var numberTo = this.asNumber(model.filterTo);
                    return (number_1 ? number_1 + "" : "") + "-" + (numberTo ? numberTo + "" : "");
                }
                var number = this.asNumber(model.filter);
                return number != null ? number + "" : "";
            };
            NumberFloatingFilterComp.prototype.asParentModel = function() {
                var currentParentModel = this.currentParentModel();
                var filterValueNumber = this.asNumber(this.eColumnFloatingFilter.value);
                var filterValueText = this.eColumnFloatingFilter.value;
                var modelFilterValue = null;
                if (filterValueNumber == null && filterValueText === "") {
                    modelFilterValue = null;
                } else if (filterValueNumber == null) {
                    modelFilterValue = currentParentModel.filter;
                } else {
                    modelFilterValue = filterValueNumber;
                }
                return {
                    type: currentParentModel.type,
                    filter: modelFilterValue,
                    filterTo: !currentParentModel ? null : currentParentModel.filterTo,
                    filterType: "number"
                };
            };
            NumberFloatingFilterComp.prototype.asNumber = function(value) {
                if (value == null) {
                    return null;
                }
                if (value === "") {
                    return null;
                }
                var asNumber = Number(value);
                var invalidNumber = !utils_1._.isNumeric(asNumber);
                return invalidNumber ? null : asNumber;
            };
            return NumberFloatingFilterComp;
        }(InputTextFloatingFilterComp);
        exports.NumberFloatingFilterComp = NumberFloatingFilterComp;
        var SetFloatingFilterComp = function(_super) {
            __extends(SetFloatingFilterComp, _super);
            function SetFloatingFilterComp() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            SetFloatingFilterComp.prototype.init = function(params) {
                _super.prototype.init.call(this, params);
                this.eColumnFloatingFilter.readOnly = true;
            };
            SetFloatingFilterComp.prototype.asFloatingFilterText = function(parentModel) {
                this.eColumnFloatingFilter.readOnly = true;
                if (!parentModel) return "";
                var values = parentModel instanceof Array ? parentModel : parentModel.values;
                if (values.length === 0) {
                    return "";
                }
                var arrayToDisplay = values.length > 10 ? values.slice(0, 10).concat("...") : values;
                return "(" + values.length + ") " + arrayToDisplay.join(",");
            };
            SetFloatingFilterComp.prototype.parseAsText = function(model) {
                return this.asFloatingFilterText(model);
            };
            SetFloatingFilterComp.prototype.asParentModel = function() {
                if (this.eColumnFloatingFilter.value == null || this.eColumnFloatingFilter.value === "") {
                    return {
                        values: [],
                        filterType: "set"
                    };
                }
                return {
                    values: this.eColumnFloatingFilter.value.split(","),
                    filterType: "set"
                };
            };
            SetFloatingFilterComp.prototype.equalModels = function(left, right) {
                return false;
            };
            return SetFloatingFilterComp;
        }(InputTextFloatingFilterComp);
        exports.SetFloatingFilterComp = SetFloatingFilterComp;
        var ReadModelAsStringFloatingFilterComp = function(_super) {
            __extends(ReadModelAsStringFloatingFilterComp, _super);
            function ReadModelAsStringFloatingFilterComp() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            ReadModelAsStringFloatingFilterComp.prototype.init = function(params) {
                _super.prototype.init.call(this, params);
                this.eColumnFloatingFilter.readOnly = true;
            };
            ReadModelAsStringFloatingFilterComp.prototype.onParentModelChanged = function(parentModel) {
                this.eColumnFloatingFilter.value = this.asFloatingFilterText(this.currentParentModel());
            };
            ReadModelAsStringFloatingFilterComp.prototype.asFloatingFilterText = function(parentModel) {
                return parentModel;
            };
            ReadModelAsStringFloatingFilterComp.prototype.parseAsText = function(model) {
                return model;
            };
            ReadModelAsStringFloatingFilterComp.prototype.asParentModel = function() {
                return null;
            };
            return ReadModelAsStringFloatingFilterComp;
        }(InputTextFloatingFilterComp);
        exports.ReadModelAsStringFloatingFilterComp = ReadModelAsStringFloatingFilterComp;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var textCellEditor_1 = __webpack_require__(67);
        var PopupTextCellEditor = function(_super) {
            __extends(PopupTextCellEditor, _super);
            function PopupTextCellEditor() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            PopupTextCellEditor.prototype.isPopup = function() {
                return true;
            };
            return PopupTextCellEditor;
        }(textCellEditor_1.TextCellEditor);
        exports.PopupTextCellEditor = PopupTextCellEditor;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var selectCellEditor_1 = __webpack_require__(75);
        var PopupSelectCellEditor = function(_super) {
            __extends(PopupSelectCellEditor, _super);
            function PopupSelectCellEditor() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            PopupSelectCellEditor.prototype.isPopup = function() {
                return true;
            };
            return PopupSelectCellEditor;
        }(selectCellEditor_1.SelectCellEditor);
        exports.PopupSelectCellEditor = PopupSelectCellEditor;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var component_1 = __webpack_require__(8);
        var constants_1 = __webpack_require__(9);
        var utils_1 = __webpack_require__(1);
        var LargeTextCellEditor = function(_super) {
            __extends(LargeTextCellEditor, _super);
            function LargeTextCellEditor() {
                return _super.call(this, LargeTextCellEditor.TEMPLATE) || this;
            }
            LargeTextCellEditor.prototype.init = function(params) {
                this.params = params;
                this.focusAfterAttached = params.cellStartedEdit;
                this.textarea = document.createElement("textarea");
                this.textarea.maxLength = params.maxLength ? params.maxLength : "200";
                this.textarea.cols = params.cols ? params.cols : "60";
                this.textarea.rows = params.rows ? params.rows : "10";
                if (utils_1.Utils.exists(params.value)) {
                    this.textarea.value = params.value.toString();
                }
                this.getGui().querySelector(".ag-large-textarea").appendChild(this.textarea);
                this.addGuiEventListener("keydown", this.onKeyDown.bind(this));
            };
            LargeTextCellEditor.prototype.onKeyDown = function(event) {
                var key = event.which || event.keyCode;
                if (key == constants_1.Constants.KEY_LEFT || key == constants_1.Constants.KEY_UP || key == constants_1.Constants.KEY_RIGHT || key == constants_1.Constants.KEY_DOWN || event.shiftKey && key == constants_1.Constants.KEY_ENTER) {
                    event.stopPropagation();
                }
            };
            LargeTextCellEditor.prototype.afterGuiAttached = function() {
                if (this.focusAfterAttached) {
                    this.textarea.focus();
                }
            };
            LargeTextCellEditor.prototype.getValue = function() {
                return this.textarea.value;
            };
            LargeTextCellEditor.prototype.isPopup = function() {
                return true;
            };
            LargeTextCellEditor.TEMPLATE = '<div class="ag-large-text" tabindex="0">' + '<div class="ag-large-textarea"></div>' + "</div>";
            return LargeTextCellEditor;
        }(component_1.Component);
        exports.LargeTextCellEditor = LargeTextCellEditor;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var baseFilter_1 = __webpack_require__(51);
        var componentAnnotations_1 = __webpack_require__(11);
        var TextFilter = function(_super) {
            __extends(TextFilter, _super);
            function TextFilter() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            TextFilter.prototype.getDefaultType = function() {
                return baseFilter_1.BaseFilter.CONTAINS;
            };
            TextFilter.prototype.customInit = function() {
                this.comparator = this.filterParams.textCustomComparator ? this.filterParams.textCustomComparator : TextFilter.DEFAULT_COMPARATOR;
                this.formatter = this.filterParams.textFormatter ? this.filterParams.textFormatter : this.filterParams.caseSensitive == true ? TextFilter.DEFAULT_FORMATTER : TextFilter.DEFAULT_LOWERCASE_FORMATTER;
                _super.prototype.customInit.call(this);
            };
            TextFilter.prototype.modelFromFloatingFilter = function(from) {
                return {
                    type: this.filter,
                    filter: from,
                    filterType: "text"
                };
            };
            TextFilter.prototype.getApplicableFilterTypes = function() {
                return [ baseFilter_1.BaseFilter.EQUALS, baseFilter_1.BaseFilter.NOT_EQUAL, baseFilter_1.BaseFilter.STARTS_WITH, baseFilter_1.BaseFilter.ENDS_WITH, baseFilter_1.BaseFilter.CONTAINS, baseFilter_1.BaseFilter.NOT_CONTAINS ];
            };
            TextFilter.prototype.bodyTemplate = function(type) {
                var translate = this.translate.bind(this);
                var fieldId = type == baseFilter_1.FilterConditionType.MAIN ? "filterText" : "filterConditionText";
                return '<div class="ag-filter-body">\n            <input class="ag-filter-filter" id=' + fieldId + ' type="text" placeholder="' + translate("filterOoo", "Filter...") + '"/>\n        </div>';
            };
            TextFilter.prototype.initialiseFilterBodyUi = function(type) {
                _super.prototype.initialiseFilterBodyUi.call(this, type);
                this.addFilterChangedListener(type);
                this.setFilter(this.filterConditionText, baseFilter_1.FilterConditionType.CONDITION);
                this.setFilterType(this.filterCondition, baseFilter_1.FilterConditionType.CONDITION);
            };
            TextFilter.prototype.addFilterChangedListener = function(type) {
                var _this = this;
                var eElement = type === baseFilter_1.FilterConditionType.MAIN ? this.eFilterTextField : this.eFilterConditionTextField;
                var debounceMs = this.getDebounceMs(this.filterParams);
                var toDebounce = utils_1.Utils.debounce(function() {
                    return _this.onFilterTextFieldChanged(type);
                }, debounceMs);
                this.addDestroyableEventListener(eElement, "input", toDebounce);
            };
            TextFilter.prototype.refreshFilterBodyUi = function(type) {
                if (this.eFilterConditionTextField) {
                    this.addFilterChangedListener(baseFilter_1.FilterConditionType.CONDITION);
                }
            };
            TextFilter.prototype.afterGuiAttached = function() {
                this.eFilterTextField.focus();
            };
            TextFilter.prototype.filterValues = function(type) {
                return type === baseFilter_1.FilterConditionType.MAIN ? this.filterText : this.filterConditionText;
            };
            TextFilter.prototype.individualFilterPasses = function(params, type) {
                var filterText = type == baseFilter_1.FilterConditionType.MAIN ? this.filterText : this.filterConditionText;
                var filter = type == baseFilter_1.FilterConditionType.MAIN ? this.filter : this.filterCondition;
                if (!filterText) {
                    return type === baseFilter_1.FilterConditionType.MAIN ? true : this.conditionValue === "AND";
                } else {
                    return this.checkIndividualFilter(params, filter, filterText);
                }
            };
            TextFilter.prototype.checkIndividualFilter = function(params, filterType, filterText) {
                var value = this.filterParams.valueGetter(params.node);
                if (!value) {
                    return filterType === baseFilter_1.BaseFilter.NOT_EQUAL || filterType === baseFilter_1.BaseFilter.NOT_CONTAINS;
                }
                var valueFormatted = this.formatter(value);
                return this.comparator(filterType, valueFormatted, filterText);
            };
            TextFilter.prototype.onFilterTextFieldChanged = function(type) {
                var value = type === baseFilter_1.FilterConditionType.MAIN ? this.eFilterTextField.value : this.eFilterConditionTextField.value;
                var current = type === baseFilter_1.FilterConditionType.MAIN ? this.filterText : this.filterConditionText;
                var filterText = utils_1.Utils.makeNull(value);
                if (filterText && filterText.trim() === "") {
                    filterText = null;
                }
                if (current !== filterText) {
                    var newLowerCase = filterText && this.filterParams.caseSensitive != true ? filterText.toLowerCase() : filterText;
                    var previousLowerCase = current && this.filterParams.caseSensitive != true ? current.toLowerCase() : current;
                    if (type === baseFilter_1.FilterConditionType.MAIN) {
                        this.filterText = this.formatter(filterText);
                    } else {
                        this.filterConditionText = this.formatter(filterText);
                    }
                    if (previousLowerCase !== newLowerCase) {
                        this.onFilterChanged();
                    }
                }
            };
            TextFilter.prototype.setFilter = function(filter, type) {
                filter = utils_1.Utils.makeNull(filter);
                if (type === baseFilter_1.FilterConditionType.MAIN) {
                    if (filter) {
                        this.filterText = this.formatter(filter);
                        if (!this.eFilterTextField) return;
                        this.eFilterTextField.value = filter;
                    } else {
                        this.filterText = null;
                        if (!this.eFilterTextField) return;
                        this.eFilterTextField.value = null;
                    }
                } else {
                    if (filter) {
                        this.filterConditionText = this.formatter(filter);
                        if (!this.eFilterConditionTextField) return;
                        this.eFilterConditionTextField.value = filter;
                    } else {
                        this.filterConditionText = null;
                        if (!this.eFilterConditionTextField) return;
                        this.eFilterConditionTextField.value = null;
                    }
                }
            };
            TextFilter.prototype.getFilter = function() {
                return this.filterText;
            };
            TextFilter.prototype.resetState = function() {
                this.setFilter(null, baseFilter_1.FilterConditionType.MAIN);
                this.setFilterType(this.defaultFilter, baseFilter_1.FilterConditionType.MAIN);
                this.setFilter(null, baseFilter_1.FilterConditionType.CONDITION);
                this.setFilterType(this.defaultFilter, baseFilter_1.FilterConditionType.CONDITION);
            };
            TextFilter.prototype.serialize = function(type) {
                var filter = type === baseFilter_1.FilterConditionType.MAIN ? this.filter : this.filterCondition;
                var filterText = type === baseFilter_1.FilterConditionType.MAIN ? this.filterText : this.filterConditionText;
                return {
                    type: filter ? filter : this.defaultFilter,
                    filter: filterText,
                    filterType: "text"
                };
            };
            TextFilter.prototype.parse = function(model, type) {
                this.setFilterType(model.type, type);
                this.setFilter(model.filter, type);
            };
            TextFilter.prototype.setType = function(filterType, type) {
                this.setFilterType(filterType, type);
            };
            TextFilter.DEFAULT_FORMATTER = function(from) {
                return from;
            };
            TextFilter.DEFAULT_LOWERCASE_FORMATTER = function(from) {
                if (from == null) {
                    return null;
                }
                return from.toString().toLowerCase();
            };
            TextFilter.DEFAULT_COMPARATOR = function(filter, value, filterText) {
                switch (filter) {
                  case TextFilter.CONTAINS:
                    return value.indexOf(filterText) >= 0;

                  case TextFilter.NOT_CONTAINS:
                    return value.indexOf(filterText) === -1;

                  case TextFilter.EQUALS:
                    return value === filterText;

                  case TextFilter.NOT_EQUAL:
                    return value != filterText;

                  case TextFilter.STARTS_WITH:
                    return value.indexOf(filterText) === 0;

                  case TextFilter.ENDS_WITH:
                    var index = value.lastIndexOf(filterText);
                    return index >= 0 && index === value.length - filterText.length;

                  default:
                    console.warn("invalid filter type " + filter);
                    return false;
                }
            };
            __decorate([ componentAnnotations_1.QuerySelector("#filterText"), __metadata("design:type", HTMLInputElement) ], TextFilter.prototype, "eFilterTextField", void 0);
            __decorate([ componentAnnotations_1.QuerySelector("#filterConditionText"), __metadata("design:type", HTMLInputElement) ], TextFilter.prototype, "eFilterConditionTextField", void 0);
            return TextFilter;
        }(baseFilter_1.ComparableBaseFilter);
        exports.TextFilter = TextFilter;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var componentAnnotations_1 = __webpack_require__(11);
        var baseFilter_1 = __webpack_require__(51);
        var NumberFilter = function(_super) {
            __extends(NumberFilter, _super);
            function NumberFilter() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            NumberFilter.prototype.modelFromFloatingFilter = function(from) {
                return {
                    type: this.filter,
                    filter: Number(from),
                    filterTo: this.filterNumberTo,
                    filterType: "number"
                };
            };
            NumberFilter.prototype.getApplicableFilterTypes = function() {
                return [ baseFilter_1.BaseFilter.EQUALS, baseFilter_1.BaseFilter.NOT_EQUAL, baseFilter_1.BaseFilter.LESS_THAN, baseFilter_1.BaseFilter.LESS_THAN_OR_EQUAL, baseFilter_1.BaseFilter.GREATER_THAN, baseFilter_1.BaseFilter.GREATER_THAN_OR_EQUAL, baseFilter_1.BaseFilter.IN_RANGE ];
            };
            NumberFilter.prototype.bodyTemplate = function(type) {
                var translate = this.translate.bind(this);
                var fieldId = type == baseFilter_1.FilterConditionType.MAIN ? "filterText" : "filterConditionText";
                var filterNumberToPanelId = type == baseFilter_1.FilterConditionType.MAIN ? "filterNumberToPanel" : "filterNumberToPanelCondition";
                var fieldToId = type == baseFilter_1.FilterConditionType.MAIN ? "filterToText" : "filterToConditionText";
                return '<div class="ag-filter-body">\n            <div>\n                <input class="ag-filter-filter" id="' + fieldId + '" type="text" placeholder="' + translate("filterOoo") + '"/>\n            </div>\n             <div class="ag-filter-number-to" id="' + filterNumberToPanelId + '">\n                <input class="ag-filter-filter" id="' + fieldToId + '" type="text" placeholder="' + translate("filterOoo") + '"/>\n            </div>\n        </div>';
            };
            NumberFilter.prototype.initialiseFilterBodyUi = function(type) {
                _super.prototype.initialiseFilterBodyUi.call(this, type);
                if (type === baseFilter_1.FilterConditionType.MAIN) {
                    this.eFilterTextField = this.queryForHtmlInputElement("#filterText");
                    this.addFilterChangedEventListeners(type, this.eFilterTextField, this.eFilterToTextField);
                } else {
                    this.eFilterTextConditionField = this.queryForHtmlInputElement("#filterConditionText");
                    this.addFilterChangedEventListeners(type, this.eFilterTextConditionField, this.eFilterToConditionText);
                    this.setFilter(this.filterNumberCondition, baseFilter_1.FilterConditionType.CONDITION);
                    this.setFilterTo(this.filterNumberConditionTo, baseFilter_1.FilterConditionType.CONDITION);
                    this.setFilterType(this.filterCondition, baseFilter_1.FilterConditionType.CONDITION);
                }
            };
            NumberFilter.prototype.addFilterChangedEventListeners = function(type, filterElement, filterToElement) {
                var _this = this;
                var debounceMs = this.getDebounceMs(this.filterParams);
                var toDebounce = utils_1.Utils.debounce(function() {
                    return _this.onTextFieldsChanged(type, filterElement, filterToElement);
                }, debounceMs);
                this.addDestroyableEventListener(filterElement, "input", toDebounce);
                this.addDestroyableEventListener(filterToElement, "input", toDebounce);
            };
            NumberFilter.prototype.afterGuiAttached = function() {
                this.eFilterTextField.focus();
            };
            NumberFilter.prototype.comparator = function() {
                return function(left, right) {
                    if (left === right) {
                        return 0;
                    }
                    if (left < right) {
                        return 1;
                    }
                    if (left > right) {
                        return -1;
                    }
                };
            };
            NumberFilter.prototype.onTextFieldsChanged = function(type, filterElement, filterToElement) {
                var newFilter = this.stringToFloat(filterElement.value);
                var newFilterTo = this.stringToFloat(filterToElement.value);
                if (type === baseFilter_1.FilterConditionType.MAIN) {
                    if (this.filterNumber !== newFilter || this.filterNumberTo !== newFilterTo) {
                        this.filterNumber = newFilter;
                        this.filterNumberTo = newFilterTo;
                        this.onFilterChanged();
                    }
                } else {
                    if (this.filterNumberCondition !== newFilter || this.filterNumberConditionTo !== newFilterTo) {
                        this.filterNumberCondition = newFilter;
                        this.filterNumberConditionTo = newFilterTo;
                        this.onFilterChanged();
                    }
                }
            };
            NumberFilter.prototype.filterValues = function(type) {
                if (type === baseFilter_1.FilterConditionType.MAIN) {
                    return this.filter !== baseFilter_1.BaseFilter.IN_RANGE ? this.asNumber(this.filterNumber) : [ this.asNumber(this.filterNumber), this.asNumber(this.filterNumberTo) ];
                }
                return this.filterCondition !== baseFilter_1.BaseFilter.IN_RANGE ? this.asNumber(this.filterNumberCondition) : [ this.asNumber(this.filterNumberCondition), this.asNumber(this.filterNumberConditionTo) ];
            };
            NumberFilter.prototype.asNumber = function(value) {
                return utils_1.Utils.isNumeric(value) ? value : null;
            };
            NumberFilter.prototype.stringToFloat = function(value) {
                var filterText = utils_1.Utils.makeNull(value);
                if (filterText && filterText.trim() === "") {
                    filterText = null;
                }
                var newFilter;
                if (filterText !== null && filterText !== undefined) {
                    newFilter = parseFloat(filterText);
                } else {
                    newFilter = null;
                }
                return newFilter;
            };
            NumberFilter.prototype.setFilter = function(filter, type) {
                filter = utils_1.Utils.makeNull(filter);
                if (filter !== null && !(typeof filter === "number")) {
                    filter = parseFloat(filter);
                }
                if (type === baseFilter_1.FilterConditionType.MAIN) {
                    this.filterNumber = filter;
                    if (!this.eFilterTextField) return;
                    this.eFilterTextField.value = filter;
                } else {
                    this.filterNumberCondition = filter;
                    if (!this.eFilterTextConditionField) return;
                    this.eFilterTextConditionField.value = filter;
                }
            };
            NumberFilter.prototype.setFilterTo = function(filter, type) {
                filter = utils_1.Utils.makeNull(filter);
                if (filter !== null && !(typeof filter === "number")) {
                    filter = parseFloat(filter);
                }
                if (type === baseFilter_1.FilterConditionType.MAIN) {
                    this.filterNumberTo = filter;
                    if (!this.eFilterToTextField) return;
                    this.eFilterToTextField.value = filter;
                } else {
                    this.filterNumberConditionTo = filter;
                    if (!this.eFilterToConditionText) return;
                    this.eFilterToConditionText.value = filter;
                }
            };
            NumberFilter.prototype.getFilter = function(type) {
                return type === baseFilter_1.FilterConditionType.MAIN ? this.filterNumber : this.filterNumberCondition;
            };
            NumberFilter.prototype.serialize = function(type) {
                var filter = type === baseFilter_1.FilterConditionType.MAIN ? this.filter : this.filterCondition;
                var filterNumber = type === baseFilter_1.FilterConditionType.MAIN ? this.filterNumber : this.filterNumberCondition;
                var filterNumberTo = type === baseFilter_1.FilterConditionType.MAIN ? this.filterNumberTo : this.filterNumberConditionTo;
                return {
                    type: filter ? filter : this.defaultFilter,
                    filter: filterNumber,
                    filterTo: filterNumberTo,
                    filterType: "number"
                };
            };
            NumberFilter.prototype.parse = function(model, type) {
                this.setFilterType(model.type, type);
                this.setFilter(model.filter, type);
                this.setFilterTo(model.filterTo, type);
            };
            NumberFilter.prototype.refreshFilterBodyUi = function(type) {
                var filterType = type === baseFilter_1.FilterConditionType.MAIN ? this.filter : this.filterCondition;
                var panel = type === baseFilter_1.FilterConditionType.MAIN ? this.eNumberToPanel : this.eNumberToConditionPanel;
                if (!panel) return;
                var visible = filterType === NumberFilter.IN_RANGE;
                utils_1.Utils.setVisible(panel, visible);
            };
            NumberFilter.prototype.resetState = function() {
                this.setFilterType(this.defaultFilter, baseFilter_1.FilterConditionType.MAIN);
                this.setFilter(null, baseFilter_1.FilterConditionType.MAIN);
                this.setFilterTo(null, baseFilter_1.FilterConditionType.MAIN);
                this.setFilterType(this.defaultFilter, baseFilter_1.FilterConditionType.CONDITION);
                this.setFilter(null, baseFilter_1.FilterConditionType.CONDITION);
                this.setFilterTo(null, baseFilter_1.FilterConditionType.CONDITION);
            };
            NumberFilter.prototype.setType = function(filterType, type) {
                this.setFilterType(filterType, type);
            };
            NumberFilter.LESS_THAN = "lessThan";
            __decorate([ componentAnnotations_1.QuerySelector("#filterNumberToPanel"), __metadata("design:type", HTMLElement) ], NumberFilter.prototype, "eNumberToPanel", void 0);
            __decorate([ componentAnnotations_1.QuerySelector("#filterNumberToPanelCondition"), __metadata("design:type", HTMLElement) ], NumberFilter.prototype, "eNumberToConditionPanel", void 0);
            __decorate([ componentAnnotations_1.QuerySelector("#filterToText"), __metadata("design:type", HTMLInputElement) ], NumberFilter.prototype, "eFilterToTextField", void 0);
            __decorate([ componentAnnotations_1.QuerySelector("#filterToConditionText"), __metadata("design:type", HTMLInputElement) ], NumberFilter.prototype, "eFilterToConditionText", void 0);
            return NumberFilter;
        }(baseFilter_1.ScalarBaseFilter);
        exports.NumberFilter = NumberFilter;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var gridCell_1 = __webpack_require__(23);
        var constants_1 = __webpack_require__(9);
        var mouseEventService_1 = __webpack_require__(44);
        var paginationProxy_1 = __webpack_require__(29);
        var focusedCellController_1 = __webpack_require__(22);
        var utils_1 = __webpack_require__(1);
        var animationFrameService_1 = __webpack_require__(37);
        var columnController_1 = __webpack_require__(4);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var NavigationService = function() {
            function NavigationService() {}
            NavigationService.prototype.init = function() {
                this.scrollWidth = this.gridOptionsWrapper.getScrollbarWidth();
            };
            NavigationService.prototype.registerGridComp = function(gridPanel) {
                this.gridPanel = gridPanel;
            };
            NavigationService.prototype.handlePageScrollingKey = function(event) {
                var key = event.which || event.keyCode;
                var alt = event.altKey;
                var ctrl = event.ctrlKey;
                var currentCell = this.mouseEventService.getGridCellForEvent(event).getGridCellDef();
                if (!currentCell) {
                    return false;
                }
                var processed = false;
                switch (key) {
                  case constants_1.Constants.KEY_PAGE_HOME:
                  case constants_1.Constants.KEY_PAGE_END:
                    if (!ctrl && !alt) {
                        this.onHomeOrEndKey(key);
                        processed = true;
                    }
                    break;

                  case constants_1.Constants.KEY_LEFT:
                  case constants_1.Constants.KEY_RIGHT:
                    if (ctrl && !alt) {
                        this.onCtrlLeftOrRight(key, currentCell);
                        processed = true;
                    }
                    break;

                  case constants_1.Constants.KEY_UP:
                  case constants_1.Constants.KEY_DOWN:
                    if (ctrl && !alt) {
                        this.onCtrlUpOrDown(key, currentCell);
                        processed = true;
                    }
                    break;

                  case constants_1.Constants.KEY_PAGE_DOWN:
                    if (!ctrl && !alt) {
                        this.onPageDown(currentCell);
                        processed = true;
                    }
                    break;

                  case constants_1.Constants.KEY_PAGE_UP:
                    if (!ctrl && !alt) {
                        this.onPageUp(currentCell);
                        processed = true;
                    }
                    break;
                }
                if (processed) {
                    event.preventDefault();
                }
                return processed;
            };
            NavigationService.prototype.onPageDown = function(gridCell) {
                var scrollPosition = this.gridPanel.getVScrollPosition();
                var pixelsInOnePage = scrollPosition.bottom - scrollPosition.top;
                if (this.gridPanel.isHorizontalScrollShowing()) {
                    pixelsInOnePage -= this.scrollWidth;
                }
                var pagingPixelOffset = this.paginationProxy.getPixelOffset();
                var currentPageBottomPixel = scrollPosition.top + pixelsInOnePage;
                var currentPageBottomRow = this.paginationProxy.getRowIndexAtPixel(currentPageBottomPixel + pagingPixelOffset);
                var scrollIndex = currentPageBottomRow;
                var currentCellPixel = this.paginationProxy.getRow(gridCell.rowIndex).rowTop;
                var nextCellPixel = currentCellPixel + pixelsInOnePage - pagingPixelOffset;
                var focusIndex = this.paginationProxy.getRowIndexAtPixel(nextCellPixel + pagingPixelOffset);
                var pageLastRow = this.paginationProxy.getPageLastRow();
                if (focusIndex > pageLastRow) {
                    focusIndex = pageLastRow;
                }
                if (scrollIndex > pageLastRow) {
                    scrollIndex = pageLastRow;
                }
                this.navigateTo(scrollIndex, "top", null, focusIndex, gridCell.column);
            };
            NavigationService.prototype.onPageUp = function(gridCell) {
                var scrollPosition = this.gridPanel.getVScrollPosition();
                var pixelsInOnePage = scrollPosition.bottom - scrollPosition.top;
                if (this.gridPanel.isHorizontalScrollShowing()) {
                    pixelsInOnePage -= this.scrollWidth;
                }
                var pagingPixelOffset = this.paginationProxy.getPixelOffset();
                var currentPageTopPixel = scrollPosition.top;
                var currentPageTopRow = this.paginationProxy.getRowIndexAtPixel(currentPageTopPixel + pagingPixelOffset);
                var scrollIndex = currentPageTopRow;
                var currentRowNode = this.paginationProxy.getRow(gridCell.rowIndex);
                var nextCellPixel = currentRowNode.rowTop + currentRowNode.rowHeight - pixelsInOnePage - pagingPixelOffset;
                var focusIndex = this.paginationProxy.getRowIndexAtPixel(nextCellPixel + pagingPixelOffset);
                var firstRow = this.paginationProxy.getPageFirstRow();
                if (focusIndex < firstRow) {
                    focusIndex = firstRow;
                }
                if (scrollIndex < firstRow) {
                    scrollIndex = firstRow;
                }
                this.navigateTo(scrollIndex, "bottom", null, focusIndex, gridCell.column);
            };
            NavigationService.prototype.navigateTo = function(scrollIndex, scrollType, scrollColumn, focusIndex, focusColumn) {
                if (utils_1._.exists(scrollColumn)) {
                    this.gridPanel.ensureColumnVisible(scrollColumn);
                }
                if (utils_1._.exists(scrollIndex)) {
                    this.gridPanel.ensureIndexVisible(scrollIndex, scrollType);
                }
                this.animationFrameService.flushAllFrames();
                this.focusedCellController.setFocusedCell(focusIndex, focusColumn, null, true);
                if (this.rangeController) {
                    var gridCell = new gridCell_1.GridCell({
                        rowIndex: focusIndex,
                        floating: null,
                        column: focusColumn
                    });
                    this.rangeController.setRangeToCell(gridCell);
                }
            };
            NavigationService.prototype.onCtrlUpOrDown = function(key, gridCell) {
                var upKey = key === constants_1.Constants.KEY_UP;
                var rowIndexToScrollTo = upKey ? 0 : this.paginationProxy.getPageLastRow();
                this.navigateTo(rowIndexToScrollTo, null, gridCell.column, rowIndexToScrollTo, gridCell.column);
            };
            NavigationService.prototype.onCtrlLeftOrRight = function(key, gridCell) {
                var leftKey = key === constants_1.Constants.KEY_LEFT;
                var allColumns = this.columnController.getAllDisplayedColumns();
                var columnToSelect = leftKey ? allColumns[0] : allColumns[allColumns.length - 1];
                this.navigateTo(gridCell.rowIndex, null, columnToSelect, gridCell.rowIndex, columnToSelect);
            };
            NavigationService.prototype.onHomeOrEndKey = function(key) {
                var homeKey = key === constants_1.Constants.KEY_PAGE_HOME;
                var allColumns = this.columnController.getAllDisplayedColumns();
                var columnToSelect = homeKey ? allColumns[0] : allColumns[allColumns.length - 1];
                var rowIndexToScrollTo = homeKey ? 0 : this.paginationProxy.getPageLastRow();
                this.navigateTo(rowIndexToScrollTo, null, columnToSelect, rowIndexToScrollTo, columnToSelect);
            };
            __decorate([ context_1.Autowired("mouseEventService"), __metadata("design:type", mouseEventService_1.MouseEventService) ], NavigationService.prototype, "mouseEventService", void 0);
            __decorate([ context_1.Autowired("paginationProxy"), __metadata("design:type", paginationProxy_1.PaginationProxy) ], NavigationService.prototype, "paginationProxy", void 0);
            __decorate([ context_1.Autowired("focusedCellController"), __metadata("design:type", focusedCellController_1.FocusedCellController) ], NavigationService.prototype, "focusedCellController", void 0);
            __decorate([ context_1.Autowired("animationFrameService"), __metadata("design:type", animationFrameService_1.AnimationFrameService) ], NavigationService.prototype, "animationFrameService", void 0);
            __decorate([ context_1.Optional("rangeController"), __metadata("design:type", Object) ], NavigationService.prototype, "rangeController", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], NavigationService.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], NavigationService.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], NavigationService.prototype, "init", null);
            NavigationService = __decorate([ context_1.Bean("navigationService") ], NavigationService);
            return NavigationService;
        }();
        exports.NavigationService = NavigationService;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var context_1 = __webpack_require__(0);
        var dragAndDropService_1 = __webpack_require__(15);
        var columnController_1 = __webpack_require__(4);
        var eventService_1 = __webpack_require__(3);
        var events_1 = __webpack_require__(5);
        var headerRowComp_1 = __webpack_require__(99);
        var bodyDropTarget_1 = __webpack_require__(101);
        var column_1 = __webpack_require__(10);
        var scrollVisibleService_1 = __webpack_require__(36);
        var HeaderContainer = function() {
            function HeaderContainer(eContainer, eViewport, pinned) {
                this.headerRowComps = [];
                this.eContainer = eContainer;
                this.pinned = pinned;
                this.eViewport = eViewport;
            }
            HeaderContainer.prototype.registerGridComp = function(gridPanel) {
                this.setupDragAndDrop(gridPanel);
            };
            HeaderContainer.prototype.forEachHeaderElement = function(callback) {
                this.headerRowComps.forEach(function(headerRowComp) {
                    return headerRowComp.forEachHeaderElement(callback);
                });
            };
            HeaderContainer.prototype.init = function() {
                this.scrollWidth = this.gridOptionsWrapper.getScrollbarWidth();
                this.eventService.addEventListener(events_1.Events.EVENT_COLUMN_VALUE_CHANGED, this.onColumnValueChanged.bind(this));
                this.eventService.addEventListener(events_1.Events.EVENT_COLUMN_ROW_GROUP_CHANGED, this.onColumnRowGroupChanged.bind(this));
                this.eventService.addEventListener(events_1.Events.EVENT_GRID_COLUMNS_CHANGED, this.onGridColumnsChanged.bind(this));
                this.eventService.addEventListener(events_1.Events.EVENT_SCROLL_VISIBILITY_CHANGED, this.onScrollVisibilityChanged.bind(this));
                this.eventService.addEventListener(events_1.Events.EVENT_COLUMN_RESIZED, this.onColumnResized.bind(this));
                this.eventService.addEventListener(events_1.Events.EVENT_DISPLAYED_COLUMNS_CHANGED, this.onDisplayedColumnsChanged.bind(this));
            };
            HeaderContainer.prototype.onColumnRowGroupChanged = function() {
                this.onGridColumnsChanged();
            };
            HeaderContainer.prototype.onColumnValueChanged = function() {
                this.onGridColumnsChanged();
            };
            HeaderContainer.prototype.onColumnResized = function() {
                this.setWidthOfPinnedContainer();
            };
            HeaderContainer.prototype.onDisplayedColumnsChanged = function() {
                this.setWidthOfPinnedContainer();
            };
            HeaderContainer.prototype.onScrollVisibilityChanged = function() {
                this.setWidthOfPinnedContainer();
            };
            HeaderContainer.prototype.setWidthOfPinnedContainer = function() {
                var pinningLeft = this.pinned === column_1.Column.PINNED_LEFT;
                var pinningRight = this.pinned === column_1.Column.PINNED_RIGHT;
                if (pinningLeft || pinningRight) {
                    var width = pinningLeft ? this.columnController.getPinnedLeftContainerWidth() : this.columnController.getPinnedRightContainerWidth();
                    var addPaddingForScrollbar = pinningLeft ? this.scrollVisibleService.isLeftVerticalScrollShowing() : this.scrollVisibleService.isRightVerticalScrollShowing();
                    if (addPaddingForScrollbar) {
                        width += this.scrollWidth;
                    }
                    this.eContainer.style.width = width + "px";
                }
            };
            HeaderContainer.prototype.destroy = function() {
                this.removeHeaderRowComps();
            };
            HeaderContainer.prototype.onGridColumnsChanged = function() {
                this.removeHeaderRowComps();
                this.createHeaderRowComps();
            };
            HeaderContainer.prototype.refresh = function() {
                this.onGridColumnsChanged();
            };
            HeaderContainer.prototype.setupDragAndDrop = function(gridComp) {
                var dropContainer = this.eViewport ? this.eViewport : this.eContainer;
                var bodyDropTarget = new bodyDropTarget_1.BodyDropTarget(this.pinned, dropContainer);
                this.context.wireBean(bodyDropTarget);
                bodyDropTarget.registerGridComp(gridComp);
            };
            HeaderContainer.prototype.removeHeaderRowComps = function() {
                this.headerRowComps.forEach(function(headerRowComp) {
                    headerRowComp.destroy();
                });
                this.headerRowComps.length = 0;
                utils_1.Utils.removeAllChildren(this.eContainer);
            };
            HeaderContainer.prototype.createHeaderRowComps = function() {
                var rowCount = this.columnController.getHeaderRowCount();
                for (var dept = 0; dept < rowCount; dept++) {
                    var groupRow = dept !== rowCount - 1;
                    var type = groupRow ? headerRowComp_1.HeaderRowType.COLUMN_GROUP : headerRowComp_1.HeaderRowType.COLUMN;
                    var headerRowComp = new headerRowComp_1.HeaderRowComp(dept, type, this.pinned, this.dropTarget);
                    this.context.wireBean(headerRowComp);
                    this.headerRowComps.push(headerRowComp);
                    this.eContainer.appendChild(headerRowComp.getGui());
                }
                var includeFloatingFilterRow = this.gridOptionsWrapper.isFloatingFilter() && !this.columnController.isPivotMode();
                if (includeFloatingFilterRow) {
                    var headerRowComp = new headerRowComp_1.HeaderRowComp(rowCount, headerRowComp_1.HeaderRowType.FLOATING_FILTER, this.pinned, this.dropTarget);
                    this.context.wireBean(headerRowComp);
                    this.headerRowComps.push(headerRowComp);
                    this.eContainer.appendChild(headerRowComp.getGui());
                }
            };
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], HeaderContainer.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], HeaderContainer.prototype, "context", void 0);
            __decorate([ context_1.Autowired("$scope"), __metadata("design:type", Object) ], HeaderContainer.prototype, "$scope", void 0);
            __decorate([ context_1.Autowired("dragAndDropService"), __metadata("design:type", dragAndDropService_1.DragAndDropService) ], HeaderContainer.prototype, "dragAndDropService", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], HeaderContainer.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], HeaderContainer.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("scrollVisibleService"), __metadata("design:type", scrollVisibleService_1.ScrollVisibleService) ], HeaderContainer.prototype, "scrollVisibleService", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], HeaderContainer.prototype, "init", null);
            return HeaderContainer;
        }();
        exports.HeaderContainer = HeaderContainer;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var component_1 = __webpack_require__(8);
        var context_1 = __webpack_require__(0);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var columnController_1 = __webpack_require__(4);
        var column_1 = __webpack_require__(10);
        var eventService_1 = __webpack_require__(3);
        var events_1 = __webpack_require__(5);
        var utils_1 = __webpack_require__(1);
        var headerWrapperComp_1 = __webpack_require__(100);
        var headerGroupWrapperComp_1 = __webpack_require__(133);
        var filterManager_1 = __webpack_require__(18);
        var componentRecipes_1 = __webpack_require__(21);
        var gridApi_1 = __webpack_require__(6);
        var HeaderRowType;
        (function(HeaderRowType) {
            HeaderRowType[HeaderRowType["COLUMN_GROUP"] = 0] = "COLUMN_GROUP";
            HeaderRowType[HeaderRowType["COLUMN"] = 1] = "COLUMN";
            HeaderRowType[HeaderRowType["FLOATING_FILTER"] = 2] = "FLOATING_FILTER";
        })(HeaderRowType = exports.HeaderRowType || (exports.HeaderRowType = {}));
        var HeaderRowComp = function(_super) {
            __extends(HeaderRowComp, _super);
            function HeaderRowComp(dept, type, pinned, dropTarget) {
                var _this = _super.call(this, '<div class="ag-header-row" role="presentation"/>') || this;
                _this.headerComps = {};
                _this.dept = dept;
                _this.type = type;
                _this.pinned = pinned;
                _this.dropTarget = dropTarget;
                return _this;
            }
            HeaderRowComp.prototype.forEachHeaderElement = function(callback) {
                var _this = this;
                Object.keys(this.headerComps).forEach(function(key) {
                    callback(_this.headerComps[key]);
                });
            };
            HeaderRowComp.prototype.destroy = function() {
                var idsOfAllChildren = Object.keys(this.headerComps);
                this.removeAndDestroyChildComponents(idsOfAllChildren);
                _super.prototype.destroy.call(this);
            };
            HeaderRowComp.prototype.removeAndDestroyChildComponents = function(idsToDestroy) {
                var _this = this;
                idsToDestroy.forEach(function(id) {
                    var childHeaderComp = _this.headerComps[id];
                    _this.getGui().removeChild(childHeaderComp.getGui());
                    if (childHeaderComp.destroy) {
                        childHeaderComp.destroy();
                    }
                    delete _this.headerComps[id];
                });
            };
            HeaderRowComp.prototype.onRowHeightChanged = function() {
                var headerRowCount = this.columnController.getHeaderRowCount();
                var sizes = [];
                var numberOfFloating = 0;
                var groupHeight;
                var headerHeight;
                if (!this.columnController.isPivotMode()) {
                    if (this.gridOptionsWrapper.isFloatingFilter()) {
                        headerRowCount++;
                    }
                    numberOfFloating = this.gridOptionsWrapper.isFloatingFilter() ? 1 : 0;
                    groupHeight = this.gridOptionsWrapper.getGroupHeaderHeight();
                    headerHeight = this.gridOptionsWrapper.getHeaderHeight();
                } else {
                    numberOfFloating = 0;
                    groupHeight = this.gridOptionsWrapper.getPivotGroupHeaderHeight();
                    headerHeight = this.gridOptionsWrapper.getPivotHeaderHeight();
                }
                var numberOfNonGroups = 1 + numberOfFloating;
                var numberOfGroups = headerRowCount - numberOfNonGroups;
                for (var i = 0; i < numberOfGroups; i++) {
                    sizes.push(groupHeight);
                }
                sizes.push(headerHeight);
                for (var i = 0; i < numberOfFloating; i++) {
                    sizes.push(this.gridOptionsWrapper.getFloatingFiltersHeight());
                }
                var rowHeight = 0;
                for (var i = 0; i < this.dept; i++) {
                    rowHeight += sizes[i];
                }
                this.getGui().style.top = rowHeight + "px";
                this.getGui().style.height = sizes[this.dept] + "px";
            };
            HeaderRowComp.prototype.init = function() {
                this.onRowHeightChanged();
                this.onVirtualColumnsChanged();
                this.setWidth();
                this.addDestroyableEventListener(this.gridOptionsWrapper, gridOptionsWrapper_1.GridOptionsWrapper.PROP_HEADER_HEIGHT, this.onRowHeightChanged.bind(this));
                this.addDestroyableEventListener(this.gridOptionsWrapper, gridOptionsWrapper_1.GridOptionsWrapper.PROP_PIVOT_HEADER_HEIGHT, this.onRowHeightChanged.bind(this));
                this.addDestroyableEventListener(this.gridOptionsWrapper, gridOptionsWrapper_1.GridOptionsWrapper.PROP_GROUP_HEADER_HEIGHT, this.onRowHeightChanged.bind(this));
                this.addDestroyableEventListener(this.gridOptionsWrapper, gridOptionsWrapper_1.GridOptionsWrapper.PROP_PIVOT_GROUP_HEADER_HEIGHT, this.onRowHeightChanged.bind(this));
                this.addDestroyableEventListener(this.gridOptionsWrapper, gridOptionsWrapper_1.GridOptionsWrapper.PROP_FLOATING_FILTERS_HEIGHT, this.onRowHeightChanged.bind(this));
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_VIRTUAL_COLUMNS_CHANGED, this.onVirtualColumnsChanged.bind(this));
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_DISPLAYED_COLUMNS_CHANGED, this.onDisplayedColumnsChanged.bind(this));
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_COLUMN_RESIZED, this.onColumnResized.bind(this));
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_GRID_COLUMNS_CHANGED, this.onGridColumnsChanged.bind(this));
            };
            HeaderRowComp.prototype.onColumnResized = function() {
                this.setWidth();
            };
            HeaderRowComp.prototype.setWidth = function() {
                var mainRowWidth = this.columnController.getContainerWidth(this.pinned) + "px";
                this.getGui().style.width = mainRowWidth;
            };
            HeaderRowComp.prototype.onGridColumnsChanged = function() {
                this.removeAndDestroyAllChildComponents();
            };
            HeaderRowComp.prototype.removeAndDestroyAllChildComponents = function() {
                var idsOfAllChildren = Object.keys(this.headerComps);
                this.removeAndDestroyChildComponents(idsOfAllChildren);
            };
            HeaderRowComp.prototype.onDisplayedColumnsChanged = function() {
                this.onVirtualColumnsChanged();
                this.setWidth();
            };
            HeaderRowComp.prototype.onVirtualColumnsChanged = function() {
                var _this = this;
                var currentChildIds = Object.keys(this.headerComps);
                var itemsAtDepth = this.columnController.getVirtualHeaderGroupRow(this.pinned, this.type == HeaderRowType.FLOATING_FILTER ? this.dept - 1 : this.dept);
                var ensureDomOrder = this.gridOptionsWrapper.isEnsureDomOrder();
                var eBefore;
                itemsAtDepth.forEach(function(child) {
                    if (child.isEmptyGroup()) {
                        return;
                    }
                    var idOfChild = child.getUniqueId();
                    var eParentContainer = _this.getGui();
                    var colAlreadyInDom = currentChildIds.indexOf(idOfChild) >= 0;
                    var headerComp;
                    var eHeaderCompGui;
                    if (colAlreadyInDom) {
                        utils_1.Utils.removeFromArray(currentChildIds, idOfChild);
                        headerComp = _this.headerComps[idOfChild];
                        eHeaderCompGui = headerComp.getGui();
                        if (ensureDomOrder) {
                            utils_1.Utils.ensureDomOrder(eParentContainer, eHeaderCompGui, eBefore);
                        }
                        eBefore = eHeaderCompGui;
                    } else {
                        headerComp = _this.createHeaderComp(child);
                        _this.headerComps[idOfChild] = headerComp;
                        eHeaderCompGui = headerComp.getGui();
                        if (ensureDomOrder) {
                            utils_1.Utils.insertWithDomOrder(eParentContainer, eHeaderCompGui, eBefore);
                        } else {
                            eParentContainer.appendChild(eHeaderCompGui);
                        }
                        eBefore = eHeaderCompGui;
                    }
                });
                this.removeAndDestroyChildComponents(currentChildIds);
            };
            HeaderRowComp.prototype.createHeaderComp = function(columnGroupChild) {
                var result;
                switch (this.type) {
                  case HeaderRowType.COLUMN:
                    result = new headerWrapperComp_1.HeaderWrapperComp(columnGroupChild, this.dropTarget, this.pinned);
                    break;

                  case HeaderRowType.COLUMN_GROUP:
                    result = new headerGroupWrapperComp_1.HeaderGroupWrapperComp(columnGroupChild, this.dropTarget, this.pinned);
                    break;

                  case HeaderRowType.FLOATING_FILTER:
                    var column = columnGroupChild;
                    result = this.createFloatingFilterWrapper(column);
                    break;
                }
                this.context.wireBean(result);
                return result;
            };
            HeaderRowComp.prototype.createFloatingFilterWrapper = function(column) {
                var _this = this;
                var floatingFilterParams = this.createFloatingFilterParams(column);
                var floatingFilterWrapper = this.componentRecipes.newFloatingFilterWrapperComponent(column, floatingFilterParams);
                this.addDestroyableEventListener(column, column_1.Column.EVENT_FILTER_CHANGED, function() {
                    var filterComponentPromise = _this.filterManager.getFilterComponent(column);
                    floatingFilterWrapper.onParentModelChanged(filterComponentPromise.resolveNow(null, function(filter) {
                        return filter.getModel();
                    }));
                });
                var cachedFilter = this.filterManager.cachedFilter(column);
                if (cachedFilter) {
                    var filterComponentPromise = this.filterManager.getFilterComponent(column);
                    floatingFilterWrapper.onParentModelChanged(filterComponentPromise.resolveNow(null, function(filter) {
                        return filter.getModel();
                    }));
                }
                return floatingFilterWrapper;
            };
            HeaderRowComp.prototype.createFloatingFilterParams = function(column) {
                var _this = this;
                var baseParams = {
                    api: this.gridApi,
                    column: column,
                    currentParentModel: function() {
                        var filterComponentPromise = _this.filterManager.getFilterComponent(column);
                        var wholeParentFilter = filterComponentPromise.resolveNow(null, function(filter) {
                            return filter.getNullableModel ? filter.getNullableModel() : filter.getModel();
                        });
                        return wholeParentFilter.operator != null ? wholeParentFilter.condition1 : wholeParentFilter;
                    },
                    onFloatingFilterChanged: function(change) {
                        var captureModelChangedResolveFunc;
                        var modelChanged = new utils_1.Promise(function(resolve) {
                            captureModelChangedResolveFunc = resolve;
                        });
                        var filterComponentPromise = _this.filterManager.getFilterComponent(column);
                        filterComponentPromise.then(function(filterComponent) {
                            if (filterComponent.onFloatingFilterChanged) {
                                var result = filterComponent.onFloatingFilterChanged(change);
                                captureModelChangedResolveFunc(result);
                            } else {
                                filterComponent.setModel(change);
                                _this.filterManager.onFilterChanged();
                                captureModelChangedResolveFunc(true);
                            }
                        });
                        return modelChanged.resolveNow(true, function(modelChanged) {
                            return modelChanged;
                        });
                    },
                    suppressFilterButton: false
                };
                return baseParams;
            };
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], HeaderRowComp.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], HeaderRowComp.prototype, "gridApi", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], HeaderRowComp.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], HeaderRowComp.prototype, "context", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], HeaderRowComp.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("filterManager"), __metadata("design:type", filterManager_1.FilterManager) ], HeaderRowComp.prototype, "filterManager", void 0);
            __decorate([ context_1.Autowired("componentRecipes"), __metadata("design:type", componentRecipes_1.ComponentRecipes) ], HeaderRowComp.prototype, "componentRecipes", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], HeaderRowComp.prototype, "init", null);
            return HeaderRowComp;
        }(component_1.Component);
        exports.HeaderRowComp = HeaderRowComp;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var component_1 = __webpack_require__(8);
        var context_1 = __webpack_require__(0);
        var column_1 = __webpack_require__(10);
        var utils_1 = __webpack_require__(1);
        var dragAndDropService_1 = __webpack_require__(15);
        var columnApi_1 = __webpack_require__(7);
        var columnController_1 = __webpack_require__(4);
        var horizontalResizeService_1 = __webpack_require__(59);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var cssClassApplier_1 = __webpack_require__(81);
        var setLeftFeature_1 = __webpack_require__(52);
        var gridApi_1 = __webpack_require__(6);
        var sortController_1 = __webpack_require__(24);
        var eventService_1 = __webpack_require__(3);
        var componentRecipes_1 = __webpack_require__(21);
        var agCheckbox_1 = __webpack_require__(60);
        var componentAnnotations_1 = __webpack_require__(11);
        var selectAllFeature_1 = __webpack_require__(132);
        var events_1 = __webpack_require__(5);
        var columnHoverService_1 = __webpack_require__(45);
        var beans_1 = __webpack_require__(28);
        var hoverFeature_1 = __webpack_require__(74);
        var touchListener_1 = __webpack_require__(46);
        var HeaderWrapperComp = function(_super) {
            __extends(HeaderWrapperComp, _super);
            function HeaderWrapperComp(column, dragSourceDropTarget, pinned) {
                var _this = _super.call(this, HeaderWrapperComp.TEMPLATE) || this;
                _this.column = column;
                _this.dragSourceDropTarget = dragSourceDropTarget;
                _this.pinned = pinned;
                return _this;
            }
            HeaderWrapperComp.prototype.getColumn = function() {
                return this.column;
            };
            HeaderWrapperComp.prototype.init = function() {
                this.instantiate(this.context);
                var displayName = this.columnController.getDisplayNameForColumn(this.column, "header", true);
                var enableSorting = this.gridOptionsWrapper.isEnableSorting() && !this.column.getColDef().suppressSorting;
                var enableMenu = this.menuFactory.isMenuEnabled(this.column) && !this.column.getColDef().suppressMenu;
                this.appendHeaderComp(displayName, enableSorting, enableMenu);
                this.setupWidth();
                this.setupMovingCss();
                this.setupTooltip();
                this.setupResize();
                this.setupMenuClass();
                this.setupSortableClass(enableSorting);
                this.addColumnHoverListener();
                this.addFeature(this.context, new hoverFeature_1.HoverFeature([ this.column ], this.getGui()));
                this.addDestroyableEventListener(this.column, column_1.Column.EVENT_FILTER_ACTIVE_CHANGED, this.onFilterChanged.bind(this));
                this.onFilterChanged();
                this.addFeature(this.context, new selectAllFeature_1.SelectAllFeature(this.cbSelectAll, this.column));
                var setLeftFeature = new setLeftFeature_1.SetLeftFeature(this.column, this.getGui(), this.beans);
                setLeftFeature.init();
                this.addDestroyFunc(setLeftFeature.destroy.bind(setLeftFeature));
                this.addAttributes();
                cssClassApplier_1.CssClassApplier.addHeaderClassesFromColDef(this.column.getColDef(), this.getGui(), this.gridOptionsWrapper, this.column, null);
            };
            HeaderWrapperComp.prototype.addColumnHoverListener = function() {
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_COLUMN_HOVER_CHANGED, this.onColumnHover.bind(this));
                this.onColumnHover();
            };
            HeaderWrapperComp.prototype.onColumnHover = function() {
                var isHovered = this.columnHoverService.isHovered(this.column);
                utils_1.Utils.addOrRemoveCssClass(this.getGui(), "ag-column-hover", isHovered);
            };
            HeaderWrapperComp.prototype.setupSortableClass = function(enableSorting) {
                if (enableSorting) {
                    var element = this.getGui();
                    utils_1.Utils.addCssClass(element, "ag-header-cell-sortable");
                }
            };
            HeaderWrapperComp.prototype.onFilterChanged = function() {
                var filterPresent = this.column.isFilterActive();
                utils_1.Utils.addOrRemoveCssClass(this.getGui(), "ag-header-cell-filtered", filterPresent);
            };
            HeaderWrapperComp.prototype.appendHeaderComp = function(displayName, enableSorting, enableMenu) {
                var _this = this;
                var params = {
                    column: this.column,
                    displayName: displayName,
                    enableSorting: enableSorting,
                    enableMenu: enableMenu,
                    showColumnMenu: function(source) {
                        _this.gridApi.showColumnMenuAfterButtonClick(_this.column, source);
                    },
                    progressSort: function(multiSort) {
                        _this.sortController.progressSort(_this.column, !!multiSort, "uiColumnSorted");
                    },
                    setSort: function(sort, multiSort) {
                        _this.sortController.setSortForColumn(_this.column, sort, !!multiSort, "uiColumnSorted");
                    },
                    api: this.gridApi,
                    columnApi: this.columnApi,
                    context: this.gridOptionsWrapper.getContext()
                };
                var callback = this.afterHeaderCompCreated.bind(this, displayName);
                this.componentRecipes.newHeaderComponent(params).then(callback);
            };
            HeaderWrapperComp.prototype.afterHeaderCompCreated = function(displayName, headerComp) {
                this.appendChild(headerComp);
                this.setupMove(headerComp.getGui(), displayName);
                if (headerComp.destroy) {
                    this.addDestroyFunc(headerComp.destroy.bind(headerComp));
                }
            };
            HeaderWrapperComp.prototype.onColumnMovingChanged = function() {
                if (this.column.isMoving()) {
                    utils_1.Utils.addCssClass(this.getGui(), "ag-header-cell-moving");
                } else {
                    utils_1.Utils.removeCssClass(this.getGui(), "ag-header-cell-moving");
                }
            };
            HeaderWrapperComp.prototype.setupMove = function(eHeaderCellLabel, displayName) {
                var _this = this;
                var suppressMove = this.gridOptionsWrapper.isSuppressMovableColumns() || this.column.getColDef().suppressMovable || this.column.isLockPosition();
                if (suppressMove) {
                    return;
                }
                if (eHeaderCellLabel) {
                    var dragSource_1 = {
                        type: dragAndDropService_1.DragSourceType.HeaderCell,
                        eElement: eHeaderCellLabel,
                        dragItemCallback: function() {
                            return _this.createDragItem();
                        },
                        dragItemName: displayName,
                        dragSourceDropTarget: this.dragSourceDropTarget,
                        dragStarted: function() {
                            return _this.column.setMoving(true, "uiColumnMoved");
                        },
                        dragStopped: function() {
                            return _this.column.setMoving(false, "uiColumnMoved");
                        }
                    };
                    this.dragAndDropService.addDragSource(dragSource_1, true);
                    this.addDestroyFunc(function() {
                        return _this.dragAndDropService.removeDragSource(dragSource_1);
                    });
                }
            };
            HeaderWrapperComp.prototype.createDragItem = function() {
                var visibleState = {};
                visibleState[this.column.getId()] = this.column.isVisible();
                return {
                    columns: [ this.column ],
                    visibleState: visibleState
                };
            };
            HeaderWrapperComp.prototype.setupResize = function() {
                var _this = this;
                var colDef = this.column.getColDef();
                if (!this.eResize) {
                    return;
                }
                if (!this.column.isResizable()) {
                    utils_1.Utils.removeFromParent(this.eResize);
                    return;
                }
                var finishedWithResizeFunc = this.horizontalResizeService.addResizeBar({
                    eResizeBar: this.eResize,
                    onResizeStart: this.onResizeStart.bind(this),
                    onResizing: this.onResizing.bind(this, false),
                    onResizeEnd: this.onResizing.bind(this, true)
                });
                this.addDestroyFunc(finishedWithResizeFunc);
                var weWantAutoSize = !this.gridOptionsWrapper.isSuppressAutoSize() && !colDef.suppressAutoSize;
                if (weWantAutoSize) {
                    this.addDestroyableEventListener(this.eResize, "dblclick", function() {
                        _this.columnController.autoSizeColumn(_this.column, "uiColumnResized");
                    });
                    var touchListener = new touchListener_1.TouchListener(this.eResize);
                    this.addDestroyableEventListener(touchListener, touchListener_1.TouchListener.EVENT_DOUBLE_TAP, function() {
                        _this.columnController.autoSizeColumn(_this.column, "uiColumnResized");
                    });
                    this.addDestroyFunc(touchListener.destroy.bind(touchListener));
                }
            };
            HeaderWrapperComp.prototype.onResizing = function(finished, resizeAmount) {
                var resizeAmountNormalised = this.normaliseResizeAmount(resizeAmount);
                var newWidth = this.resizeStartWidth + resizeAmountNormalised;
                this.columnController.setColumnWidth(this.column, newWidth, this.resizeWithShiftKey, finished, "uiColumnDragged");
            };
            HeaderWrapperComp.prototype.onResizeStart = function(shiftKey) {
                this.resizeStartWidth = this.column.getActualWidth();
                this.resizeWithShiftKey = shiftKey;
            };
            HeaderWrapperComp.prototype.setupTooltip = function() {
                var colDef = this.column.getColDef();
                if (colDef.headerTooltip) {
                    this.getGui().title = colDef.headerTooltip;
                }
            };
            HeaderWrapperComp.prototype.setupMovingCss = function() {
                this.addDestroyableEventListener(this.column, column_1.Column.EVENT_MOVING_CHANGED, this.onColumnMovingChanged.bind(this));
                this.onColumnMovingChanged();
            };
            HeaderWrapperComp.prototype.addAttributes = function() {
                this.getGui().setAttribute("col-id", this.column.getColId());
            };
            HeaderWrapperComp.prototype.setupWidth = function() {
                this.addDestroyableEventListener(this.column, column_1.Column.EVENT_WIDTH_CHANGED, this.onColumnWidthChanged.bind(this));
                this.onColumnWidthChanged();
            };
            HeaderWrapperComp.prototype.setupMenuClass = function() {
                this.addDestroyableEventListener(this.column, column_1.Column.EVENT_MENU_VISIBLE_CHANGED, this.onMenuVisible.bind(this));
                this.onColumnWidthChanged();
            };
            HeaderWrapperComp.prototype.onMenuVisible = function() {
                this.addOrRemoveCssClass("ag-column-menu-visible", this.column.isMenuVisible());
            };
            HeaderWrapperComp.prototype.onColumnWidthChanged = function() {
                this.getGui().style.width = this.column.getActualWidth() + "px";
            };
            HeaderWrapperComp.prototype.normaliseResizeAmount = function(dragChange) {
                var result = dragChange;
                if (this.gridOptionsWrapper.isEnableRtl()) {
                    if (this.pinned !== column_1.Column.PINNED_LEFT) {
                        result *= -1;
                    }
                } else {
                    if (this.pinned === column_1.Column.PINNED_RIGHT) {
                        result *= -1;
                    }
                }
                return result;
            };
            HeaderWrapperComp.TEMPLATE = '<div class="ag-header-cell" role="presentation" >' + '<div ref="eResize" class="ag-header-cell-resize" role="presentation"></div>' + '<ag-checkbox ref="cbSelectAll" class="ag-header-select-all" role="presentation"></ag-checkbox>' + "</div>";
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], HeaderWrapperComp.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("dragAndDropService"), __metadata("design:type", dragAndDropService_1.DragAndDropService) ], HeaderWrapperComp.prototype, "dragAndDropService", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], HeaderWrapperComp.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("horizontalResizeService"), __metadata("design:type", horizontalResizeService_1.HorizontalResizeService) ], HeaderWrapperComp.prototype, "horizontalResizeService", void 0);
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], HeaderWrapperComp.prototype, "context", void 0);
            __decorate([ context_1.Autowired("menuFactory"), __metadata("design:type", Object) ], HeaderWrapperComp.prototype, "menuFactory", void 0);
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], HeaderWrapperComp.prototype, "gridApi", void 0);
            __decorate([ context_1.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], HeaderWrapperComp.prototype, "columnApi", void 0);
            __decorate([ context_1.Autowired("sortController"), __metadata("design:type", sortController_1.SortController) ], HeaderWrapperComp.prototype, "sortController", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], HeaderWrapperComp.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("componentRecipes"), __metadata("design:type", componentRecipes_1.ComponentRecipes) ], HeaderWrapperComp.prototype, "componentRecipes", void 0);
            __decorate([ context_1.Autowired("columnHoverService"), __metadata("design:type", columnHoverService_1.ColumnHoverService) ], HeaderWrapperComp.prototype, "columnHoverService", void 0);
            __decorate([ context_1.Autowired("beans"), __metadata("design:type", beans_1.Beans) ], HeaderWrapperComp.prototype, "beans", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eResize"), __metadata("design:type", HTMLElement) ], HeaderWrapperComp.prototype, "eResize", void 0);
            __decorate([ componentAnnotations_1.RefSelector("cbSelectAll"), __metadata("design:type", agCheckbox_1.AgCheckbox) ], HeaderWrapperComp.prototype, "cbSelectAll", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], HeaderWrapperComp.prototype, "init", null);
            return HeaderWrapperComp;
        }(component_1.Component);
        exports.HeaderWrapperComp = HeaderWrapperComp;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var dragAndDropService_1 = __webpack_require__(15);
        var context_1 = __webpack_require__(0);
        var moveColumnController_1 = __webpack_require__(102);
        var column_1 = __webpack_require__(10);
        var bodyDropPivotTarget_1 = __webpack_require__(103);
        var columnController_1 = __webpack_require__(4);
        var DropType;
        (function(DropType) {
            DropType[DropType["ColumnMove"] = 0] = "ColumnMove";
            DropType[DropType["Pivot"] = 1] = "Pivot";
        })(DropType || (DropType = {}));
        var BodyDropTarget = function() {
            function BodyDropTarget(pinned, eContainer) {
                this.dropListeners = {};
                this.pinned = pinned;
                this.eContainer = eContainer;
            }
            BodyDropTarget.prototype.registerGridComp = function(gridPanel) {
                this.gridPanel = gridPanel;
                this.moveColumnController.registerGridComp(gridPanel);
                switch (this.pinned) {
                  case column_1.Column.PINNED_LEFT:
                    this.eSecondaryContainers = this.gridPanel.getDropTargetLeftContainers();
                    break;

                  case column_1.Column.PINNED_RIGHT:
                    this.eSecondaryContainers = this.gridPanel.getDropTargetRightContainers();
                    break;

                  default:
                    this.eSecondaryContainers = this.gridPanel.getDropTargetBodyContainers();
                    break;
                }
            };
            BodyDropTarget.prototype.isInterestedIn = function(type) {
                return type === dragAndDropService_1.DragSourceType.HeaderCell || type === dragAndDropService_1.DragSourceType.ToolPanel;
            };
            BodyDropTarget.prototype.getSecondaryContainers = function() {
                return this.eSecondaryContainers;
            };
            BodyDropTarget.prototype.getContainer = function() {
                return this.eContainer;
            };
            BodyDropTarget.prototype.init = function() {
                this.moveColumnController = new moveColumnController_1.MoveColumnController(this.pinned, this.eContainer);
                this.context.wireBean(this.moveColumnController);
                var bodyDropPivotTarget = new bodyDropPivotTarget_1.BodyDropPivotTarget(this.pinned);
                this.context.wireBean(bodyDropPivotTarget);
                this.dropListeners[DropType.ColumnMove] = this.moveColumnController;
                this.dropListeners[DropType.Pivot] = bodyDropPivotTarget;
                this.dragAndDropService.addDropTarget(this);
            };
            BodyDropTarget.prototype.getIconName = function() {
                return this.currentDropListener.getIconName();
            };
            BodyDropTarget.prototype.getDropType = function(draggingEvent) {
                if (this.columnController.isPivotMode()) {
                    if (draggingEvent.dragSource.type === dragAndDropService_1.DragSourceType.ToolPanel) {
                        return DropType.Pivot;
                    } else {
                        return DropType.ColumnMove;
                    }
                } else {
                    return DropType.ColumnMove;
                }
            };
            BodyDropTarget.prototype.onDragEnter = function(draggingEvent) {
                var dropType = this.getDropType(draggingEvent);
                this.currentDropListener = this.dropListeners[dropType];
                this.currentDropListener.onDragEnter(draggingEvent);
            };
            BodyDropTarget.prototype.onDragLeave = function(params) {
                this.currentDropListener.onDragLeave(params);
            };
            BodyDropTarget.prototype.onDragging = function(params) {
                this.currentDropListener.onDragging(params);
            };
            BodyDropTarget.prototype.onDragStop = function(params) {
                this.currentDropListener.onDragStop(params);
            };
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], BodyDropTarget.prototype, "context", void 0);
            __decorate([ context_1.Autowired("dragAndDropService"), __metadata("design:type", dragAndDropService_1.DragAndDropService) ], BodyDropTarget.prototype, "dragAndDropService", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], BodyDropTarget.prototype, "columnController", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], BodyDropTarget.prototype, "init", null);
            return BodyDropTarget;
        }();
        exports.BodyDropTarget = BodyDropTarget;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var logger_1 = __webpack_require__(12);
        var columnController_1 = __webpack_require__(4);
        var column_1 = __webpack_require__(10);
        var utils_1 = __webpack_require__(1);
        var dragAndDropService_1 = __webpack_require__(15);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var MoveColumnController = function() {
            function MoveColumnController(pinned, eContainer) {
                this.needToMoveLeft = false;
                this.needToMoveRight = false;
                this.pinned = pinned;
                this.eContainer = eContainer;
                this.centerContainer = !utils_1.Utils.exists(pinned);
            }
            MoveColumnController.prototype.registerGridComp = function(gridPanel) {
                this.gridPanel = gridPanel;
            };
            MoveColumnController.prototype.init = function() {
                this.logger = this.loggerFactory.create("MoveColumnController");
            };
            MoveColumnController.prototype.getIconName = function() {
                return this.pinned ? dragAndDropService_1.DragAndDropService.ICON_PINNED : dragAndDropService_1.DragAndDropService.ICON_MOVE;
            };
            MoveColumnController.prototype.onDragEnter = function(draggingEvent) {
                var columns = draggingEvent.dragItem.columns;
                var dragCameFromToolPanel = draggingEvent.dragSource.type === dragAndDropService_1.DragSourceType.ToolPanel;
                if (dragCameFromToolPanel) {
                    this.setColumnsVisible(columns, true, "uiColumnDragged");
                } else {
                    var visibleState_1 = draggingEvent.dragItem.visibleState;
                    var visibleColumns = columns.filter(function(column) {
                        return visibleState_1[column.getId()];
                    });
                    this.setColumnsVisible(visibleColumns, true, "uiColumnDragged");
                }
                this.setColumnsPinned(columns, this.pinned, "uiColumnDragged");
                this.onDragging(draggingEvent, true);
            };
            MoveColumnController.prototype.onDragLeave = function(draggingEvent) {
                var hideColumnOnExit = !this.gridOptionsWrapper.isSuppressDragLeaveHidesColumns() && !draggingEvent.fromNudge;
                if (hideColumnOnExit) {
                    var dragItem = draggingEvent.dragSource.dragItemCallback();
                    var columns = dragItem.columns;
                    this.setColumnsVisible(columns, false, "uiColumnDragged");
                }
                this.ensureIntervalCleared();
            };
            MoveColumnController.prototype.setColumnsVisible = function(columns, visible, source) {
                if (source === void 0) {
                    source = "api";
                }
                if (columns) {
                    var allowedCols = columns.filter(function(c) {
                        return !c.isLockVisible();
                    });
                    this.columnController.setColumnsVisible(allowedCols, visible, source);
                }
            };
            MoveColumnController.prototype.setColumnsPinned = function(columns, pinned, source) {
                if (source === void 0) {
                    source = "api";
                }
                if (columns) {
                    var allowedCols = columns.filter(function(c) {
                        return !c.isLockPinned();
                    });
                    this.columnController.setColumnsPinned(allowedCols, pinned, source);
                }
            };
            MoveColumnController.prototype.onDragStop = function() {
                this.ensureIntervalCleared();
            };
            MoveColumnController.prototype.normaliseX = function(x) {
                var flipHorizontallyForRtl = this.gridOptionsWrapper.isEnableRtl();
                if (flipHorizontallyForRtl) {
                    var clientWidth = this.eContainer.clientWidth;
                    x = clientWidth - x;
                }
                var adjustForScroll = this.centerContainer;
                if (adjustForScroll) {
                    x += this.gridPanel.getBodyViewportScrollLeft();
                }
                return x;
            };
            MoveColumnController.prototype.checkCenterForScrolling = function(xAdjustedForScroll) {
                if (this.centerContainer) {
                    var firstVisiblePixel = this.gridPanel.getBodyViewportScrollLeft();
                    var lastVisiblePixel = firstVisiblePixel + this.gridPanel.getCenterWidth();
                    if (this.gridOptionsWrapper.isEnableRtl()) {
                        this.needToMoveRight = xAdjustedForScroll < firstVisiblePixel + 50;
                        this.needToMoveLeft = xAdjustedForScroll > lastVisiblePixel - 50;
                    } else {
                        this.needToMoveLeft = xAdjustedForScroll < firstVisiblePixel + 50;
                        this.needToMoveRight = xAdjustedForScroll > lastVisiblePixel - 50;
                    }
                    if (this.needToMoveLeft || this.needToMoveRight) {
                        this.ensureIntervalStarted();
                    } else {
                        this.ensureIntervalCleared();
                    }
                }
            };
            MoveColumnController.prototype.onDragging = function(draggingEvent, fromEnter) {
                var _this = this;
                if (fromEnter === void 0) {
                    fromEnter = false;
                }
                this.lastDraggingEvent = draggingEvent;
                if (utils_1.Utils.missing(draggingEvent.hDirection)) {
                    return;
                }
                var xNormalised = this.normaliseX(draggingEvent.x);
                if (!fromEnter) {
                    this.checkCenterForScrolling(xNormalised);
                }
                var hDirectionNormalised = this.normaliseDirection(draggingEvent.hDirection);
                var dragSourceType = draggingEvent.dragSource.type;
                var columnsToMove = draggingEvent.dragSource.dragItemCallback().columns;
                columnsToMove = columnsToMove.filter(function(col) {
                    if (col.isLockPinned()) {
                        return col.getPinned() == _this.pinned;
                    } else {
                        return true;
                    }
                });
                this.attemptMoveColumns(dragSourceType, columnsToMove, hDirectionNormalised, xNormalised, fromEnter);
            };
            MoveColumnController.prototype.normaliseDirection = function(hDirection) {
                if (this.gridOptionsWrapper.isEnableRtl()) {
                    switch (hDirection) {
                      case dragAndDropService_1.HDirection.Left:
                        return dragAndDropService_1.HDirection.Right;

                      case dragAndDropService_1.HDirection.Right:
                        return dragAndDropService_1.HDirection.Left;

                      default:
                        console.error("ag-Grid: Unknown direction " + hDirection);
                    }
                } else {
                    return hDirection;
                }
            };
            MoveColumnController.prototype.calculateOldIndex = function(movingCols) {
                var gridCols = this.columnController.getAllGridColumns();
                var indexes = [];
                movingCols.forEach(function(col) {
                    return indexes.push(gridCols.indexOf(col));
                });
                utils_1.Utils.sortNumberArray(indexes);
                var firstIndex = indexes[0];
                var lastIndex = indexes[indexes.length - 1];
                var spread = lastIndex - firstIndex;
                var gapsExist = spread !== indexes.length - 1;
                return gapsExist ? null : firstIndex;
            };
            MoveColumnController.prototype.attemptMoveColumns = function(dragSourceType, allMovingColumns, hDirection, xAdjusted, fromEnter) {
                var draggingLeft = hDirection === dragAndDropService_1.HDirection.Left;
                var draggingRight = hDirection === dragAndDropService_1.HDirection.Right;
                var validMoves = this.calculateValidMoves(allMovingColumns, draggingRight, xAdjusted);
                var oldIndex = this.calculateOldIndex(allMovingColumns);
                for (var i = 0; i < validMoves.length; i++) {
                    var newIndex = validMoves[i];
                    var constrainDirection = oldIndex !== null && !fromEnter;
                    if (dragSourceType == dragAndDropService_1.DragSourceType.HeaderCell) {
                        constrainDirection = oldIndex !== null;
                    }
                    if (constrainDirection) {
                        if (draggingLeft && newIndex >= oldIndex) {
                            continue;
                        }
                        if (draggingRight && newIndex <= oldIndex) {
                            continue;
                        }
                    }
                    if (!this.columnController.doesMovePassRules(allMovingColumns, newIndex)) {
                        continue;
                    }
                    this.columnController.moveColumns(allMovingColumns, newIndex, "uiColumnDragged");
                    return;
                }
            };
            MoveColumnController.prototype.calculateValidMoves = function(movingCols, draggingRight, x) {
                var allDisplayedCols = this.columnController.getDisplayedColumns(this.pinned);
                var allGridCols = this.columnController.getAllGridColumns();
                var colIsMovingFunc = function(col) {
                    return movingCols.indexOf(col) >= 0;
                };
                var colIsNotMovingFunc = function(col) {
                    return movingCols.indexOf(col) < 0;
                };
                var movingDisplayedCols = allDisplayedCols.filter(colIsMovingFunc);
                var otherDisplayedCols = allDisplayedCols.filter(colIsNotMovingFunc);
                var otherGridCols = allGridCols.filter(colIsNotMovingFunc);
                var displayIndex = 0;
                var availableWidth = x;
                if (draggingRight) {
                    var widthOfMovingDisplayedCols_1 = 0;
                    movingDisplayedCols.forEach(function(col) {
                        return widthOfMovingDisplayedCols_1 += col.getActualWidth();
                    });
                    availableWidth -= widthOfMovingDisplayedCols_1;
                }
                for (var i = 0; i < otherDisplayedCols.length; i++) {
                    var col = otherDisplayedCols[i];
                    availableWidth -= col.getActualWidth();
                    if (availableWidth < 0) {
                        break;
                    }
                    displayIndex++;
                }
                if (draggingRight) {
                    displayIndex++;
                }
                var gridColIndex;
                if (displayIndex > 0) {
                    var leftColumn = otherDisplayedCols[displayIndex - 1];
                    gridColIndex = otherGridCols.indexOf(leftColumn) + 1;
                } else {
                    gridColIndex = 0;
                }
                var validMoves = [ gridColIndex ];
                var nextCol = allGridCols[gridColIndex];
                while (utils_1.Utils.exists(nextCol) && this.isColumnHidden(allDisplayedCols, nextCol)) {
                    gridColIndex++;
                    validMoves.push(gridColIndex);
                    nextCol = allGridCols[gridColIndex];
                }
                return validMoves;
            };
            MoveColumnController.prototype.isColumnHidden = function(displayedColumns, col) {
                return displayedColumns.indexOf(col) < 0;
            };
            MoveColumnController.prototype.ensureIntervalStarted = function() {
                if (!this.movingIntervalId) {
                    this.intervalCount = 0;
                    this.failedMoveAttempts = 0;
                    this.movingIntervalId = setInterval(this.moveInterval.bind(this), 100);
                    if (this.needToMoveLeft) {
                        this.dragAndDropService.setGhostIcon(dragAndDropService_1.DragAndDropService.ICON_LEFT, true);
                    } else {
                        this.dragAndDropService.setGhostIcon(dragAndDropService_1.DragAndDropService.ICON_RIGHT, true);
                    }
                }
            };
            MoveColumnController.prototype.ensureIntervalCleared = function() {
                if (this.moveInterval) {
                    clearInterval(this.movingIntervalId);
                    this.movingIntervalId = null;
                    this.dragAndDropService.setGhostIcon(dragAndDropService_1.DragAndDropService.ICON_MOVE);
                }
            };
            MoveColumnController.prototype.moveInterval = function() {
                var pixelsToMove;
                this.intervalCount++;
                pixelsToMove = 10 + this.intervalCount * 5;
                if (pixelsToMove > 100) {
                    pixelsToMove = 100;
                }
                var pixelsMoved;
                if (this.needToMoveLeft) {
                    pixelsMoved = this.gridPanel.scrollHorizontally(-pixelsToMove);
                } else if (this.needToMoveRight) {
                    pixelsMoved = this.gridPanel.scrollHorizontally(pixelsToMove);
                }
                if (pixelsMoved !== 0) {
                    this.onDragging(this.lastDraggingEvent);
                    this.failedMoveAttempts = 0;
                } else {
                    this.failedMoveAttempts++;
                    var columns = this.lastDraggingEvent.dragItem.columns;
                    var columnsThatCanPin = columns.filter(function(c) {
                        return !c.isLockPinned();
                    });
                    if (columnsThatCanPin.length > 0) {
                        this.dragAndDropService.setGhostIcon(dragAndDropService_1.DragAndDropService.ICON_PINNED);
                        if (this.failedMoveAttempts > 7) {
                            var pinType = this.needToMoveLeft ? column_1.Column.PINNED_LEFT : column_1.Column.PINNED_RIGHT;
                            this.setColumnsPinned(columnsThatCanPin, pinType, "uiColumnDragged");
                            this.dragAndDropService.nudge();
                        }
                    }
                }
            };
            __decorate([ context_1.Autowired("loggerFactory"), __metadata("design:type", logger_1.LoggerFactory) ], MoveColumnController.prototype, "loggerFactory", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], MoveColumnController.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("dragAndDropService"), __metadata("design:type", dragAndDropService_1.DragAndDropService) ], MoveColumnController.prototype, "dragAndDropService", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], MoveColumnController.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], MoveColumnController.prototype, "init", null);
            return MoveColumnController;
        }();
        exports.MoveColumnController = MoveColumnController;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var dragAndDropService_1 = __webpack_require__(15);
        var columnController_1 = __webpack_require__(4);
        var context_1 = __webpack_require__(0);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var BodyDropPivotTarget = function() {
            function BodyDropPivotTarget(pinned) {
                this.columnsToAggregate = [];
                this.columnsToGroup = [];
                this.columnsToPivot = [];
                this.pinned = pinned;
            }
            BodyDropPivotTarget.prototype.onDragEnter = function(draggingEvent) {
                var _this = this;
                this.clearColumnsList();
                if (this.gridOptionsWrapper.isFunctionsReadOnly()) {
                    return;
                }
                var dragColumns = draggingEvent.dragItem.columns;
                dragColumns.forEach(function(column) {
                    if (!column.isPrimary()) {
                        return;
                    }
                    if (column.isAnyFunctionActive()) {
                        return;
                    }
                    if (column.isAllowValue()) {
                        _this.columnsToAggregate.push(column);
                    } else if (column.isAllowRowGroup()) {
                        _this.columnsToGroup.push(column);
                    } else if (column.isAllowRowGroup()) {
                        _this.columnsToPivot.push(column);
                    }
                });
            };
            BodyDropPivotTarget.prototype.getIconName = function() {
                var totalColumns = this.columnsToAggregate.length + this.columnsToGroup.length + this.columnsToPivot.length;
                if (totalColumns > 0) {
                    return this.pinned ? dragAndDropService_1.DragAndDropService.ICON_PINNED : dragAndDropService_1.DragAndDropService.ICON_MOVE;
                } else {
                    return null;
                }
            };
            BodyDropPivotTarget.prototype.onDragLeave = function(draggingEvent) {
                this.clearColumnsList();
            };
            BodyDropPivotTarget.prototype.clearColumnsList = function() {
                this.columnsToAggregate.length = 0;
                this.columnsToGroup.length = 0;
                this.columnsToPivot.length = 0;
            };
            BodyDropPivotTarget.prototype.onDragging = function(draggingEvent) {};
            BodyDropPivotTarget.prototype.onDragStop = function(draggingEvent) {
                if (this.columnsToAggregate.length > 0) {
                    this.columnController.addValueColumns(this.columnsToAggregate, "toolPanelDragAndDrop");
                }
                if (this.columnsToGroup.length > 0) {
                    this.columnController.addRowGroupColumns(this.columnsToGroup, "toolPanelDragAndDrop");
                }
                if (this.columnsToPivot.length > 0) {
                    this.columnController.addPivotColumns(this.columnsToPivot, "toolPanelDragAndDrop");
                }
            };
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], BodyDropPivotTarget.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], BodyDropPivotTarget.prototype, "gridOptionsWrapper", void 0);
            return BodyDropPivotTarget;
        }();
        exports.BodyDropPivotTarget = BodyDropPivotTarget;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var column_1 = __webpack_require__(10);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var utils_1 = __webpack_require__(1);
        var columnController_1 = __webpack_require__(4);
        var balancedColumnTreeBuilder_1 = __webpack_require__(38);
        var AutoGroupColService = function() {
            function AutoGroupColService() {}
            AutoGroupColService_1 = AutoGroupColService;
            AutoGroupColService.prototype.createAutoGroupColumns = function(rowGroupColumns) {
                var _this = this;
                var groupAutoColumns = [];
                var doingTreeData = this.gridOptionsWrapper.isTreeData();
                var doingMultiAutoColumn = this.gridOptionsWrapper.isGroupMultiAutoColumn();
                if (doingTreeData && doingMultiAutoColumn) {
                    console.log("ag-Grid: you cannot mix groupMultiAutoColumn with treeData, only one column can be used to display groups when doing tree data");
                    doingMultiAutoColumn = false;
                }
                if (doingMultiAutoColumn) {
                    rowGroupColumns.forEach(function(rowGroupCol, index) {
                        groupAutoColumns.push(_this.createOneAutoGroupColumn(rowGroupCol, index));
                    });
                } else {
                    groupAutoColumns.push(this.createOneAutoGroupColumn(null));
                }
                return groupAutoColumns;
            };
            AutoGroupColService.prototype.createOneAutoGroupColumn = function(rowGroupCol, index) {
                var defaultAutoColDef = this.generateDefaultColDef(rowGroupCol);
                var colId;
                if (rowGroupCol) {
                    colId = AutoGroupColService_1.GROUP_AUTO_COLUMN_ID + "-" + rowGroupCol.getId();
                } else {
                    colId = AutoGroupColService_1.GROUP_AUTO_COLUMN_BUNDLE_ID;
                }
                var userAutoColDef = this.gridOptionsWrapper.getAutoGroupColumnDef();
                utils_1._.mergeDeep(defaultAutoColDef, userAutoColDef);
                defaultAutoColDef = this.balancedColumnTreeBuilder.mergeColDefs(defaultAutoColDef);
                defaultAutoColDef.colId = colId;
                if (!this.gridOptionsWrapper.isTreeData()) {
                    var noFieldOrValueGetter = utils_1._.missing(defaultAutoColDef.field) && utils_1._.missing(defaultAutoColDef.valueGetter) && utils_1._.missing(defaultAutoColDef.filterValueGetter);
                    if (noFieldOrValueGetter) {
                        defaultAutoColDef.suppressFilter = true;
                    }
                }
                if (index > 0) {
                    defaultAutoColDef.headerCheckboxSelection = false;
                }
                var newCol = new column_1.Column(defaultAutoColDef, colId, true);
                this.context.wireBean(newCol);
                return newCol;
            };
            AutoGroupColService.prototype.generateDefaultColDef = function(rowGroupCol) {
                var localeTextFunc = this.gridOptionsWrapper.getLocaleTextFunc();
                var defaultAutoColDef = {
                    headerName: localeTextFunc("group", "Group"),
                    cellRenderer: "agGroupCellRenderer"
                };
                if (rowGroupCol) {
                    var rowGroupColDef = rowGroupCol.getColDef();
                    utils_1._.assign(defaultAutoColDef, {
                        headerName: this.columnController.getDisplayNameForColumn(rowGroupCol, "header"),
                        headerValueGetter: rowGroupColDef.headerValueGetter
                    });
                    if (rowGroupColDef.cellRenderer) {
                        utils_1._.assign(defaultAutoColDef, {
                            cellRendererParams: {
                                innerRenderer: rowGroupColDef.cellRenderer,
                                innerRendererParams: rowGroupColDef.cellRendererParams
                            }
                        });
                    }
                    defaultAutoColDef.showRowGroup = rowGroupCol.getColId();
                } else {
                    defaultAutoColDef.showRowGroup = true;
                }
                return defaultAutoColDef;
            };
            AutoGroupColService.GROUP_AUTO_COLUMN_ID = "ag-Grid-AutoColumn";
            AutoGroupColService.GROUP_AUTO_COLUMN_BUNDLE_ID = AutoGroupColService_1.GROUP_AUTO_COLUMN_ID;
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], AutoGroupColService.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], AutoGroupColService.prototype, "context", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], AutoGroupColService.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("balancedColumnTreeBuilder"), __metadata("design:type", balancedColumnTreeBuilder_1.BalancedColumnTreeBuilder) ], AutoGroupColService.prototype, "balancedColumnTreeBuilder", void 0);
            AutoGroupColService = AutoGroupColService_1 = __decorate([ context_1.Bean("autoGroupColService") ], AutoGroupColService);
            return AutoGroupColService;
            var AutoGroupColService_1;
        }();
        exports.AutoGroupColService = AutoGroupColService;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var constants_1 = __webpack_require__(9);
        var utils_1 = __webpack_require__(1);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var ImmutableService = function() {
            function ImmutableService() {}
            ImmutableService.prototype.postConstruct = function() {
                if (this.rowModel.getType() === constants_1.Constants.ROW_MODEL_TYPE_CLIENT_SIDE) {
                    this.clientSideRowModel = this.rowModel;
                }
            };
            ImmutableService.prototype.createTransactionForRowData = function(data) {
                if (utils_1._.missing(this.clientSideRowModel)) {
                    console.error("ag-Grid: ImmutableService only works with ClientSideRowModel");
                    return;
                }
                var getRowNodeIdFunc = this.gridOptionsWrapper.getRowNodeIdFunc();
                if (utils_1._.missing(getRowNodeIdFunc)) {
                    console.error("ag-Grid: ImmutableService requires getRowNodeId() callback to be implemented, your row data need IDs!");
                    return;
                }
                var transaction = {
                    remove: [],
                    update: [],
                    add: []
                };
                var existingNodesMap = this.clientSideRowModel.getCopyOfNodesMap();
                var orderMap = {};
                if (utils_1._.exists(data)) {
                    data.forEach(function(dataItem, index) {
                        var id = getRowNodeIdFunc(dataItem);
                        var existingNode = existingNodesMap[id];
                        orderMap[id] = index;
                        if (existingNode) {
                            var dataHasChanged = existingNode.data !== dataItem;
                            if (dataHasChanged) {
                                transaction.update.push(dataItem);
                            }
                            existingNodesMap[id] = undefined;
                        } else {
                            transaction.add.push(dataItem);
                        }
                    });
                }
                utils_1._.iterateObject(existingNodesMap, function(id, rowNode) {
                    if (rowNode) {
                        transaction.remove.push(rowNode.data);
                    }
                });
                return [ transaction, orderMap ];
            };
            __decorate([ context_1.Autowired("rowModel"), __metadata("design:type", Object) ], ImmutableService.prototype, "rowModel", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], ImmutableService.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], ImmutableService.prototype, "postConstruct", null);
            ImmutableService = __decorate([ context_1.Bean("immutableService") ], ImmutableService);
            return ImmutableService;
        }();
        exports.ImmutableService = ImmutableService;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var ColDefUtil = function() {
            function ColDefUtil() {}
            ColDefUtil.STRING_PROPERTIES = [ "headerName", "columnGroupShow", "headerClass", "toolPanelClass", "headerValueGetter", "pivotKeys", "groupId", "colId", "sort", "field", "type", "tooltipField", "headerTooltip", "cellClass", "showRowGroup", "template", "templateUrl", "filter", "aggFunc", "cellRenderer", "cellEditor", "pinned" ];
            ColDefUtil.OBJECT_PROPERTIES = [ "headerGroupComponent", "headerGroupComponentFramework", "headerGroupComponentParams", "cellStyle", "cellRendererParams", "cellEditorFramework", "cellEditorParams", "pinnedRowCellRendererFramework", "pinnedRowCellRendererParams", "filterFramework", "filterParams", "pivotValueColumn", "headerComponent", "headerComponentFramework", "headerComponentParams", "floatingFilterComponent", "floatingFilterComponentParams", "floatingFilterComponentFramework", "refData" ];
            ColDefUtil.ARRAY_PROPERTIES = [ "children", "sortingOrder", "allowedAggFuncs", "menuTabs", "pivotTotalColumnIds", "cellClassRules", "icons" ];
            ColDefUtil.NUMBER_PROPERTIES = [ "sortedAt", "width", "minWidth", "maxWidth", "rowGroupIndex", "pivotIndex" ];
            ColDefUtil.BOOLEAN_PROPERTIES = [ "suppressCellFlash", "suppressToolPanel", "openByDefault", "marryChildren", "hide", "rowGroup", "pivot", "checkboxSelection", "headerCheckboxSelection", "headerCheckboxSelectionFilteredOnly", "suppressMenu", "suppressSorting", "suppressMovable", "suppressFilter", "lockPosition", "lockVisible", "lockPinned", "unSortIcon", "suppressSizeToFit", "suppressResize", "suppressAutoSize", "enableRowGroup", "enablePivot", "enableValue", "editable", "suppressPaste", "suppressNavigable", "enableCellChangeFlash", "rowDrag", "autoHeight" ];
            ColDefUtil.FUNCTION_PROPERTIES = [ "valueGetter", "valueSetter", "filterValueGetter", "keyCreator", "cellRenderer", "cellRendererFramework", "pinnedRowCellRenderer", "valueFormatter", "pinnedRowValueFormatter", "valueParser", "comparator", "equals", "pivotComparator", "suppressKeyboardEvent", "colSpan", "rowSpan", "getQuickFilterText", "newValueHandler", "onCellValueChanged", "onCellClicked", "onCellDoubleClicked", "onCellContextMenu", "tooltip", "cellRendererSelector", "cellEditorSelector" ];
            ColDefUtil.ALL_PROPERTIES = ColDefUtil.ARRAY_PROPERTIES.concat(ColDefUtil.OBJECT_PROPERTIES).concat(ColDefUtil.STRING_PROPERTIES).concat(ColDefUtil.NUMBER_PROPERTIES).concat(ColDefUtil.FUNCTION_PROPERTIES).concat(ColDefUtil.BOOLEAN_PROPERTIES);
            return ColDefUtil;
        }();
        exports.ColDefUtil = ColDefUtil;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var ColumnKeyCreator = function() {
            function ColumnKeyCreator() {
                this.existingKeys = [];
            }
            ColumnKeyCreator.prototype.getUniqueKey = function(colId, colField) {
                colId = utils_1.Utils.toStringOrNull(colId);
                var count = 0;
                while (true) {
                    var idToTry = void 0;
                    if (colId) {
                        idToTry = colId;
                        if (count !== 0) {
                            idToTry += "_" + count;
                        }
                    } else if (colField) {
                        idToTry = colField;
                        if (count !== 0) {
                            idToTry += "_" + count;
                        }
                    } else {
                        idToTry = "" + count;
                    }
                    if (this.existingKeys.indexOf(idToTry) < 0) {
                        this.existingKeys.push(idToTry);
                        return idToTry;
                    }
                    count++;
                }
            };
            return ColumnKeyCreator;
        }();
        exports.ColumnKeyCreator = ColumnKeyCreator;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var filterManager_1 = __webpack_require__(18);
        var utils_1 = __webpack_require__(1);
        var popupService_1 = __webpack_require__(35);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var eventService_1 = __webpack_require__(3);
        var StandardMenuFactory = function() {
            function StandardMenuFactory() {}
            StandardMenuFactory.prototype.hideActiveMenu = function() {
                if (this.hidePopup) {
                    this.hidePopup();
                }
            };
            StandardMenuFactory.prototype.showMenuAfterMouseEvent = function(column, mouseEvent) {
                var _this = this;
                this.showPopup(column, function(eMenu) {
                    _this.popupService.positionPopupUnderMouseEvent({
                        column: column,
                        type: "columnMenu",
                        mouseEvent: mouseEvent,
                        ePopup: eMenu
                    });
                });
            };
            StandardMenuFactory.prototype.showMenuAfterButtonClick = function(column, eventSource) {
                var _this = this;
                this.showPopup(column, function(eMenu) {
                    _this.popupService.positionPopupUnderComponent({
                        type: "columnMenu",
                        eventSource: eventSource,
                        ePopup: eMenu,
                        keepWithinBounds: true,
                        column: column
                    });
                });
            };
            StandardMenuFactory.prototype.showPopup = function(column, positionCallback) {
                var _this = this;
                var filterWrapper = this.filterManager.getOrCreateFilterWrapper(column);
                var eMenu = document.createElement("div");
                utils_1.Utils.addCssClass(eMenu, "ag-menu");
                filterWrapper.guiPromise.promise.then(function(gui) {
                    eMenu.appendChild(gui);
                });
                var hidePopup;
                var bodyScrollListener = function(event) {
                    if (event.direction === "horizontal") {
                        hidePopup();
                    }
                };
                this.eventService.addEventListener("bodyScroll", bodyScrollListener);
                var closedCallback = function() {
                    _this.eventService.removeEventListener("bodyScroll", bodyScrollListener);
                    column.setMenuVisible(false, "contextMenu");
                };
                hidePopup = this.popupService.addAsModalPopup(eMenu, true, closedCallback);
                positionCallback(eMenu);
                filterWrapper.filterPromise.then(function(filter) {
                    if (filter.afterGuiAttached) {
                        var params = {
                            hidePopup: hidePopup
                        };
                        filter.afterGuiAttached(params);
                    }
                });
                this.hidePopup = hidePopup;
                column.setMenuVisible(true, "contextMenu");
            };
            StandardMenuFactory.prototype.isMenuEnabled = function(column) {
                return this.gridOptionsWrapper.isEnableFilter() && column.isFilterAllowed();
            };
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], StandardMenuFactory.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("filterManager"), __metadata("design:type", filterManager_1.FilterManager) ], StandardMenuFactory.prototype, "filterManager", void 0);
            __decorate([ context_1.Autowired("popupService"), __metadata("design:type", popupService_1.PopupService) ], StandardMenuFactory.prototype, "popupService", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], StandardMenuFactory.prototype, "gridOptionsWrapper", void 0);
            StandardMenuFactory = __decorate([ context_1.Bean("menuFactory") ], StandardMenuFactory);
            return StandardMenuFactory;
        }();
        exports.StandardMenuFactory = StandardMenuFactory;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var filterService_1 = __webpack_require__(110);
        var selectableService_1 = __webpack_require__(86);
        var FilterStage = function() {
            function FilterStage() {}
            FilterStage.prototype.execute = function(params) {
                var rowNode = params.rowNode;
                if (this.gridOptionsWrapper.isEnableServerSideFilter()) {
                    this.filterService.filter(rowNode, false);
                } else {
                    this.filterService.filterAccordingToColumnState(rowNode);
                }
                this.selectableService.updateSelectableAfterFiltering(rowNode);
            };
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], FilterStage.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("selectableService"), __metadata("design:type", selectableService_1.SelectableService) ], FilterStage.prototype, "selectableService", void 0);
            __decorate([ context_1.Autowired("filterService"), __metadata("design:type", filterService_1.FilterService) ], FilterStage.prototype, "filterService", void 0);
            FilterStage = __decorate([ context_1.Bean("filterStage") ], FilterStage);
            return FilterStage;
        }();
        exports.FilterStage = FilterStage;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var filterManager_1 = __webpack_require__(18);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var FilterService = function() {
            function FilterService() {}
            FilterService.prototype.postConstruct = function() {
                this.doingTreeData = this.gridOptionsWrapper.isTreeData();
            };
            FilterService.prototype.filterAccordingToColumnState = function(rowNode) {
                var filterActive = this.filterManager.isAnyFilterPresent();
                this.filter(rowNode, filterActive);
            };
            FilterService.prototype.filter = function(rowNode, filterActive) {
                var _this = this;
                if (rowNode.hasChildren()) {
                    rowNode.childrenAfterGroup.forEach(function(node) {
                        return _this.filter(node, filterActive);
                    });
                    if (filterActive) {
                        rowNode.childrenAfterFilter = rowNode.childrenAfterGroup.filter(function(childNode) {
                            var passBecauseChildren = childNode.childrenAfterFilter && childNode.childrenAfterFilter.length > 0;
                            var passBecauseDataPasses = childNode.data && _this.filterManager.doesRowPassFilter(childNode);
                            return passBecauseChildren || passBecauseDataPasses;
                        });
                    } else {
                        rowNode.childrenAfterFilter = rowNode.childrenAfterGroup;
                    }
                    this.setAllChildrenCount(rowNode);
                } else {
                    rowNode.childrenAfterFilter = rowNode.childrenAfterGroup;
                    rowNode.setAllChildrenCount(null);
                }
            };
            FilterService.prototype.setAllChildrenCountTreeData = function(rowNode) {
                var allChildrenCount = 0;
                rowNode.childrenAfterFilter.forEach(function(child) {
                    allChildrenCount++;
                    allChildrenCount += child.allChildrenCount;
                });
                rowNode.setAllChildrenCount(allChildrenCount);
            };
            FilterService.prototype.setAllChildrenCountGridGrouping = function(rowNode) {
                var allChildrenCount = 0;
                rowNode.childrenAfterFilter.forEach(function(child) {
                    if (child.group) {
                        allChildrenCount += child.allChildrenCount;
                    } else {
                        allChildrenCount++;
                    }
                });
                rowNode.setAllChildrenCount(allChildrenCount);
            };
            FilterService.prototype.setAllChildrenCount = function(rowNode) {
                if (this.doingTreeData) {
                    this.setAllChildrenCountTreeData(rowNode);
                } else {
                    this.setAllChildrenCountGridGrouping(rowNode);
                }
            };
            __decorate([ context_1.Autowired("filterManager"), __metadata("design:type", filterManager_1.FilterManager) ], FilterService.prototype, "filterManager", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], FilterService.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], FilterService.prototype, "postConstruct", null);
            FilterService = __decorate([ context_1.Bean("filterService") ], FilterService);
            return FilterService;
        }();
        exports.FilterService = FilterService;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var sortService_1 = __webpack_require__(112);
        var SortStage = function() {
            function SortStage() {}
            SortStage.prototype.execute = function(params) {
                if (this.gridOptionsWrapper.isEnableServerSideSorting()) {
                    this.sortService.sort(params.rowNode, null);
                } else {
                    this.sortService.sortAccordingToColumnsState(params.rowNode);
                }
            };
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], SortStage.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("sortService"), __metadata("design:type", sortService_1.SortService) ], SortStage.prototype, "sortService", void 0);
            SortStage = __decorate([ context_1.Bean("sortStage") ], SortStage);
            return SortStage;
        }();
        exports.SortStage = SortStage;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var sortController_1 = __webpack_require__(24);
        var utils_1 = __webpack_require__(1);
        var valueService_1 = __webpack_require__(16);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var columnController_1 = __webpack_require__(4);
        var SortService = function() {
            function SortService() {}
            SortService.prototype.init = function() {
                this.postSortFunc = this.gridOptionsWrapper.getPostSortFunc();
            };
            SortService.prototype.sortAccordingToColumnsState = function(rowNode) {
                var sortOptions = this.sortController.getSortForRowController();
                this.sort(rowNode, sortOptions);
            };
            SortService.prototype.sort = function(rowNode, sortOptions) {
                var _this = this;
                rowNode.childrenAfterSort = rowNode.childrenAfterFilter.slice(0);
                this.pullDownDataForHideOpenParents(rowNode, true);
                var sortActive = utils_1._.exists(sortOptions) && sortOptions.length > 0;
                if (sortActive) {
                    var sortedRowNodes = rowNode.childrenAfterSort.map(function(it, pos) {
                        return {
                            currentPos: pos,
                            rowNode: it
                        };
                    });
                    sortedRowNodes.sort(this.compareRowNodes.bind(this, sortOptions));
                    rowNode.childrenAfterSort = sortedRowNodes.map(function(sorted) {
                        return sorted.rowNode;
                    });
                }
                this.updateChildIndexes(rowNode);
                this.pullDownDataForHideOpenParents(rowNode, false);
                rowNode.childrenAfterFilter.forEach(function(child) {
                    if (child.hasChildren()) {
                        _this.sort(child, sortOptions);
                    }
                });
                if (this.postSortFunc) {
                    this.postSortFunc(rowNode.childrenAfterSort);
                }
            };
            SortService.prototype.compareRowNodes = function(sortOptions, sortedNodeA, sortedNodeB) {
                var nodeA = sortedNodeA.rowNode;
                var nodeB = sortedNodeB.rowNode;
                for (var i = 0, len = sortOptions.length; i < len; i++) {
                    var sortOption = sortOptions[i];
                    var isInverted = sortOption.inverter === -1;
                    var valueA = this.getValue(nodeA, sortOption.column);
                    var valueB = this.getValue(nodeB, sortOption.column);
                    var comparatorResult = void 0;
                    if (sortOption.column.getColDef().comparator) {
                        comparatorResult = sortOption.column.getColDef().comparator(valueA, valueB, nodeA, nodeB, isInverted);
                    } else {
                        comparatorResult = utils_1._.defaultComparator(valueA, valueB, this.gridOptionsWrapper.isAccentedSort());
                    }
                    if (comparatorResult !== 0) {
                        return comparatorResult * sortOption.inverter;
                    }
                }
                return sortedNodeA.currentPos - sortedNodeB.currentPos;
            };
            SortService.prototype.getValue = function(nodeA, column) {
                return this.valueService.getValue(column, nodeA);
            };
            SortService.prototype.updateChildIndexes = function(rowNode) {
                if (utils_1._.missing(rowNode.childrenAfterSort)) {
                    return;
                }
                rowNode.childrenAfterSort.forEach(function(child, index) {
                    var firstChild = index === 0;
                    var lastChild = index === rowNode.childrenAfterSort.length - 1;
                    child.setFirstChild(firstChild);
                    child.setLastChild(lastChild);
                    child.setChildIndex(index);
                });
            };
            SortService.prototype.pullDownDataForHideOpenParents = function(rowNode, clearOperation) {
                var _this = this;
                if (utils_1._.missing(rowNode.childrenAfterSort)) {
                    return;
                }
                if (!this.gridOptionsWrapper.isGroupHideOpenParents()) {
                    return;
                }
                rowNode.childrenAfterSort.forEach(function(childRowNode) {
                    var groupDisplayCols = _this.columnController.getGroupDisplayColumns();
                    groupDisplayCols.forEach(function(groupDisplayCol) {
                        var showRowGroup = groupDisplayCol.getColDef().showRowGroup;
                        if (typeof showRowGroup !== "string") {
                            console.error("ag-Grid: groupHideOpenParents only works when specifying specific columns for colDef.showRowGroup");
                            return;
                        }
                        var displayingGroupKey = showRowGroup;
                        var rowGroupColumn = _this.columnController.getPrimaryColumn(displayingGroupKey);
                        var thisRowNodeMatches = rowGroupColumn === childRowNode.rowGroupColumn;
                        if (thisRowNodeMatches) {
                            return;
                        }
                        if (clearOperation) {
                            childRowNode.setGroupValue(groupDisplayCol.getId(), null);
                        } else {
                            var parentToStealFrom = childRowNode.getFirstChildOfFirstChild(rowGroupColumn);
                            if (parentToStealFrom) {
                                childRowNode.setGroupValue(groupDisplayCol.getId(), parentToStealFrom.key);
                            }
                        }
                    });
                });
            };
            __decorate([ context_1.Autowired("sortController"), __metadata("design:type", sortController_1.SortController) ], SortService.prototype, "sortController", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], SortService.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("valueService"), __metadata("design:type", valueService_1.ValueService) ], SortService.prototype, "valueService", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], SortService.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], SortService.prototype, "init", null);
            SortService = __decorate([ context_1.Bean("sortService") ], SortService);
            return SortService;
        }();
        exports.SortService = SortService;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var rowNode_1 = __webpack_require__(14);
        var utils_1 = __webpack_require__(1);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var selectionController_1 = __webpack_require__(17);
        var eventService_1 = __webpack_require__(3);
        var columnController_1 = __webpack_require__(4);
        var FlattenStage = function() {
            function FlattenStage() {}
            FlattenStage.prototype.execute = function(params) {
                var rootNode = params.rowNode;
                var result = [];
                var nextRowTop = {
                    value: 0
                };
                var skipLeafNodes = this.columnController.isPivotMode();
                var showRootNode = skipLeafNodes && rootNode.leafGroup;
                var topList = showRootNode ? [ rootNode ] : rootNode.childrenAfterSort;
                this.resetRowTops(rootNode);
                this.recursivelyAddToRowsToDisplay(topList, result, nextRowTop, skipLeafNodes, 0);
                var includeGroupTotalFooter = !showRootNode && this.gridOptionsWrapper.isGroupIncludeTotalFooter();
                if (includeGroupTotalFooter) {
                    this.ensureFooterNodeExists(rootNode);
                    this.addRowNodeToRowsToDisplay(rootNode.sibling, result, nextRowTop, 0);
                }
                return result;
            };
            FlattenStage.prototype.resetRowTops = function(rowNode) {
                rowNode.clearRowTop();
                if (rowNode.hasChildren()) {
                    if (rowNode.childrenAfterGroup) {
                        for (var i = 0; i < rowNode.childrenAfterGroup.length; i++) {
                            this.resetRowTops(rowNode.childrenAfterGroup[i]);
                        }
                    }
                    if (rowNode.sibling) {
                        rowNode.sibling.clearRowTop();
                    }
                }
            };
            FlattenStage.prototype.recursivelyAddToRowsToDisplay = function(rowsToFlatten, result, nextRowTop, skipLeafNodes, uiLevel) {
                if (utils_1.Utils.missingOrEmpty(rowsToFlatten)) {
                    return;
                }
                var groupSuppressRow = this.gridOptionsWrapper.isGroupSuppressRow();
                var hideOpenParents = this.gridOptionsWrapper.isGroupHideOpenParents();
                var groupRemoveSingleChildren = this.gridOptionsWrapper.isGroupRemoveSingleChildren();
                var groupRemoveLowestSingleChildren = !groupRemoveSingleChildren && this.gridOptionsWrapper.isGroupRemoveLowestSingleChildren();
                for (var i = 0; i < rowsToFlatten.length; i++) {
                    var rowNode = rowsToFlatten[i];
                    var isParent = rowNode.hasChildren();
                    var isGroupSuppressedNode = groupSuppressRow && isParent;
                    var isSkippedLeafNode = skipLeafNodes && !isParent;
                    var isRemovedSingleChildrenGroup = groupRemoveSingleChildren && isParent && rowNode.childrenAfterGroup.length === 1;
                    var isRemovedLowestSingleChildrenGroup = groupRemoveLowestSingleChildren && isParent && rowNode.leafGroup && rowNode.childrenAfterGroup.length === 1;
                    var neverAllowToExpand = skipLeafNodes && rowNode.leafGroup;
                    var isHiddenOpenParent = hideOpenParents && rowNode.expanded && !neverAllowToExpand;
                    var thisRowShouldBeRendered = !isSkippedLeafNode && !isGroupSuppressedNode && !isHiddenOpenParent && !isRemovedSingleChildrenGroup && !isRemovedLowestSingleChildrenGroup;
                    if (thisRowShouldBeRendered) {
                        this.addRowNodeToRowsToDisplay(rowNode, result, nextRowTop, uiLevel);
                    }
                    if (skipLeafNodes && rowNode.leafGroup) {
                        continue;
                    }
                    if (isParent) {
                        var excludedParent = isRemovedSingleChildrenGroup || isRemovedLowestSingleChildrenGroup;
                        if (rowNode.expanded || excludedParent) {
                            var uiLevelForChildren = excludedParent ? uiLevel : uiLevel + 1;
                            this.recursivelyAddToRowsToDisplay(rowNode.childrenAfterSort, result, nextRowTop, skipLeafNodes, uiLevelForChildren);
                            if (this.gridOptionsWrapper.isGroupIncludeFooter()) {
                                this.ensureFooterNodeExists(rowNode);
                                this.addRowNodeToRowsToDisplay(rowNode.sibling, result, nextRowTop, uiLevel);
                            }
                        } else {}
                    } else if (rowNode.master && rowNode.expanded) {
                        var detailNode = this.createDetailNode(rowNode);
                        this.addRowNodeToRowsToDisplay(detailNode, result, nextRowTop, uiLevel);
                    }
                }
            };
            FlattenStage.prototype.addRowNodeToRowsToDisplay = function(rowNode, result, nextRowTop, uiLevel) {
                result.push(rowNode);
                if (utils_1.Utils.missing(rowNode.rowHeight)) {
                    var rowHeight = this.gridOptionsWrapper.getRowHeightForNode(rowNode);
                    rowNode.setRowHeight(rowHeight);
                }
                rowNode.setUiLevel(uiLevel);
                rowNode.setRowTop(nextRowTop.value);
                rowNode.setRowIndex(result.length - 1);
                nextRowTop.value += rowNode.rowHeight;
            };
            FlattenStage.prototype.ensureFooterNodeExists = function(groupNode) {
                if (utils_1.Utils.exists(groupNode.sibling)) {
                    return;
                }
                var footerNode = new rowNode_1.RowNode();
                this.context.wireBean(footerNode);
                Object.keys(groupNode).forEach(function(key) {
                    footerNode[key] = groupNode[key];
                });
                footerNode.footer = true;
                footerNode.rowTop = null;
                footerNode.oldRowTop = null;
                if (utils_1.Utils.exists(footerNode.id)) {
                    footerNode.id = "rowGroupFooter_" + footerNode.id;
                }
                footerNode.sibling = groupNode;
                groupNode.sibling = footerNode;
            };
            FlattenStage.prototype.createDetailNode = function(masterNode) {
                if (utils_1.Utils.exists(masterNode.detailNode)) {
                    return masterNode.detailNode;
                } else {
                    var detailNode = new rowNode_1.RowNode();
                    this.context.wireBean(detailNode);
                    detailNode.detail = true;
                    detailNode.flower = detailNode.detail;
                    detailNode.parent = masterNode;
                    if (utils_1.Utils.exists(masterNode.id)) {
                        detailNode.id = "detail_" + masterNode.id;
                    }
                    detailNode.data = masterNode.data;
                    detailNode.level = masterNode.level + 1;
                    masterNode.detailNode = detailNode;
                    masterNode.childFlower = masterNode.detailNode;
                    return detailNode;
                }
            };
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], FlattenStage.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("selectionController"), __metadata("design:type", selectionController_1.SelectionController) ], FlattenStage.prototype, "selectionController", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], FlattenStage.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], FlattenStage.prototype, "context", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], FlattenStage.prototype, "columnController", void 0);
            FlattenStage = __decorate([ context_1.Bean("flattenStage") ], FlattenStage);
            return FlattenStage;
        }();
        exports.FlattenStage = FlattenStage;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var context_1 = __webpack_require__(0);
        var eventService_1 = __webpack_require__(3);
        var selectionController_1 = __webpack_require__(17);
        var events_1 = __webpack_require__(5);
        var sortController_1 = __webpack_require__(24);
        var filterManager_1 = __webpack_require__(18);
        var constants_1 = __webpack_require__(9);
        var infiniteCache_1 = __webpack_require__(136);
        var beanStub_1 = __webpack_require__(13);
        var rowNodeCache_1 = __webpack_require__(87);
        var rowNodeBlockLoader_1 = __webpack_require__(115);
        var gridApi_1 = __webpack_require__(6);
        var columnApi_1 = __webpack_require__(7);
        var InfiniteRowModel = function(_super) {
            __extends(InfiniteRowModel, _super);
            function InfiniteRowModel() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            InfiniteRowModel.prototype.getRowBounds = function(index) {
                return {
                    rowHeight: this.rowHeight,
                    rowTop: this.rowHeight * index
                };
            };
            InfiniteRowModel.prototype.init = function() {
                var _this = this;
                if (!this.gridOptionsWrapper.isRowModelInfinite()) {
                    return;
                }
                this.rowHeight = this.gridOptionsWrapper.getRowHeightAsNumber();
                this.addEventListeners();
                this.setDatasource(this.gridOptionsWrapper.getDatasource());
                this.addDestroyFunc(function() {
                    return _this.destroyCache();
                });
            };
            InfiniteRowModel.prototype.destroyDatasource = function() {
                if (this.datasource && this.datasource.destroy) {
                    this.datasource.destroy();
                }
                this.datasource = null;
            };
            InfiniteRowModel.prototype.isLastRowFound = function() {
                return this.infiniteCache ? this.infiniteCache.isMaxRowFound() : false;
            };
            InfiniteRowModel.prototype.addEventListeners = function() {
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_FILTER_CHANGED, this.onFilterChanged.bind(this));
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_SORT_CHANGED, this.onSortChanged.bind(this));
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_COLUMN_EVERYTHING_CHANGED, this.onColumnEverything.bind(this));
            };
            InfiniteRowModel.prototype.onFilterChanged = function() {
                if (this.gridOptionsWrapper.isEnableServerSideFilter()) {
                    this.reset();
                }
            };
            InfiniteRowModel.prototype.onSortChanged = function() {
                if (this.gridOptionsWrapper.isEnableServerSideSorting()) {
                    this.reset();
                }
            };
            InfiniteRowModel.prototype.onColumnEverything = function() {
                if (this.gridOptionsWrapper.isEnableServerSideSorting()) {
                    this.reset();
                }
            };
            InfiniteRowModel.prototype.destroy = function() {
                _super.prototype.destroy.call(this);
            };
            InfiniteRowModel.prototype.getType = function() {
                return constants_1.Constants.ROW_MODEL_TYPE_INFINITE;
            };
            InfiniteRowModel.prototype.setDatasource = function(datasource) {
                this.destroyDatasource();
                this.datasource = datasource;
                if (datasource) {
                    this.checkForDeprecated();
                    this.reset();
                }
            };
            InfiniteRowModel.prototype.checkForDeprecated = function() {
                var ds = this.datasource;
                if (utils_1.Utils.exists(ds.maxConcurrentRequests)) {
                    console.error("ag-Grid: since version 5.1.x, maxConcurrentRequests is replaced with grid property maxConcurrentDatasourceRequests");
                }
                if (utils_1.Utils.exists(ds.maxPagesInCache)) {
                    console.error("ag-Grid: since version 5.1.x, maxPagesInCache is replaced with grid property maxPagesInPaginationCache");
                }
                if (utils_1.Utils.exists(ds.overflowSize)) {
                    console.error("ag-Grid: since version 5.1.x, overflowSize is replaced with grid property paginationOverflowSize");
                }
                if (utils_1.Utils.exists(ds.blockSize)) {
                    console.error("ag-Grid: since version 5.1.x, pageSize/blockSize is replaced with grid property infinitePageSize");
                }
            };
            InfiniteRowModel.prototype.isEmpty = function() {
                return utils_1.Utils.missing(this.infiniteCache);
            };
            InfiniteRowModel.prototype.isRowsToRender = function() {
                return utils_1.Utils.exists(this.infiniteCache);
            };
            InfiniteRowModel.prototype.getNodesInRangeForSelection = function(firstInRange, lastInRange) {
                return this.infiniteCache.getRowNodesInRange(firstInRange, lastInRange);
            };
            InfiniteRowModel.prototype.reset = function() {
                if (utils_1.Utils.missing(this.datasource)) {
                    return;
                }
                var userGeneratingIds = utils_1.Utils.exists(this.gridOptionsWrapper.getRowNodeIdFunc());
                if (!userGeneratingIds) {
                    this.selectionController.reset();
                }
                this.resetCache();
                var event = this.createModelUpdatedEvent();
                this.eventService.dispatchEvent(event);
            };
            InfiniteRowModel.prototype.createModelUpdatedEvent = function() {
                return {
                    type: events_1.Events.EVENT_MODEL_UPDATED,
                    api: this.gridApi,
                    columnApi: this.columnApi,
                    newPage: false,
                    newData: false,
                    keepRenderedRows: false,
                    animate: false
                };
            };
            InfiniteRowModel.prototype.resetCache = function() {
                this.destroyCache();
                var maxConcurrentRequests = this.gridOptionsWrapper.getMaxConcurrentDatasourceRequests();
                this.rowNodeBlockLoader = new rowNodeBlockLoader_1.RowNodeBlockLoader(maxConcurrentRequests);
                this.context.wireBean(this.rowNodeBlockLoader);
                var cacheSettings = {
                    datasource: this.datasource,
                    filterModel: this.filterManager.getFilterModel(),
                    sortModel: this.sortController.getSortModel(),
                    rowNodeBlockLoader: this.rowNodeBlockLoader,
                    maxConcurrentRequests: maxConcurrentRequests,
                    overflowSize: this.gridOptionsWrapper.getCacheOverflowSize(),
                    initialRowCount: this.gridOptionsWrapper.getInfiniteInitialRowCount(),
                    maxBlocksInCache: this.gridOptionsWrapper.getMaxBlocksInCache(),
                    blockSize: this.gridOptionsWrapper.getCacheBlockSize(),
                    rowHeight: this.gridOptionsWrapper.getRowHeightAsNumber(),
                    lastAccessedSequence: new utils_1.NumberSequence()
                };
                if (!(cacheSettings.maxConcurrentRequests >= 1)) {
                    cacheSettings.maxConcurrentRequests = 2;
                }
                if (!(cacheSettings.blockSize >= 1)) {
                    cacheSettings.blockSize = 100;
                }
                if (!(cacheSettings.initialRowCount >= 1)) {
                    cacheSettings.initialRowCount = 0;
                }
                if (!(cacheSettings.overflowSize >= 1)) {
                    cacheSettings.overflowSize = 1;
                }
                this.infiniteCache = new infiniteCache_1.InfiniteCache(cacheSettings);
                this.context.wireBean(this.infiniteCache);
                this.infiniteCache.addEventListener(rowNodeCache_1.RowNodeCache.EVENT_CACHE_UPDATED, this.onCacheUpdated.bind(this));
            };
            InfiniteRowModel.prototype.destroyCache = function() {
                if (this.infiniteCache) {
                    this.infiniteCache.destroy();
                    this.infiniteCache = null;
                }
                if (this.rowNodeBlockLoader) {
                    this.rowNodeBlockLoader.destroy();
                    this.rowNodeBlockLoader = null;
                }
            };
            InfiniteRowModel.prototype.onCacheUpdated = function() {
                var event = this.createModelUpdatedEvent();
                this.eventService.dispatchEvent(event);
            };
            InfiniteRowModel.prototype.getRow = function(rowIndex) {
                return this.infiniteCache ? this.infiniteCache.getRow(rowIndex) : null;
            };
            InfiniteRowModel.prototype.getRowNode = function(id) {
                var result = null;
                this.forEachNode(function(rowNode) {
                    if (rowNode.id === id) {
                        result = rowNode;
                    }
                });
                return result;
            };
            InfiniteRowModel.prototype.forEachNode = function(callback) {
                if (this.infiniteCache) {
                    this.infiniteCache.forEachNodeDeep(callback, new utils_1.NumberSequence());
                }
            };
            InfiniteRowModel.prototype.getCurrentPageHeight = function() {
                return this.getRowCount() * this.rowHeight;
            };
            InfiniteRowModel.prototype.getRowIndexAtPixel = function(pixel) {
                if (this.rowHeight !== 0) {
                    var rowIndexForPixel = Math.floor(pixel / this.rowHeight);
                    if (rowIndexForPixel > this.getPageLastRow()) {
                        return this.getPageLastRow();
                    } else {
                        return rowIndexForPixel;
                    }
                } else {
                    return 0;
                }
            };
            InfiniteRowModel.prototype.getPageFirstRow = function() {
                return 0;
            };
            InfiniteRowModel.prototype.getPageLastRow = function() {
                return this.infiniteCache ? this.infiniteCache.getVirtualRowCount() - 1 : 0;
            };
            InfiniteRowModel.prototype.getRowCount = function() {
                return this.infiniteCache ? this.infiniteCache.getVirtualRowCount() : 0;
            };
            InfiniteRowModel.prototype.updateRowData = function(transaction) {
                if (utils_1.Utils.exists(transaction.remove) || utils_1.Utils.exists(transaction.update)) {
                    console.warn("ag-Grid: updateRowData for InfiniteRowModel does not support remove or update, only add");
                    return;
                }
                if (utils_1.Utils.missing(transaction.addIndex)) {
                    console.warn("ag-Grid: updateRowData for InfiniteRowModel requires add and addIndex to be set");
                    return;
                }
                if (this.infiniteCache) {
                    this.infiniteCache.insertItemsAtIndex(transaction.addIndex, transaction.add);
                }
            };
            InfiniteRowModel.prototype.isRowPresent = function(rowNode) {
                return false;
            };
            InfiniteRowModel.prototype.refreshCache = function() {
                if (this.infiniteCache) {
                    this.infiniteCache.refreshCache();
                }
            };
            InfiniteRowModel.prototype.purgeCache = function() {
                if (this.infiniteCache) {
                    this.infiniteCache.purgeCache();
                }
            };
            InfiniteRowModel.prototype.getVirtualRowCount = function() {
                if (this.infiniteCache) {
                    return this.infiniteCache.getVirtualRowCount();
                } else {
                    return null;
                }
            };
            InfiniteRowModel.prototype.isMaxRowFound = function() {
                if (this.infiniteCache) {
                    return this.infiniteCache.isMaxRowFound();
                }
            };
            InfiniteRowModel.prototype.setVirtualRowCount = function(rowCount, maxRowFound) {
                if (this.infiniteCache) {
                    this.infiniteCache.setVirtualRowCount(rowCount, maxRowFound);
                }
            };
            InfiniteRowModel.prototype.getBlockState = function() {
                if (this.rowNodeBlockLoader) {
                    return this.rowNodeBlockLoader.getBlockState();
                } else {
                    return null;
                }
            };
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], InfiniteRowModel.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("filterManager"), __metadata("design:type", filterManager_1.FilterManager) ], InfiniteRowModel.prototype, "filterManager", void 0);
            __decorate([ context_1.Autowired("sortController"), __metadata("design:type", sortController_1.SortController) ], InfiniteRowModel.prototype, "sortController", void 0);
            __decorate([ context_1.Autowired("selectionController"), __metadata("design:type", selectionController_1.SelectionController) ], InfiniteRowModel.prototype, "selectionController", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], InfiniteRowModel.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], InfiniteRowModel.prototype, "context", void 0);
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], InfiniteRowModel.prototype, "gridApi", void 0);
            __decorate([ context_1.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], InfiniteRowModel.prototype, "columnApi", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], InfiniteRowModel.prototype, "init", null);
            __decorate([ context_1.PreDestroy, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], InfiniteRowModel.prototype, "destroyDatasource", null);
            __decorate([ context_1.PreDestroy, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], InfiniteRowModel.prototype, "destroy", null);
            InfiniteRowModel = __decorate([ context_1.Bean("rowModel") ], InfiniteRowModel);
            return InfiniteRowModel;
        }(beanStub_1.BeanStub);
        exports.InfiniteRowModel = InfiniteRowModel;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        var __param = this && this.__param || function(paramIndex, decorator) {
            return function(target, key) {
                decorator(target, key, paramIndex);
            };
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var rowNodeBlock_1 = __webpack_require__(61);
        var logger_1 = __webpack_require__(12);
        var context_1 = __webpack_require__(0);
        var utils_1 = __webpack_require__(1);
        var RowNodeBlockLoader = function() {
            function RowNodeBlockLoader(maxConcurrentRequests) {
                this.activeBlockLoadsCount = 0;
                this.blocks = [];
                this.active = true;
                this.maxConcurrentRequests = maxConcurrentRequests;
            }
            RowNodeBlockLoader.prototype.setBeans = function(loggerFactory) {
                this.logger = loggerFactory.create("RowNodeBlockLoader");
            };
            RowNodeBlockLoader.prototype.addBlock = function(block) {
                this.blocks.push(block);
            };
            RowNodeBlockLoader.prototype.removeBlock = function(block) {
                utils_1._.removeFromArray(this.blocks, block);
            };
            RowNodeBlockLoader.prototype.destroy = function() {
                this.active = false;
            };
            RowNodeBlockLoader.prototype.loadComplete = function() {
                this.activeBlockLoadsCount--;
            };
            RowNodeBlockLoader.prototype.checkBlockToLoad = function() {
                if (!this.active) {
                    return;
                }
                this.printCacheStatus();
                if (this.activeBlockLoadsCount >= this.maxConcurrentRequests) {
                    this.logger.log("checkBlockToLoad: max loads exceeded");
                    return;
                }
                var blockToLoad = null;
                this.blocks.forEach(function(block) {
                    if (block.getState() === rowNodeBlock_1.RowNodeBlock.STATE_DIRTY) {
                        blockToLoad = block;
                    }
                });
                if (blockToLoad) {
                    blockToLoad.load();
                    this.activeBlockLoadsCount++;
                    this.logger.log("checkBlockToLoad: loading page " + blockToLoad.getBlockNumber());
                    this.printCacheStatus();
                } else {
                    this.logger.log("checkBlockToLoad: no pages to load");
                }
            };
            RowNodeBlockLoader.prototype.getBlockState = function() {
                var result = {};
                this.blocks.forEach(function(block) {
                    var nodeIdPrefix = block.getNodeIdPrefix();
                    var stateItem = {
                        blockNumber: block.getBlockNumber(),
                        startRow: block.getStartRow(),
                        endRow: block.getEndRow(),
                        pageStatus: block.getState()
                    };
                    if (utils_1._.exists(nodeIdPrefix)) {
                        result[nodeIdPrefix + block.getBlockNumber()] = stateItem;
                    } else {
                        result[block.getBlockNumber()] = stateItem;
                    }
                });
                return result;
            };
            RowNodeBlockLoader.prototype.printCacheStatus = function() {
                if (this.logger.isLogging()) {
                    this.logger.log("printCacheStatus: activePageLoadsCount = " + this.activeBlockLoadsCount + "," + (" blocks = " + JSON.stringify(this.getBlockState())));
                }
            };
            __decorate([ __param(0, context_1.Qualifier("loggerFactory")), __metadata("design:type", Function), __metadata("design:paramtypes", [ logger_1.LoggerFactory ]), __metadata("design:returntype", void 0) ], RowNodeBlockLoader.prototype, "setBeans", null);
            return RowNodeBlockLoader;
        }();
        exports.RowNodeBlockLoader = RowNodeBlockLoader;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var constants_1 = __webpack_require__(9);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var columnApi_1 = __webpack_require__(7);
        var columnController_1 = __webpack_require__(4);
        var filterManager_1 = __webpack_require__(18);
        var rowNode_1 = __webpack_require__(14);
        var eventService_1 = __webpack_require__(3);
        var events_1 = __webpack_require__(5);
        var context_1 = __webpack_require__(0);
        var selectionController_1 = __webpack_require__(17);
        var clientSideNodeManager_1 = __webpack_require__(88);
        var changedPath_1 = __webpack_require__(89);
        var valueService_1 = __webpack_require__(16);
        var valueCache_1 = __webpack_require__(33);
        var gridApi_1 = __webpack_require__(6);
        var RecursionType;
        (function(RecursionType) {
            RecursionType[RecursionType["Normal"] = 0] = "Normal";
            RecursionType[RecursionType["AfterFilter"] = 1] = "AfterFilter";
            RecursionType[RecursionType["AfterFilterAndSort"] = 2] = "AfterFilterAndSort";
            RecursionType[RecursionType["PivotNodes"] = 3] = "PivotNodes";
        })(RecursionType || (RecursionType = {}));
        var ClientSideRowModel = function() {
            function ClientSideRowModel() {}
            ClientSideRowModel.prototype.init = function() {
                var refreshEverythingFunc = this.refreshModel.bind(this, {
                    step: constants_1.Constants.STEP_EVERYTHING
                });
                this.eventService.addModalPriorityEventListener(events_1.Events.EVENT_COLUMN_EVERYTHING_CHANGED, refreshEverythingFunc);
                this.eventService.addModalPriorityEventListener(events_1.Events.EVENT_COLUMN_ROW_GROUP_CHANGED, refreshEverythingFunc);
                this.eventService.addModalPriorityEventListener(events_1.Events.EVENT_COLUMN_VALUE_CHANGED, this.onValueChanged.bind(this));
                this.eventService.addModalPriorityEventListener(events_1.Events.EVENT_COLUMN_PIVOT_CHANGED, this.refreshModel.bind(this, {
                    step: constants_1.Constants.STEP_PIVOT
                }));
                this.eventService.addModalPriorityEventListener(events_1.Events.EVENT_ROW_GROUP_OPENED, this.onRowGroupOpened.bind(this));
                this.eventService.addModalPriorityEventListener(events_1.Events.EVENT_FILTER_CHANGED, this.onFilterChanged.bind(this));
                this.eventService.addModalPriorityEventListener(events_1.Events.EVENT_SORT_CHANGED, this.onSortChanged.bind(this));
                this.eventService.addModalPriorityEventListener(events_1.Events.EVENT_COLUMN_PIVOT_MODE_CHANGED, refreshEverythingFunc);
                var refreshMapFunc = this.refreshModel.bind(this, {
                    step: constants_1.Constants.STEP_MAP,
                    keepRenderedRows: true,
                    animate: true
                });
                this.gridOptionsWrapper.addEventListener(gridOptionsWrapper_1.GridOptionsWrapper.PROP_GROUP_REMOVE_SINGLE_CHILDREN, refreshMapFunc);
                this.gridOptionsWrapper.addEventListener(gridOptionsWrapper_1.GridOptionsWrapper.PROP_GROUP_REMOVE_LOWEST_SINGLE_CHILDREN, refreshMapFunc);
                this.rootNode = new rowNode_1.RowNode();
                this.nodeManager = new clientSideNodeManager_1.ClientSideNodeManager(this.rootNode, this.gridOptionsWrapper, this.context, this.eventService, this.columnController);
                this.context.wireBean(this.rootNode);
            };
            ClientSideRowModel.prototype.ensureRowAtPixel = function(rowNode, pixel) {
                var indexAtPixelNow = this.getRowIndexAtPixel(pixel);
                var rowNodeAtPixelNow = this.getRow(indexAtPixelNow);
                if (rowNodeAtPixelNow === rowNode) {
                    return false;
                }
                utils_1.Utils.removeFromArray(this.rootNode.allLeafChildren, rowNode);
                utils_1.Utils.insertIntoArray(this.rootNode.allLeafChildren, rowNode, indexAtPixelNow);
                this.refreshModel({
                    step: constants_1.Constants.STEP_EVERYTHING,
                    keepRenderedRows: true,
                    animate: true,
                    keepEditingRows: true
                });
                return true;
            };
            ClientSideRowModel.prototype.isLastRowFound = function() {
                return true;
            };
            ClientSideRowModel.prototype.getRowCount = function() {
                if (this.rowsToDisplay) {
                    return this.rowsToDisplay.length;
                } else {
                    return 0;
                }
            };
            ClientSideRowModel.prototype.getRowBounds = function(index) {
                if (utils_1.Utils.missing(this.rowsToDisplay)) {
                    return null;
                }
                var rowNode = this.rowsToDisplay[index];
                if (rowNode) {
                    return {
                        rowTop: rowNode.rowTop,
                        rowHeight: rowNode.rowHeight
                    };
                } else {
                    return null;
                }
            };
            ClientSideRowModel.prototype.onRowGroupOpened = function() {
                var animate = this.gridOptionsWrapper.isAnimateRows();
                this.refreshModel({
                    step: constants_1.Constants.STEP_MAP,
                    keepRenderedRows: true,
                    animate: animate
                });
            };
            ClientSideRowModel.prototype.onFilterChanged = function() {
                var animate = this.gridOptionsWrapper.isAnimateRows();
                this.refreshModel({
                    step: constants_1.Constants.STEP_FILTER,
                    keepRenderedRows: true,
                    animate: animate
                });
            };
            ClientSideRowModel.prototype.onSortChanged = function() {
                if (this.gridOptionsWrapper.isEnableServerSideSorting()) {
                    return;
                }
                var animate = this.gridOptionsWrapper.isAnimateRows();
                this.refreshModel({
                    step: constants_1.Constants.STEP_SORT,
                    keepRenderedRows: true,
                    animate: animate,
                    keepEditingRows: true
                });
            };
            ClientSideRowModel.prototype.getType = function() {
                return constants_1.Constants.ROW_MODEL_TYPE_CLIENT_SIDE;
            };
            ClientSideRowModel.prototype.onValueChanged = function() {
                if (this.columnController.isPivotActive()) {
                    this.refreshModel({
                        step: constants_1.Constants.STEP_PIVOT
                    });
                } else {
                    this.refreshModel({
                        step: constants_1.Constants.STEP_AGGREGATE
                    });
                }
            };
            ClientSideRowModel.prototype.createChangePath = function(rowNodeTransactions) {
                var valueColumns = this.columnController.getValueColumns();
                var noValueColumns = utils_1.Utils.missingOrEmpty(valueColumns);
                var noTransactions = utils_1.Utils.missingOrEmpty(rowNodeTransactions);
                var changedPath = new changedPath_1.ChangedPath(false);
                if (noValueColumns || noTransactions) {
                    changedPath.setInactive();
                }
                return changedPath;
            };
            ClientSideRowModel.prototype.refreshModel = function(params) {
                var _this = this;
                var changedPath = this.createChangePath(params.rowNodeTransactions);
                switch (params.step) {
                  case constants_1.Constants.STEP_EVERYTHING:
                    this.doRowGrouping(params.groupState, params.rowNodeTransactions, params.rowNodeOrder, changedPath);

                  case constants_1.Constants.STEP_FILTER:
                    this.doFilter();

                  case constants_1.Constants.STEP_PIVOT:
                    this.doPivot(changedPath);

                  case constants_1.Constants.STEP_AGGREGATE:
                    this.doAggregate(changedPath);

                  case constants_1.Constants.STEP_SORT:
                    this.doSort();

                  case constants_1.Constants.STEP_MAP:
                    this.doRowsToDisplay();
                }
                var event = {
                    type: events_1.Events.EVENT_MODEL_UPDATED,
                    api: this.gridApi,
                    columnApi: this.columnApi,
                    animate: params.animate,
                    keepRenderedRows: params.keepRenderedRows,
                    newData: params.newData,
                    newPage: false
                };
                this.eventService.dispatchEvent(event);
                if (this.$scope) {
                    setTimeout(function() {
                        _this.$scope.$apply();
                    }, 0);
                }
            };
            ClientSideRowModel.prototype.isEmpty = function() {
                var rowsMissing;
                var doingLegacyTreeData = utils_1.Utils.exists(this.gridOptionsWrapper.getNodeChildDetailsFunc());
                if (doingLegacyTreeData) {
                    rowsMissing = utils_1.Utils.missing(this.rootNode.childrenAfterGroup) || this.rootNode.childrenAfterGroup.length === 0;
                } else {
                    rowsMissing = utils_1.Utils.missing(this.rootNode.allLeafChildren) || this.rootNode.allLeafChildren.length === 0;
                }
                var empty = utils_1.Utils.missing(this.rootNode) || rowsMissing || !this.columnController.isReady();
                return empty;
            };
            ClientSideRowModel.prototype.isRowsToRender = function() {
                return utils_1.Utils.exists(this.rowsToDisplay) && this.rowsToDisplay.length > 0;
            };
            ClientSideRowModel.prototype.getNodesInRangeForSelection = function(firstInRange, lastInRange) {
                var firstRowHit = !lastInRange;
                var lastRowHit = false;
                var lastRow;
                var result = [];
                var groupsSelectChildren = this.gridOptionsWrapper.isGroupSelectsChildren();
                this.forEachNodeAfterFilterAndSort(function(rowNode) {
                    var lookingForLastRow = firstRowHit && !lastRowHit;
                    if (!firstRowHit) {
                        if (rowNode === lastInRange || rowNode === firstInRange) {
                            firstRowHit = true;
                        }
                    }
                    var skipThisGroupNode = rowNode.group && groupsSelectChildren;
                    if (!skipThisGroupNode) {
                        var inRange = firstRowHit && !lastRowHit;
                        var childOfLastRow = rowNode.isParentOfNode(lastRow);
                        if (inRange || childOfLastRow) {
                            result.push(rowNode);
                        }
                    }
                    if (lookingForLastRow) {
                        if (rowNode === lastInRange || rowNode === firstInRange) {
                            lastRowHit = true;
                            if (rowNode === lastInRange) {
                                lastRow = lastInRange;
                            } else {
                                lastRow = firstInRange;
                            }
                        }
                    }
                });
                return result;
            };
            ClientSideRowModel.prototype.setDatasource = function(datasource) {
                console.error("ag-Grid: should never call setDatasource on clientSideRowController");
            };
            ClientSideRowModel.prototype.getTopLevelNodes = function() {
                return this.rootNode ? this.rootNode.childrenAfterGroup : null;
            };
            ClientSideRowModel.prototype.getRootNode = function() {
                return this.rootNode;
            };
            ClientSideRowModel.prototype.getRow = function(index) {
                return this.rowsToDisplay[index];
            };
            ClientSideRowModel.prototype.isRowPresent = function(rowNode) {
                return this.rowsToDisplay.indexOf(rowNode) >= 0;
            };
            ClientSideRowModel.prototype.getVirtualRowCount = function() {
                console.warn("ag-Grid: rowModel.getVirtualRowCount() is not longer a function, use rowModel.getRowCount() instead");
                return this.getPageLastRow();
            };
            ClientSideRowModel.prototype.getPageFirstRow = function() {
                return 0;
            };
            ClientSideRowModel.prototype.getPageLastRow = function() {
                if (this.rowsToDisplay) {
                    return this.rowsToDisplay.length - 1;
                } else {
                    return 0;
                }
            };
            ClientSideRowModel.prototype.getRowIndexAtPixel = function(pixelToMatch) {
                if (this.isEmpty()) {
                    return -1;
                }
                var bottomPointer = 0;
                var topPointer = this.rowsToDisplay.length - 1;
                if (pixelToMatch <= 0) {
                    return 0;
                }
                var lastNode = this.rowsToDisplay[this.rowsToDisplay.length - 1];
                if (lastNode.rowTop <= pixelToMatch) {
                    return this.rowsToDisplay.length - 1;
                }
                while (true) {
                    var midPointer = Math.floor((bottomPointer + topPointer) / 2);
                    var currentRowNode = this.rowsToDisplay[midPointer];
                    if (this.isRowInPixel(currentRowNode, pixelToMatch)) {
                        return midPointer;
                    } else if (currentRowNode.rowTop < pixelToMatch) {
                        bottomPointer = midPointer + 1;
                    } else if (currentRowNode.rowTop > pixelToMatch) {
                        topPointer = midPointer - 1;
                    }
                }
            };
            ClientSideRowModel.prototype.isRowInPixel = function(rowNode, pixelToMatch) {
                var topPixel = rowNode.rowTop;
                var bottomPixel = rowNode.rowTop + rowNode.rowHeight;
                var pixelInRow = topPixel <= pixelToMatch && bottomPixel > pixelToMatch;
                return pixelInRow;
            };
            ClientSideRowModel.prototype.getCurrentPageHeight = function() {
                if (this.rowsToDisplay && this.rowsToDisplay.length > 0) {
                    var lastRow = this.rowsToDisplay[this.rowsToDisplay.length - 1];
                    var lastPixel = lastRow.rowTop + lastRow.rowHeight;
                    return lastPixel;
                } else {
                    return 0;
                }
            };
            ClientSideRowModel.prototype.forEachLeafNode = function(callback) {
                if (this.rootNode.allLeafChildren) {
                    this.rootNode.allLeafChildren.forEach(function(rowNode, index) {
                        return callback(rowNode, index);
                    });
                }
            };
            ClientSideRowModel.prototype.forEachNode = function(callback) {
                this.recursivelyWalkNodesAndCallback(this.rootNode.childrenAfterGroup, callback, RecursionType.Normal, 0);
            };
            ClientSideRowModel.prototype.forEachNodeAfterFilter = function(callback) {
                this.recursivelyWalkNodesAndCallback(this.rootNode.childrenAfterFilter, callback, RecursionType.AfterFilter, 0);
            };
            ClientSideRowModel.prototype.forEachNodeAfterFilterAndSort = function(callback) {
                this.recursivelyWalkNodesAndCallback(this.rootNode.childrenAfterSort, callback, RecursionType.AfterFilterAndSort, 0);
            };
            ClientSideRowModel.prototype.forEachPivotNode = function(callback) {
                this.recursivelyWalkNodesAndCallback([ this.rootNode ], callback, RecursionType.PivotNodes, 0);
            };
            ClientSideRowModel.prototype.recursivelyWalkNodesAndCallback = function(nodes, callback, recursionType, index) {
                if (nodes) {
                    for (var i = 0; i < nodes.length; i++) {
                        var node = nodes[i];
                        callback(node, index++);
                        if (node.hasChildren()) {
                            var nodeChildren = void 0;
                            switch (recursionType) {
                              case RecursionType.Normal:
                                nodeChildren = node.childrenAfterGroup;
                                break;

                              case RecursionType.AfterFilter:
                                nodeChildren = node.childrenAfterFilter;
                                break;

                              case RecursionType.AfterFilterAndSort:
                                nodeChildren = node.childrenAfterSort;
                                break;

                              case RecursionType.PivotNodes:
                                nodeChildren = !node.leafGroup ? node.childrenAfterSort : null;
                                break;
                            }
                            if (nodeChildren) {
                                index = this.recursivelyWalkNodesAndCallback(nodeChildren, callback, recursionType, index);
                            }
                        }
                    }
                }
                return index;
            };
            ClientSideRowModel.prototype.doAggregate = function(changedPath) {
                if (this.aggregationStage) {
                    this.aggregationStage.execute({
                        rowNode: this.rootNode,
                        changedPath: changedPath
                    });
                }
            };
            ClientSideRowModel.prototype.expandOrCollapseAll = function(expand) {
                var usingTreeData = this.gridOptionsWrapper.isTreeData();
                if (this.rootNode) {
                    recursiveExpandOrCollapse(this.rootNode.childrenAfterGroup);
                }
                function recursiveExpandOrCollapse(rowNodes) {
                    if (!rowNodes) {
                        return;
                    }
                    rowNodes.forEach(function(rowNode) {
                        var shouldExpandOrCollapse = usingTreeData ? utils_1.Utils.exists(rowNode.childrenAfterGroup) : rowNode.group;
                        if (shouldExpandOrCollapse) {
                            rowNode.expanded = expand;
                            recursiveExpandOrCollapse(rowNode.childrenAfterGroup);
                        }
                    });
                }
                this.refreshModel({
                    step: constants_1.Constants.STEP_MAP
                });
            };
            ClientSideRowModel.prototype.doSort = function() {
                this.sortStage.execute({
                    rowNode: this.rootNode
                });
            };
            ClientSideRowModel.prototype.doRowGrouping = function(groupState, rowNodeTransactions, rowNodeOrder, changedPath) {
                var _this = this;
                var doingLegacyTreeData = utils_1.Utils.exists(this.gridOptionsWrapper.getNodeChildDetailsFunc());
                if (doingLegacyTreeData) {
                    return;
                }
                if (this.groupStage) {
                    if (utils_1.Utils.exists(rowNodeTransactions)) {
                        rowNodeTransactions.forEach(function(tran) {
                            _this.groupStage.execute({
                                rowNode: _this.rootNode,
                                rowNodeTransaction: tran,
                                rowNodeOrder: rowNodeOrder,
                                changedPath: changedPath
                            });
                        });
                    } else {
                        this.selectionController.removeGroupsFromSelection();
                        this.groupStage.execute({
                            rowNode: this.rootNode,
                            changedPath: changedPath
                        });
                        this.restoreGroupState(groupState);
                    }
                    if (this.gridOptionsWrapper.isGroupSelectsChildren()) {
                        this.selectionController.updateGroupsFromChildrenSelections();
                    }
                } else {
                    this.rootNode.childrenAfterGroup = this.rootNode.allLeafChildren;
                }
            };
            ClientSideRowModel.prototype.restoreGroupState = function(groupState) {
                if (!groupState) {
                    return;
                }
                utils_1.Utils.traverseNodesWithKey(this.rootNode.childrenAfterGroup, function(node, key) {
                    if (typeof groupState[key] === "boolean") {
                        node.expanded = groupState[key];
                    }
                });
            };
            ClientSideRowModel.prototype.doFilter = function() {
                this.filterStage.execute({
                    rowNode: this.rootNode
                });
            };
            ClientSideRowModel.prototype.doPivot = function(changedPath) {
                if (this.pivotStage) {
                    this.pivotStage.execute({
                        rowNode: this.rootNode,
                        changedPath: changedPath
                    });
                }
            };
            ClientSideRowModel.prototype.getGroupState = function() {
                if (!this.rootNode.childrenAfterGroup || !this.gridOptionsWrapper.isRememberGroupStateWhenNewData()) {
                    return null;
                }
                var result = {};
                utils_1.Utils.traverseNodesWithKey(this.rootNode.childrenAfterGroup, function(node, key) {
                    return result[key] = node.expanded;
                });
                return result;
            };
            ClientSideRowModel.prototype.getCopyOfNodesMap = function() {
                return this.nodeManager.getCopyOfNodesMap();
            };
            ClientSideRowModel.prototype.getRowNode = function(id) {
                return this.nodeManager.getRowNode(id);
            };
            ClientSideRowModel.prototype.setRowData = function(rowData) {
                var groupState = this.getGroupState();
                this.nodeManager.setRowData(rowData);
                var rowDataChangedEvent = {
                    type: events_1.Events.EVENT_ROW_DATA_CHANGED,
                    api: this.gridApi,
                    columnApi: this.columnApi
                };
                this.eventService.dispatchEvent(rowDataChangedEvent);
                this.refreshModel({
                    step: constants_1.Constants.STEP_EVERYTHING,
                    groupState: groupState,
                    newData: true
                });
            };
            ClientSideRowModel.prototype.batchUpdateRowData = function(rowDataTransaction, callback) {
                var _this = this;
                if (!this.rowDataTransactionBatch) {
                    this.rowDataTransactionBatch = [];
                    var waitMillis = this.gridOptionsWrapper.getBatchUpdateWaitMillis();
                    setTimeout(function() {
                        _this.executeBatchUpdateRowData();
                        _this.rowDataTransactionBatch = null;
                    }, waitMillis);
                }
                this.rowDataTransactionBatch.push({
                    rowDataTransaction: rowDataTransaction,
                    callback: callback
                });
            };
            ClientSideRowModel.prototype.executeBatchUpdateRowData = function() {
                var _this = this;
                this.valueCache.onDataChanged();
                var callbackFuncsBound = [];
                var rowNodeTrans = [];
                this.rowDataTransactionBatch.forEach(function(tranItem) {
                    var rowNodeTran = _this.nodeManager.updateRowData(tranItem.rowDataTransaction, null);
                    rowNodeTrans.push(rowNodeTran);
                    if (tranItem.callback) {
                        callbackFuncsBound.push(tranItem.callback.bind(rowNodeTran));
                    }
                });
                this.commonUpdateRowData(rowNodeTrans);
                if (callbackFuncsBound.length > 0) {
                    setTimeout(function() {
                        callbackFuncsBound.forEach(function(func) {
                            return func();
                        });
                    }, 0);
                }
            };
            ClientSideRowModel.prototype.updateRowData = function(rowDataTran, rowNodeOrder) {
                this.valueCache.onDataChanged();
                var rowNodeTran = this.nodeManager.updateRowData(rowDataTran, rowNodeOrder);
                this.commonUpdateRowData([ rowNodeTran ], rowNodeOrder);
                return rowNodeTran;
            };
            ClientSideRowModel.prototype.commonUpdateRowData = function(rowNodeTrans, rowNodeOrder) {
                this.refreshModel({
                    step: constants_1.Constants.STEP_EVERYTHING,
                    rowNodeTransactions: rowNodeTrans,
                    rowNodeOrder: rowNodeOrder,
                    keepRenderedRows: true,
                    animate: true,
                    keepEditingRows: true
                });
                var event = {
                    type: events_1.Events.EVENT_ROW_DATA_UPDATED,
                    api: this.gridApi,
                    columnApi: this.columnApi
                };
                this.eventService.dispatchEvent(event);
            };
            ClientSideRowModel.prototype.doRowsToDisplay = function() {
                this.rowsToDisplay = this.flattenStage.execute({
                    rowNode: this.rootNode
                });
            };
            ClientSideRowModel.prototype.onRowHeightChanged = function() {
                this.refreshModel({
                    step: constants_1.Constants.STEP_MAP,
                    keepRenderedRows: true,
                    keepEditingRows: true
                });
            };
            ClientSideRowModel.prototype.resetRowHeights = function() {
                this.forEachNode(function(rowNode) {
                    return rowNode.setRowHeight(null);
                });
                this.onRowHeightChanged();
            };
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], ClientSideRowModel.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], ClientSideRowModel.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("filterManager"), __metadata("design:type", filterManager_1.FilterManager) ], ClientSideRowModel.prototype, "filterManager", void 0);
            __decorate([ context_1.Autowired("$scope"), __metadata("design:type", Object) ], ClientSideRowModel.prototype, "$scope", void 0);
            __decorate([ context_1.Autowired("selectionController"), __metadata("design:type", selectionController_1.SelectionController) ], ClientSideRowModel.prototype, "selectionController", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], ClientSideRowModel.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], ClientSideRowModel.prototype, "context", void 0);
            __decorate([ context_1.Autowired("valueService"), __metadata("design:type", valueService_1.ValueService) ], ClientSideRowModel.prototype, "valueService", void 0);
            __decorate([ context_1.Autowired("valueCache"), __metadata("design:type", valueCache_1.ValueCache) ], ClientSideRowModel.prototype, "valueCache", void 0);
            __decorate([ context_1.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], ClientSideRowModel.prototype, "columnApi", void 0);
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], ClientSideRowModel.prototype, "gridApi", void 0);
            __decorate([ context_1.Autowired("filterStage"), __metadata("design:type", Object) ], ClientSideRowModel.prototype, "filterStage", void 0);
            __decorate([ context_1.Autowired("sortStage"), __metadata("design:type", Object) ], ClientSideRowModel.prototype, "sortStage", void 0);
            __decorate([ context_1.Autowired("flattenStage"), __metadata("design:type", Object) ], ClientSideRowModel.prototype, "flattenStage", void 0);
            __decorate([ context_1.Optional("groupStage"), __metadata("design:type", Object) ], ClientSideRowModel.prototype, "groupStage", void 0);
            __decorate([ context_1.Optional("aggregationStage"), __metadata("design:type", Object) ], ClientSideRowModel.prototype, "aggregationStage", void 0);
            __decorate([ context_1.Optional("pivotStage"), __metadata("design:type", Object) ], ClientSideRowModel.prototype, "pivotStage", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], ClientSideRowModel.prototype, "init", null);
            ClientSideRowModel = __decorate([ context_1.Bean("rowModel") ], ClientSideRowModel);
            return ClientSideRowModel;
        }();
        exports.ClientSideRowModel = ClientSideRowModel;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var BaseFrameworkFactory = function() {
            function BaseFrameworkFactory() {}
            BaseFrameworkFactory.prototype.dateComponent = function(gridOptions) {
                return gridOptions.dateComponent;
            };
            BaseFrameworkFactory.prototype.colDefFloatingCellRenderer = function(colDef) {
                return colDef.pinnedRowCellRenderer;
            };
            BaseFrameworkFactory.prototype.colDefCellRenderer = function(colDef) {
                return colDef.cellRenderer;
            };
            BaseFrameworkFactory.prototype.colDefCellEditor = function(colDef) {
                return colDef.cellEditor;
            };
            BaseFrameworkFactory.prototype.colDefFilter = function(colDef) {
                return colDef.filter;
            };
            BaseFrameworkFactory.prototype.gridOptionsFullWidthCellRenderer = function(gridOptions) {
                return gridOptions.fullWidthCellRenderer;
            };
            BaseFrameworkFactory.prototype.gridOptionsGroupRowRenderer = function(gridOptions) {
                return gridOptions.groupRowRenderer;
            };
            BaseFrameworkFactory.prototype.gridOptionsGroupRowInnerRenderer = function(gridOptions) {
                return gridOptions.groupRowInnerRenderer;
            };
            BaseFrameworkFactory.prototype.setTimeout = function(action, timeout) {
                setTimeout(action, timeout);
            };
            return BaseFrameworkFactory;
        }();
        exports.BaseFrameworkFactory = BaseFrameworkFactory;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var LINE_SEPARATOR = "\r\n";
        var XmlFactory = function() {
            function XmlFactory() {}
            XmlFactory.prototype.createXml = function(xmlElement, booleanTransformer) {
                var _this = this;
                var props = "";
                if (xmlElement.properties) {
                    if (xmlElement.properties.prefixedAttributes) {
                        xmlElement.properties.prefixedAttributes.forEach(function(prefixedSet) {
                            Object.keys(prefixedSet.map).forEach(function(key) {
                                props += _this.returnAttributeIfPopulated(prefixedSet.prefix + key, prefixedSet.map[key], booleanTransformer);
                            });
                        });
                    }
                    if (xmlElement.properties.rawMap) {
                        Object.keys(xmlElement.properties.rawMap).forEach(function(key) {
                            props += _this.returnAttributeIfPopulated(key, xmlElement.properties.rawMap[key], booleanTransformer);
                        });
                    }
                }
                var result = "<" + xmlElement.name + props;
                if (!xmlElement.children && xmlElement.textNode == null) {
                    return result + "/>" + LINE_SEPARATOR;
                }
                if (xmlElement.textNode != null) {
                    return result + ">" + xmlElement.textNode + "</" + xmlElement.name + ">" + LINE_SEPARATOR;
                }
                result += ">" + LINE_SEPARATOR;
                xmlElement.children.forEach(function(it) {
                    result += _this.createXml(it, booleanTransformer);
                });
                return result + "</" + xmlElement.name + ">" + LINE_SEPARATOR;
            };
            XmlFactory.prototype.returnAttributeIfPopulated = function(key, value, booleanTransformer) {
                if (!value) {
                    return "";
                }
                var xmlValue = value;
                if (typeof value === "boolean") {
                    if (booleanTransformer) {
                        xmlValue = booleanTransformer(value);
                    }
                }
                xmlValue = '"' + xmlValue + '"';
                return " " + key + "=" + xmlValue;
            };
            XmlFactory = __decorate([ context_1.Bean("xmlFactory") ], XmlFactory);
            return XmlFactory;
        }();
        exports.XmlFactory = XmlFactory;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        (function(global) {
            Object.defineProperty(exports, "__esModule", {
                value: true
            });
            var globalObj = typeof global === "undefined" ? {} : global;
            globalObj.HTMLElement = typeof HTMLElement === "undefined" ? {} : HTMLElement;
            globalObj.HTMLButtonElement = typeof HTMLButtonElement === "undefined" ? {} : HTMLButtonElement;
            globalObj.HTMLSelectElement = typeof HTMLSelectElement === "undefined" ? {} : HTMLSelectElement;
            globalObj.HTMLInputElement = typeof HTMLInputElement === "undefined" ? {} : HTMLInputElement;
            globalObj.Node = typeof Node === "undefined" ? {} : Node;
            globalObj.MouseEvent = typeof MouseEvent === "undefined" ? {} : MouseEvent;
            var balancedColumnTreeBuilder_1 = __webpack_require__(38);
            exports.BalancedColumnTreeBuilder = balancedColumnTreeBuilder_1.BalancedColumnTreeBuilder;
            var columnController_1 = __webpack_require__(4);
            exports.ColumnController = columnController_1.ColumnController;
            var columnKeyCreator_1 = __webpack_require__(107);
            exports.ColumnKeyCreator = columnKeyCreator_1.ColumnKeyCreator;
            var columnUtils_1 = __webpack_require__(31);
            exports.ColumnUtils = columnUtils_1.ColumnUtils;
            var displayedGroupCreator_1 = __webpack_require__(48);
            exports.DisplayedGroupCreator = displayedGroupCreator_1.DisplayedGroupCreator;
            var groupInstanceIdCreator_1 = __webpack_require__(83);
            exports.GroupInstanceIdCreator = groupInstanceIdCreator_1.GroupInstanceIdCreator;
            var componentUtil_1 = __webpack_require__(62);
            exports.ComponentUtil = componentUtil_1.ComponentUtil;
            var colDefUtil_1 = __webpack_require__(106);
            exports.ColDefUtil = colDefUtil_1.ColDefUtil;
            var componentProvider_1 = __webpack_require__(66);
            exports.ComponentProvider = componentProvider_1.ComponentProvider;
            var agGridNg1_1 = __webpack_require__(135);
            exports.initialiseAgGridWithAngular1 = agGridNg1_1.initialiseAgGridWithAngular1;
            var agGridWebComponent_1 = __webpack_require__(141);
            exports.initialiseAgGridWithWebComponents = agGridWebComponent_1.initialiseAgGridWithWebComponents;
            var beanStub_1 = __webpack_require__(13);
            exports.BeanStub = beanStub_1.BeanStub;
            var context_1 = __webpack_require__(0);
            exports.Context = context_1.Context;
            exports.Autowired = context_1.Autowired;
            exports.PostConstruct = context_1.PostConstruct;
            exports.PreConstruct = context_1.PreConstruct;
            exports.Optional = context_1.Optional;
            exports.Bean = context_1.Bean;
            exports.Qualifier = context_1.Qualifier;
            exports.PreDestroy = context_1.PreDestroy;
            var componentAnnotations_1 = __webpack_require__(11);
            exports.QuerySelector = componentAnnotations_1.QuerySelector;
            exports.Listener = componentAnnotations_1.Listener;
            exports.RefSelector = componentAnnotations_1.RefSelector;
            var dragAndDropService_1 = __webpack_require__(15);
            exports.DragAndDropService = dragAndDropService_1.DragAndDropService;
            exports.DragSourceType = dragAndDropService_1.DragSourceType;
            exports.HDirection = dragAndDropService_1.HDirection;
            exports.VDirection = dragAndDropService_1.VDirection;
            var dragService_1 = __webpack_require__(40);
            exports.DragService = dragService_1.DragService;
            var column_1 = __webpack_require__(10);
            exports.Column = column_1.Column;
            var columnGroup_1 = __webpack_require__(26);
            exports.ColumnGroup = columnGroup_1.ColumnGroup;
            var gridCell_1 = __webpack_require__(23);
            exports.GridCell = gridCell_1.GridCell;
            var gridRow_1 = __webpack_require__(64);
            exports.GridRow = gridRow_1.GridRow;
            var originalColumnGroup_1 = __webpack_require__(32);
            exports.OriginalColumnGroup = originalColumnGroup_1.OriginalColumnGroup;
            var rowNode_1 = __webpack_require__(14);
            exports.RowNode = rowNode_1.RowNode;
            var baseFilter_1 = __webpack_require__(51);
            exports.BaseFilter = baseFilter_1.BaseFilter;
            var dateFilter_1 = __webpack_require__(68);
            exports.DateFilter = dateFilter_1.DateFilter;
            var filterManager_1 = __webpack_require__(18);
            exports.FilterManager = filterManager_1.FilterManager;
            var numberFilter_1 = __webpack_require__(96);
            exports.NumberFilter = numberFilter_1.NumberFilter;
            var textFilter_1 = __webpack_require__(95);
            exports.TextFilter = textFilter_1.TextFilter;
            var gridPanel_1 = __webpack_require__(78);
            exports.GridPanel = gridPanel_1.GridPanel;
            var scrollVisibleService_1 = __webpack_require__(36);
            exports.ScrollVisibleService = scrollVisibleService_1.ScrollVisibleService;
            var mouseEventService_1 = __webpack_require__(44);
            exports.MouseEventService = mouseEventService_1.MouseEventService;
            var bodyDropPivotTarget_1 = __webpack_require__(103);
            exports.BodyDropPivotTarget = bodyDropPivotTarget_1.BodyDropPivotTarget;
            var bodyDropTarget_1 = __webpack_require__(101);
            exports.BodyDropTarget = bodyDropTarget_1.BodyDropTarget;
            var cssClassApplier_1 = __webpack_require__(81);
            exports.CssClassApplier = cssClassApplier_1.CssClassApplier;
            var headerContainer_1 = __webpack_require__(98);
            exports.HeaderContainer = headerContainer_1.HeaderContainer;
            var headerRootComp_1 = __webpack_require__(80);
            exports.HeaderRootComp = headerRootComp_1.HeaderRootComp;
            var headerRowComp_1 = __webpack_require__(99);
            exports.HeaderRowComp = headerRowComp_1.HeaderRowComp;
            var horizontalResizeService_1 = __webpack_require__(59);
            exports.HorizontalResizeService = horizontalResizeService_1.HorizontalResizeService;
            var moveColumnController_1 = __webpack_require__(102);
            exports.MoveColumnController = moveColumnController_1.MoveColumnController;
            var standardMenu_1 = __webpack_require__(108);
            exports.StandardMenuFactory = standardMenu_1.StandardMenuFactory;
            var tabbedLayout_1 = __webpack_require__(142);
            exports.TabbedLayout = tabbedLayout_1.TabbedLayout;
            var verticalStack_1 = __webpack_require__(143);
            exports.VerticalStack = verticalStack_1.VerticalStack;
            var simpleHttpRequest_1 = __webpack_require__(144);
            exports.simpleHttpRequest = simpleHttpRequest_1.simpleHttpRequest;
            var largeTextCellEditor_1 = __webpack_require__(94);
            exports.LargeTextCellEditor = largeTextCellEditor_1.LargeTextCellEditor;
            var popupEditorWrapper_1 = __webpack_require__(69);
            exports.PopupEditorWrapper = popupEditorWrapper_1.PopupEditorWrapper;
            var popupSelectCellEditor_1 = __webpack_require__(93);
            exports.PopupSelectCellEditor = popupSelectCellEditor_1.PopupSelectCellEditor;
            var popupTextCellEditor_1 = __webpack_require__(92);
            exports.PopupTextCellEditor = popupTextCellEditor_1.PopupTextCellEditor;
            var selectCellEditor_1 = __webpack_require__(75);
            exports.SelectCellEditor = selectCellEditor_1.SelectCellEditor;
            var textCellEditor_1 = __webpack_require__(67);
            exports.TextCellEditor = textCellEditor_1.TextCellEditor;
            var animateShowChangeCellRenderer_1 = __webpack_require__(71);
            exports.AnimateShowChangeCellRenderer = animateShowChangeCellRenderer_1.AnimateShowChangeCellRenderer;
            var animateSlideCellRenderer_1 = __webpack_require__(70);
            exports.AnimateSlideCellRenderer = animateSlideCellRenderer_1.AnimateSlideCellRenderer;
            var groupCellRenderer_1 = __webpack_require__(72);
            exports.GroupCellRenderer = groupCellRenderer_1.GroupCellRenderer;
            var setLeftFeature_1 = __webpack_require__(52);
            exports.SetLeftFeature = setLeftFeature_1.SetLeftFeature;
            var autoWidthCalculator_1 = __webpack_require__(39);
            exports.AutoWidthCalculator = autoWidthCalculator_1.AutoWidthCalculator;
            var cellEditorFactory_1 = __webpack_require__(54);
            exports.CellEditorFactory = cellEditorFactory_1.CellEditorFactory;
            var cellRendererFactory_1 = __webpack_require__(55);
            exports.CellRendererFactory = cellRendererFactory_1.CellRendererFactory;
            var cellRendererService_1 = __webpack_require__(56);
            exports.CellRendererService = cellRendererService_1.CellRendererService;
            var checkboxSelectionComponent_1 = __webpack_require__(65);
            exports.CheckboxSelectionComponent = checkboxSelectionComponent_1.CheckboxSelectionComponent;
            var cellComp_1 = __webpack_require__(34);
            exports.CellComp = cellComp_1.CellComp;
            var rowComp_1 = __webpack_require__(50);
            exports.RowComp = rowComp_1.RowComp;
            var rowRenderer_1 = __webpack_require__(20);
            exports.RowRenderer = rowRenderer_1.RowRenderer;
            var valueFormatterService_1 = __webpack_require__(43);
            exports.ValueFormatterService = valueFormatterService_1.ValueFormatterService;
            var filterStage_1 = __webpack_require__(109);
            exports.FilterStage = filterStage_1.FilterStage;
            var flattenStage_1 = __webpack_require__(113);
            exports.FlattenStage = flattenStage_1.FlattenStage;
            var sortStage_1 = __webpack_require__(111);
            exports.SortStage = sortStage_1.SortStage;
            var pinnedRowModel_1 = __webpack_require__(30);
            exports.PinnedRowModel = pinnedRowModel_1.PinnedRowModel;
            var clientSideRowModel_1 = __webpack_require__(116);
            exports.ClientSideRowModel = clientSideRowModel_1.ClientSideRowModel;
            var changedPath_1 = __webpack_require__(89);
            exports.ChangedPath = changedPath_1.ChangedPath;
            var clientSideNodeManager_1 = __webpack_require__(88);
            exports.ClientSideNodeManager = clientSideNodeManager_1.ClientSideNodeManager;
            var infiniteRowModel_1 = __webpack_require__(114);
            exports.InfiniteRowModel = infiniteRowModel_1.InfiniteRowModel;
            var rowNodeBlock_1 = __webpack_require__(61);
            exports.RowNodeBlock = rowNodeBlock_1.RowNodeBlock;
            var rowNodeBlockLoader_1 = __webpack_require__(115);
            exports.RowNodeBlockLoader = rowNodeBlockLoader_1.RowNodeBlockLoader;
            var rowNodeCache_1 = __webpack_require__(87);
            exports.RowNodeCache = rowNodeCache_1.RowNodeCache;
            var stylingService_1 = __webpack_require__(73);
            exports.StylingService = stylingService_1.StylingService;
            var agCheckbox_1 = __webpack_require__(60);
            exports.AgCheckbox = agCheckbox_1.AgCheckbox;
            var component_1 = __webpack_require__(8);
            exports.Component = component_1.Component;
            var popupService_1 = __webpack_require__(35);
            exports.PopupService = popupService_1.PopupService;
            var touchListener_1 = __webpack_require__(46);
            exports.TouchListener = touchListener_1.TouchListener;
            var baseFrameworkFactory_1 = __webpack_require__(117);
            exports.BaseFrameworkFactory = baseFrameworkFactory_1.BaseFrameworkFactory;
            var cellNavigationService_1 = __webpack_require__(82);
            exports.CellNavigationService = cellNavigationService_1.CellNavigationService;
            var alignedGridsService_1 = __webpack_require__(58);
            exports.AlignedGridsService = alignedGridsService_1.AlignedGridsService;
            var constants_1 = __webpack_require__(9);
            exports.Constants = constants_1.Constants;
            var csvCreator_1 = __webpack_require__(47);
            exports.CsvCreator = csvCreator_1.CsvCreator;
            exports.BaseCreator = csvCreator_1.BaseCreator;
            var downloader_1 = __webpack_require__(84);
            exports.Downloader = downloader_1.Downloader;
            var grid_1 = __webpack_require__(85);
            exports.Grid = grid_1.Grid;
            var gridApi_1 = __webpack_require__(6);
            exports.GridApi = gridApi_1.GridApi;
            var eventKeys_1 = __webpack_require__(25);
            exports.Events = eventKeys_1.Events;
            var focusedCellController_1 = __webpack_require__(22);
            exports.FocusedCellController = focusedCellController_1.FocusedCellController;
            var functions_1 = __webpack_require__(145);
            exports.defaultGroupComparator = functions_1.defaultGroupComparator;
            var gridOptionsWrapper_1 = __webpack_require__(2);
            exports.GridOptionsWrapper = gridOptionsWrapper_1.GridOptionsWrapper;
            var eventService_1 = __webpack_require__(3);
            exports.EventService = eventService_1.EventService;
            var selectableService_1 = __webpack_require__(86);
            exports.SelectableService = selectableService_1.SelectableService;
            var gridCore_1 = __webpack_require__(42);
            exports.GridCore = gridCore_1.GridCore;
            var logger_1 = __webpack_require__(12);
            exports.Logger = logger_1.Logger;
            var selectionController_1 = __webpack_require__(17);
            exports.SelectionController = selectionController_1.SelectionController;
            var sortController_1 = __webpack_require__(24);
            exports.SortController = sortController_1.SortController;
            var templateService_1 = __webpack_require__(49);
            exports.TemplateService = templateService_1.TemplateService;
            var utils_1 = __webpack_require__(1);
            exports.Utils = utils_1.Utils;
            exports.NumberSequence = utils_1.NumberSequence;
            exports._ = utils_1._;
            exports.Promise = utils_1.Promise;
            var valueService_1 = __webpack_require__(16);
            exports.ValueService = valueService_1.ValueService;
            var expressionService_1 = __webpack_require__(19);
            exports.ExpressionService = expressionService_1.ExpressionService;
            var xmlFactory_1 = __webpack_require__(118);
            exports.XmlFactory = xmlFactory_1.XmlFactory;
            var gridSerializer_1 = __webpack_require__(63);
            exports.GridSerializer = gridSerializer_1.GridSerializer;
            exports.BaseGridSerializingSession = gridSerializer_1.BaseGridSerializingSession;
            exports.RowType = gridSerializer_1.RowType;
            var logger_2 = __webpack_require__(12);
            exports.LoggerFactory = logger_2.LoggerFactory;
            var columnApi_1 = __webpack_require__(7);
            exports.ColumnApi = columnApi_1.ColumnApi;
            var frameworkComponentWrapper_1 = __webpack_require__(146);
            exports.BaseComponentWrapper = frameworkComponentWrapper_1.BaseComponentWrapper;
            var environment_1 = __webpack_require__(41);
            exports.Environment = environment_1.Environment;
        }).call(exports, __webpack_require__(120));
    }, function(module, exports) {
        var g;
        g = function() {
            return this;
        }();
        try {
            g = g || Function("return this")() || (1, eval)("this");
        } catch (e) {
            if (typeof window === "object") g = window;
        }
        module.exports = g;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var component_1 = __webpack_require__(8);
        var context_1 = __webpack_require__(0);
        var rowNode_1 = __webpack_require__(14);
        var dragAndDropService_1 = __webpack_require__(15);
        var eventKeys_1 = __webpack_require__(25);
        var utils_1 = __webpack_require__(1);
        var beanStub_1 = __webpack_require__(13);
        var RowDragComp = function(_super) {
            __extends(RowDragComp, _super);
            function RowDragComp(rowNode, column, cellValue, beans) {
                var _this = _super.call(this, '<span class="ag-row-drag"></span>') || this;
                _this.rowNode = rowNode;
                _this.column = column;
                _this.cellValue = cellValue;
                _this.beans = beans;
                return _this;
            }
            RowDragComp.prototype.postConstruct = function() {
                this.addDragSource();
                this.checkCompatibility();
                if (this.beans.gridOptionsWrapper.isRowDragManaged()) {
                    this.addFeature(this.beans.context, new ManagedVisibilityStrategy(this, this.beans, this.rowNode, this.column));
                } else {
                    this.addFeature(this.beans.context, new NonManagedVisibilityStrategy(this, this.beans, this.rowNode, this.column));
                }
            };
            RowDragComp.prototype.checkCompatibility = function() {
                var managed = this.beans.gridOptionsWrapper.isRowDragManaged();
                var treeData = this.beans.gridOptionsWrapper.isTreeData();
                if (treeData && managed) {
                    utils_1._.doOnce(function() {
                        return console.warn("ag-Grid: If using row drag with tree data, you cannot have rowDragManaged=true");
                    }, "RowDragComp.managedAndTreeData");
                }
            };
            RowDragComp.prototype.addDragSource = function() {
                var _this = this;
                var dragItem = {
                    rowNode: this.rowNode
                };
                var dragSource = {
                    type: dragAndDropService_1.DragSourceType.RowDrag,
                    eElement: this.getGui(),
                    dragItemName: this.cellValue,
                    dragItemCallback: function() {
                        return dragItem;
                    },
                    dragStartPixels: 0
                };
                this.beans.dragAndDropService.addDragSource(dragSource, true);
                this.addDestroyFunc(function() {
                    return _this.beans.dragAndDropService.removeDragSource(dragSource);
                });
            };
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], RowDragComp.prototype, "postConstruct", null);
            return RowDragComp;
        }(component_1.Component);
        exports.RowDragComp = RowDragComp;
        var NonManagedVisibilityStrategy = function(_super) {
            __extends(NonManagedVisibilityStrategy, _super);
            function NonManagedVisibilityStrategy(parent, beans, rowNode, column) {
                var _this = _super.call(this) || this;
                _this.parent = parent;
                _this.beans = beans;
                _this.column = column;
                _this.rowNode = rowNode;
                return _this;
            }
            NonManagedVisibilityStrategy.prototype.postConstruct = function() {
                this.addDestroyableEventListener(this.beans.gridOptionsWrapper, "suppressRowDrag", this.onSuppressRowDrag.bind(this));
                this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_DATA_CHANGED, this.workOutVisibility.bind(this));
                this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_CELL_CHANGED, this.workOutVisibility.bind(this));
                this.workOutVisibility();
            };
            NonManagedVisibilityStrategy.prototype.onSuppressRowDrag = function() {
                this.workOutVisibility();
            };
            NonManagedVisibilityStrategy.prototype.workOutVisibility = function() {
                var suppressRowDrag = this.beans.gridOptionsWrapper.isSuppressRowDrag();
                if (suppressRowDrag) {
                    this.parent.setVisible(false);
                } else {
                    var visible = this.column.isRowDrag(this.rowNode);
                    this.parent.setVisible(visible);
                }
            };
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], NonManagedVisibilityStrategy.prototype, "postConstruct", null);
            return NonManagedVisibilityStrategy;
        }(beanStub_1.BeanStub);
        var ManagedVisibilityStrategy = function(_super) {
            __extends(ManagedVisibilityStrategy, _super);
            function ManagedVisibilityStrategy(parent, beans, rowNode, column) {
                var _this = _super.call(this) || this;
                _this.parent = parent;
                _this.beans = beans;
                _this.column = column;
                _this.rowNode = rowNode;
                return _this;
            }
            ManagedVisibilityStrategy.prototype.postConstruct = function() {
                this.addDestroyableEventListener(this.beans.eventService, eventKeys_1.Events.EVENT_SORT_CHANGED, this.onSortChanged.bind(this));
                this.addDestroyableEventListener(this.beans.eventService, eventKeys_1.Events.EVENT_FILTER_CHANGED, this.onFilterChanged.bind(this));
                this.addDestroyableEventListener(this.beans.eventService, eventKeys_1.Events.EVENT_COLUMN_ROW_GROUP_CHANGED, this.onRowGroupChanged.bind(this));
                this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_DATA_CHANGED, this.workOutVisibility.bind(this));
                this.addDestroyableEventListener(this.rowNode, rowNode_1.RowNode.EVENT_CELL_CHANGED, this.workOutVisibility.bind(this));
                this.addDestroyableEventListener(this.beans.gridOptionsWrapper, "suppressRowDrag", this.onSuppressRowDrag.bind(this));
                this.updateSortActive();
                this.updateFilterActive();
                this.updateRowGroupActive();
                this.workOutVisibility();
            };
            ManagedVisibilityStrategy.prototype.updateRowGroupActive = function() {
                var rowGroups = this.beans.columnController.getRowGroupColumns();
                this.rowGroupActive = !utils_1._.missingOrEmpty(rowGroups);
            };
            ManagedVisibilityStrategy.prototype.onRowGroupChanged = function() {
                this.updateRowGroupActive();
                this.workOutVisibility();
            };
            ManagedVisibilityStrategy.prototype.updateSortActive = function() {
                var sortModel = this.beans.sortController.getSortModel();
                this.sortActive = !utils_1._.missingOrEmpty(sortModel);
            };
            ManagedVisibilityStrategy.prototype.onSortChanged = function() {
                this.updateSortActive();
                this.workOutVisibility();
            };
            ManagedVisibilityStrategy.prototype.updateFilterActive = function() {
                this.filterActive = this.beans.filterManager.isAnyFilterPresent();
            };
            ManagedVisibilityStrategy.prototype.onFilterChanged = function() {
                this.updateFilterActive();
                this.workOutVisibility();
            };
            ManagedVisibilityStrategy.prototype.onSuppressRowDrag = function() {
                this.workOutVisibility();
            };
            ManagedVisibilityStrategy.prototype.workOutVisibility = function() {
                var sortOrFilterOrGroupActive = this.sortActive || this.filterActive || this.rowGroupActive;
                var suppressRowDrag = this.beans.gridOptionsWrapper.isSuppressRowDrag();
                var alwaysHide = sortOrFilterOrGroupActive || suppressRowDrag;
                if (alwaysHide) {
                    this.parent.setVisible(false);
                } else {
                    var visible = this.column.isRowDrag(this.rowNode);
                    this.parent.setVisible(visible);
                }
            };
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], ManagedVisibilityStrategy.prototype, "postConstruct", null);
            return ManagedVisibilityStrategy;
        }(beanStub_1.BeanStub);
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var column_1 = __webpack_require__(10);
        var utils_1 = __webpack_require__(1);
        var setLeftFeature_1 = __webpack_require__(52);
        var component_1 = __webpack_require__(8);
        var componentAnnotations_1 = __webpack_require__(11);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var beans_1 = __webpack_require__(28);
        var hoverFeature_1 = __webpack_require__(74);
        var events_1 = __webpack_require__(5);
        var eventService_1 = __webpack_require__(3);
        var columnHoverService_1 = __webpack_require__(45);
        var BaseFilterWrapperComp = function(_super) {
            __extends(BaseFilterWrapperComp, _super);
            function BaseFilterWrapperComp() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            BaseFilterWrapperComp.prototype.init = function(params) {
                this.column = params.column;
                var base = utils_1._.loadTemplate('<div class="ag-header-cell" aria-hidden="true"><div class="ag-floating-filter-body" aria-hidden="true"></div></div>');
                this.enrichBody(base);
                this.setTemplateFromElement(base);
                this.setupWidth();
                this.addColumnHoverListener();
                this.addFeature(this.context, new hoverFeature_1.HoverFeature([ this.column ], this.getGui()));
                var setLeftFeature = new setLeftFeature_1.SetLeftFeature(this.column, this.getGui(), this.beans);
                setLeftFeature.init();
                this.addDestroyFunc(setLeftFeature.destroy.bind(setLeftFeature));
            };
            BaseFilterWrapperComp.prototype.addColumnHoverListener = function() {
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_COLUMN_HOVER_CHANGED, this.onColumnHover.bind(this));
                this.onColumnHover();
            };
            BaseFilterWrapperComp.prototype.onColumnHover = function() {
                var isHovered = this.columnHoverService.isHovered(this.column);
                utils_1._.addOrRemoveCssClass(this.getGui(), "ag-column-hover", isHovered);
            };
            BaseFilterWrapperComp.prototype.setupWidth = function() {
                this.addDestroyableEventListener(this.column, column_1.Column.EVENT_WIDTH_CHANGED, this.onColumnWidthChanged.bind(this));
                this.onColumnWidthChanged();
            };
            BaseFilterWrapperComp.prototype.onColumnWidthChanged = function() {
                this.getGui().style.width = this.column.getActualWidth() + "px";
            };
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], BaseFilterWrapperComp.prototype, "context", void 0);
            __decorate([ context_1.Autowired("columnHoverService"), __metadata("design:type", columnHoverService_1.ColumnHoverService) ], BaseFilterWrapperComp.prototype, "columnHoverService", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], BaseFilterWrapperComp.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("beans"), __metadata("design:type", beans_1.Beans) ], BaseFilterWrapperComp.prototype, "beans", void 0);
            return BaseFilterWrapperComp;
        }(component_1.Component);
        exports.BaseFilterWrapperComp = BaseFilterWrapperComp;
        var FloatingFilterWrapperComp = function(_super) {
            __extends(FloatingFilterWrapperComp, _super);
            function FloatingFilterWrapperComp() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            FloatingFilterWrapperComp.prototype.init = function(params) {
                this.floatingFilterCompPromise = params.floatingFilterComp;
                this.suppressFilterButton = params.suppressFilterButton;
                _super.prototype.init.call(this, params);
                this.addEventListeners();
            };
            FloatingFilterWrapperComp.prototype.addEventListeners = function() {
                if (!this.suppressFilterButton && this.eButtonShowMainFilter) {
                    this.addDestroyableEventListener(this.eButtonShowMainFilter, "click", this.showParentFilter.bind(this));
                }
            };
            FloatingFilterWrapperComp.prototype.enrichBody = function(body) {
                var _this = this;
                this.floatingFilterCompPromise.then(function(floatingFilterComp) {
                    var floatingFilterBody = body.querySelector(".ag-floating-filter-body");
                    var floatingFilterCompUi = floatingFilterComp.getGui();
                    if (_this.suppressFilterButton) {
                        floatingFilterBody.appendChild(floatingFilterCompUi);
                        utils_1._.removeCssClass(floatingFilterBody, "ag-floating-filter-body");
                        utils_1._.addCssClass(floatingFilterBody, "ag-floating-filter-full-body");
                    } else {
                        floatingFilterBody.appendChild(floatingFilterCompUi);
                        body.appendChild(utils_1._.loadTemplate('<div class="ag-floating-filter-button" aria-hidden="true">\n                        <button type="button" ref="eButtonShowMainFilter"></button>\n                </div>'));
                        var eIcon = utils_1._.createIconNoSpan("filter", _this.gridOptionsWrapper, _this.column);
                        body.querySelector("button").appendChild(eIcon);
                    }
                    if (floatingFilterComp.afterGuiAttached) {
                        floatingFilterComp.afterGuiAttached();
                    }
                    _this.wireQuerySelectors();
                    _this.addEventListeners();
                });
            };
            FloatingFilterWrapperComp.prototype.onParentModelChanged = function(parentModel) {
                var combinedFilter = undefined;
                var mainModel = null;
                if (parentModel && parentModel.operator) {
                    combinedFilter = parentModel;
                    mainModel = combinedFilter.condition1;
                } else {
                    mainModel = parentModel;
                }
                this.floatingFilterCompPromise.then(function(floatingFilterComp) {
                    floatingFilterComp.onParentModelChanged(mainModel, combinedFilter);
                });
            };
            FloatingFilterWrapperComp.prototype.showParentFilter = function() {
                this.menuFactory.showMenuAfterButtonClick(this.column, this.eButtonShowMainFilter, "filterMenuTab", [ "filterMenuTab" ]);
            };
            __decorate([ componentAnnotations_1.RefSelector("eButtonShowMainFilter"), __metadata("design:type", HTMLInputElement) ], FloatingFilterWrapperComp.prototype, "eButtonShowMainFilter", void 0);
            __decorate([ context_1.Autowired("menuFactory"), __metadata("design:type", Object) ], FloatingFilterWrapperComp.prototype, "menuFactory", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], FloatingFilterWrapperComp.prototype, "gridOptionsWrapper", void 0);
            return FloatingFilterWrapperComp;
        }(BaseFilterWrapperComp);
        exports.FloatingFilterWrapperComp = FloatingFilterWrapperComp;
        var EmptyFloatingFilterWrapperComp = function(_super) {
            __extends(EmptyFloatingFilterWrapperComp, _super);
            function EmptyFloatingFilterWrapperComp() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            EmptyFloatingFilterWrapperComp.prototype.enrichBody = function(body) {};
            EmptyFloatingFilterWrapperComp.prototype.onParentModelChanged = function(parentModel) {};
            return EmptyFloatingFilterWrapperComp;
        }(BaseFilterWrapperComp);
        exports.EmptyFloatingFilterWrapperComp = EmptyFloatingFilterWrapperComp;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var LinkedList = function() {
            function LinkedList() {
                this.first = null;
                this.last = null;
            }
            LinkedList.prototype.add = function(item) {
                var entry = {
                    item: item,
                    next: null
                };
                if (this.last) {
                    this.last.next = entry;
                } else {
                    this.first = entry;
                }
                this.last = entry;
            };
            LinkedList.prototype.remove = function() {
                var result = this.first;
                if (result) {
                    this.first = result.next;
                    if (!this.first) {
                        this.last = null;
                    }
                }
                return result.item;
            };
            LinkedList.prototype.isEmpty = function() {
                return !this.first;
            };
            return LinkedList;
        }();
        exports.LinkedList = LinkedList;
        var LinkedListItem = function() {
            function LinkedListItem() {}
            return LinkedListItem;
        }();
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var context_1 = __webpack_require__(0);
        var component_1 = __webpack_require__(8);
        var componentRecipes_1 = __webpack_require__(21);
        var OverlayWrapperComponent = function(_super) {
            __extends(OverlayWrapperComponent, _super);
            function OverlayWrapperComponent() {
                return _super.call(this) || this;
            }
            OverlayWrapperComponent.prototype.init = function() {};
            OverlayWrapperComponent.prototype.showLoadingOverlay = function(eOverlayWrapper) {
                var _this = this;
                this.setTemplate(OverlayWrapperComponent.LOADING_WRAPPER_OVERLAY_TEMPLATE);
                this.componentRecipes.newLoadingOverlayComponent().then(function(renderer) {
                    var loadingOverlayWrapper = _this.getRefElement("loadingOverlayWrapper");
                    utils_1.Utils.removeAllChildren(loadingOverlayWrapper);
                    loadingOverlayWrapper.appendChild(renderer.getGui());
                });
                this.showOverlay(eOverlayWrapper, this.getGui());
            };
            OverlayWrapperComponent.prototype.showNoRowsOverlay = function(eOverlayWrapper) {
                var _this = this;
                this.setTemplate(OverlayWrapperComponent.NO_ROWS_WRAPPER_OVERLAY_TEMPLATE);
                this.componentRecipes.newNoRowsOverlayComponent().then(function(renderer) {
                    var noRowsOverlayWrapper = _this.getRefElement("noRowsOverlayWrapper");
                    utils_1.Utils.removeAllChildren(noRowsOverlayWrapper);
                    noRowsOverlayWrapper.appendChild(renderer.getGui());
                });
                this.showOverlay(eOverlayWrapper, this.getGui());
            };
            OverlayWrapperComponent.prototype.hideOverlay = function(eOverlayWrapper) {
                utils_1.Utils.removeAllChildren(eOverlayWrapper);
                utils_1.Utils.setVisible(eOverlayWrapper, false);
            };
            OverlayWrapperComponent.prototype.showOverlay = function(eOverlayWrapper, overlay) {
                if (overlay) {
                    utils_1.Utils.removeAllChildren(eOverlayWrapper);
                    utils_1.Utils.setVisible(eOverlayWrapper, true);
                    eOverlayWrapper.appendChild(overlay);
                } else {
                    console.warn("ag-Grid: unknown overlay");
                    this.hideOverlay(eOverlayWrapper);
                }
            };
            OverlayWrapperComponent.LOADING_WRAPPER_OVERLAY_TEMPLATE = '<div class="ag-overlay-panel" role="presentation">' + '<div class="ag-overlay-wrapper ag-overlay-loading-wrapper" ref="loadingOverlayWrapper">[OVERLAY_TEMPLATE]</div>' + "</div>";
            OverlayWrapperComponent.NO_ROWS_WRAPPER_OVERLAY_TEMPLATE = '<div class="ag-overlay-panel" role="presentation">' + '<div class="ag-overlay-wrapper ag-overlay-no-rows-wrapper" ref="noRowsOverlayWrapper">[OVERLAY_TEMPLATE]</div>' + "</div>";
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], OverlayWrapperComponent.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("componentRecipes"), __metadata("design:type", componentRecipes_1.ComponentRecipes) ], OverlayWrapperComponent.prototype, "componentRecipes", void 0);
            return OverlayWrapperComponent;
        }(component_1.Component);
        exports.OverlayWrapperComponent = OverlayWrapperComponent;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var component_1 = __webpack_require__(8);
        var column_1 = __webpack_require__(10);
        var utils_1 = __webpack_require__(1);
        var context_1 = __webpack_require__(0);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var sortController_1 = __webpack_require__(24);
        var touchListener_1 = __webpack_require__(46);
        var eventService_1 = __webpack_require__(3);
        var componentAnnotations_1 = __webpack_require__(11);
        var events_1 = __webpack_require__(5);
        var HeaderComp = function(_super) {
            __extends(HeaderComp, _super);
            function HeaderComp() {
                var _this = _super !== null && _super.apply(this, arguments) || this;
                _this.lastMovingChanged = 0;
                return _this;
            }
            HeaderComp.prototype.init = function(params) {
                var template = utils_1.Utils.firstExistingValue(params.template, HeaderComp.TEMPLATE);
                this.setTemplate(template);
                this.params = params;
                this.setupTap();
                this.setupIcons(params.column);
                this.setupMenu();
                this.setupSort();
                this.setupFilterIcon();
                this.setupText(params.displayName);
            };
            HeaderComp.prototype.setupText = function(displayName) {
                if (this.eText) {
                    this.eText.innerHTML = displayName;
                }
            };
            HeaderComp.prototype.setupIcons = function(column) {
                this.addInIcon("sortAscending", this.eSortAsc, column);
                this.addInIcon("sortDescending", this.eSortDesc, column);
                this.addInIcon("sortUnSort", this.eSortNone, column);
                this.addInIcon("menu", this.eMenu, column);
                this.addInIcon("filter", this.eFilter, column);
            };
            HeaderComp.prototype.addInIcon = function(iconName, eParent, column) {
                if (eParent == null) return;
                var eIcon = utils_1.Utils.createIconNoSpan(iconName, this.gridOptionsWrapper, column);
                eParent.appendChild(eIcon);
            };
            HeaderComp.prototype.setupTap = function() {
                var _this = this;
                if (this.gridOptionsWrapper.isSuppressTouch()) {
                    return;
                }
                var touchListener = new touchListener_1.TouchListener(this.getGui());
                if (this.params.enableMenu) {
                    var longTapListener = function(event) {
                        _this.gridOptionsWrapper.getApi().showColumnMenuAfterMouseClick(_this.params.column, event.touchStart);
                    };
                    this.addDestroyableEventListener(touchListener, touchListener_1.TouchListener.EVENT_LONG_TAP, longTapListener);
                }
                if (this.params.enableSorting) {
                    var tapListener = function() {
                        _this.sortController.progressSort(_this.params.column, false, "uiColumnSorted");
                    };
                    this.addDestroyableEventListener(touchListener, touchListener_1.TouchListener.EVENT_TAP, tapListener);
                }
                this.addDestroyFunc(function() {
                    return touchListener.destroy();
                });
            };
            HeaderComp.prototype.setupMenu = function() {
                var _this = this;
                if (!this.eMenu) {
                    return;
                }
                var dontShowMenu = !this.params.enableMenu || utils_1.Utils.isUserAgentIPad();
                if (dontShowMenu) {
                    utils_1.Utils.removeFromParent(this.eMenu);
                    return;
                }
                this.eMenu.addEventListener("click", function() {
                    return _this.showMenu(_this.eMenu);
                });
                if (!this.gridOptionsWrapper.isSuppressMenuHide()) {
                    this.eMenu.style.opacity = "0";
                    this.addGuiEventListener("mouseover", function() {
                        _this.eMenu.style.opacity = "1";
                    });
                    this.addGuiEventListener("mouseout", function() {
                        _this.eMenu.style.opacity = "0";
                    });
                }
                var style = this.eMenu.style;
                style["transition"] = "opacity 0.2s, border 0.2s";
                style["-webkit-transition"] = "opacity 0.2s, border 0.2s";
            };
            HeaderComp.prototype.showMenu = function(eventSource) {
                this.menuFactory.showMenuAfterButtonClick(this.params.column, eventSource);
            };
            HeaderComp.prototype.removeSortIcons = function() {
                utils_1.Utils.removeFromParent(this.eSortAsc);
                utils_1.Utils.removeFromParent(this.eSortDesc);
                utils_1.Utils.removeFromParent(this.eSortNone);
                utils_1.Utils.removeFromParent(this.eSortOrder);
            };
            HeaderComp.prototype.setupSort = function() {
                var _this = this;
                var enableSorting = this.params.enableSorting;
                if (!enableSorting) {
                    this.removeSortIcons();
                    return;
                }
                var sortUsingCtrl = this.gridOptionsWrapper.isMultiSortKeyCtrl();
                this.addDestroyableEventListener(this.params.column, column_1.Column.EVENT_MOVING_CHANGED, function() {
                    _this.lastMovingChanged = new Date().getTime();
                });
                if (this.eLabel) {
                    this.addDestroyableEventListener(this.eLabel, "click", function(event) {
                        var moving = _this.params.column.isMoving();
                        var nowTime = new Date().getTime();
                        var movedRecently = nowTime - _this.lastMovingChanged < 50;
                        var columnMoving = moving || movedRecently;
                        if (!columnMoving) {
                            var multiSort = sortUsingCtrl ? event.ctrlKey || event.metaKey : event.shiftKey;
                            _this.params.progressSort(multiSort);
                        } else {
                            console.log("kipping sort cos of moving " + _this.lastMovingChanged);
                        }
                    });
                }
                this.addDestroyableEventListener(this.params.column, column_1.Column.EVENT_SORT_CHANGED, this.onSortChanged.bind(this));
                this.onSortChanged();
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_SORT_CHANGED, this.setMultiSortOrder.bind(this));
                this.setMultiSortOrder();
            };
            HeaderComp.prototype.onSortChanged = function() {
                utils_1.Utils.addOrRemoveCssClass(this.getGui(), "ag-header-cell-sorted-asc", this.params.column.isSortAscending());
                utils_1.Utils.addOrRemoveCssClass(this.getGui(), "ag-header-cell-sorted-desc", this.params.column.isSortDescending());
                utils_1.Utils.addOrRemoveCssClass(this.getGui(), "ag-header-cell-sorted-none", this.params.column.isSortNone());
                if (this.eSortAsc) {
                    utils_1.Utils.addOrRemoveCssClass(this.eSortAsc, "ag-hidden", !this.params.column.isSortAscending());
                }
                if (this.eSortDesc) {
                    utils_1.Utils.addOrRemoveCssClass(this.eSortDesc, "ag-hidden", !this.params.column.isSortDescending());
                }
                if (this.eSortNone) {
                    var alwaysHideNoSort = !this.params.column.getColDef().unSortIcon && !this.gridOptionsWrapper.isUnSortIcon();
                    utils_1.Utils.addOrRemoveCssClass(this.eSortNone, "ag-hidden", alwaysHideNoSort || !this.params.column.isSortNone());
                }
            };
            HeaderComp.prototype.setMultiSortOrder = function() {
                if (!this.eSortOrder) {
                    return;
                }
                var col = this.params.column;
                var allColumnsWithSorting = this.sortController.getColumnsWithSortingOrdered();
                var indexThisCol = allColumnsWithSorting.indexOf(col);
                var moreThanOneColSorting = allColumnsWithSorting.length > 1;
                var showIndex = col.isSorting() && moreThanOneColSorting;
                utils_1.Utils.setVisible(this.eSortOrder, showIndex);
                if (indexThisCol >= 0) {
                    this.eSortOrder.innerHTML = (indexThisCol + 1).toString();
                } else {
                    this.eSortOrder.innerHTML = "";
                }
            };
            HeaderComp.prototype.setupFilterIcon = function() {
                if (!this.eFilter) {
                    return;
                }
                this.addDestroyableEventListener(this.params.column, column_1.Column.EVENT_FILTER_CHANGED, this.onFilterChanged.bind(this));
                this.onFilterChanged();
            };
            HeaderComp.prototype.onFilterChanged = function() {
                var filterPresent = this.params.column.isFilterActive();
                utils_1.Utils.addOrRemoveCssClass(this.eFilter, "ag-hidden", !filterPresent);
            };
            HeaderComp.TEMPLATE = '<div class="ag-cell-label-container" role="presentation">' + '  <span ref="eMenu" class="ag-header-icon ag-header-cell-menu-button" aria-hidden="true"></span>' + '  <div ref="eLabel" class="ag-header-cell-label" role="presentation">' + '    <span ref="eText" class="ag-header-cell-text" role="columnheader"></span>' + '    <span ref="eFilter" class="ag-header-icon ag-filter-icon" aria-hidden="true"></span>' + '    <span ref="eSortOrder" class="ag-header-icon ag-sort-order" aria-hidden="true"></span>' + '    <span ref="eSortAsc" class="ag-header-icon ag-sort-ascending-icon" aria-hidden="true"></span>' + '    <span ref="eSortDesc" class="ag-header-icon ag-sort-descending-icon" aria-hidden="true"></span>' + '    <span ref="eSortNone" class="ag-header-icon ag-sort-none-icon" aria-hidden="true"></span>' + "  </div>" + "</div>";
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], HeaderComp.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("sortController"), __metadata("design:type", sortController_1.SortController) ], HeaderComp.prototype, "sortController", void 0);
            __decorate([ context_1.Autowired("menuFactory"), __metadata("design:type", Object) ], HeaderComp.prototype, "menuFactory", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], HeaderComp.prototype, "eventService", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eFilter"), __metadata("design:type", HTMLElement) ], HeaderComp.prototype, "eFilter", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eSortAsc"), __metadata("design:type", HTMLElement) ], HeaderComp.prototype, "eSortAsc", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eSortDesc"), __metadata("design:type", HTMLElement) ], HeaderComp.prototype, "eSortDesc", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eSortNone"), __metadata("design:type", HTMLElement) ], HeaderComp.prototype, "eSortNone", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eSortOrder"), __metadata("design:type", HTMLElement) ], HeaderComp.prototype, "eSortOrder", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eMenu"), __metadata("design:type", HTMLElement) ], HeaderComp.prototype, "eMenu", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eLabel"), __metadata("design:type", HTMLElement) ], HeaderComp.prototype, "eLabel", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eText"), __metadata("design:type", HTMLElement) ], HeaderComp.prototype, "eText", void 0);
            return HeaderComp;
        }(component_1.Component);
        exports.HeaderComp = HeaderComp;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var component_1 = __webpack_require__(8);
        var utils_1 = __webpack_require__(1);
        var columnController_1 = __webpack_require__(4);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var context_1 = __webpack_require__(0);
        var touchListener_1 = __webpack_require__(46);
        var componentAnnotations_1 = __webpack_require__(11);
        var originalColumnGroup_1 = __webpack_require__(32);
        var HeaderGroupComp = function(_super) {
            __extends(HeaderGroupComp, _super);
            function HeaderGroupComp() {
                return _super.call(this, HeaderGroupComp.TEMPLATE) || this;
            }
            HeaderGroupComp.prototype.init = function(params) {
                this.params = params;
                this.setupLabel();
                this.addGroupExpandIcon();
                this.setupExpandIcons();
            };
            HeaderGroupComp.prototype.setupExpandIcons = function() {
                var _this = this;
                this.addInIcon("columnGroupOpened", "agOpened");
                this.addInIcon("columnGroupClosed", "agClosed");
                var expandAction = function(event) {
                    if (utils_1.Utils.isStopPropagationForAgGrid(event)) {
                        return;
                    }
                    var newExpandedValue = !_this.params.columnGroup.isExpanded();
                    _this.columnController.setColumnGroupOpened(_this.params.columnGroup.getOriginalColumnGroup(), newExpandedValue, "uiColumnExpanded");
                };
                this.addTouchAndClickListeners(this.eCloseIcon, expandAction);
                this.addTouchAndClickListeners(this.eOpenIcon, expandAction);
                var stopPropagationAction = function(event) {
                    utils_1.Utils.stopPropagationForAgGrid(event);
                };
                this.addDestroyableEventListener(this.eCloseIcon, "dblclick", stopPropagationAction);
                this.addDestroyableEventListener(this.eOpenIcon, "dblclick", stopPropagationAction);
                this.addDestroyableEventListener(this.getGui(), "dblclick", expandAction);
                this.updateIconVisibility();
                var originalColumnGroup = this.params.columnGroup.getOriginalColumnGroup();
                this.addDestroyableEventListener(originalColumnGroup, originalColumnGroup_1.OriginalColumnGroup.EVENT_EXPANDED_CHANGED, this.updateIconVisibility.bind(this));
                this.addDestroyableEventListener(originalColumnGroup, originalColumnGroup_1.OriginalColumnGroup.EVENT_EXPANDABLE_CHANGED, this.updateIconVisibility.bind(this));
            };
            HeaderGroupComp.prototype.addTouchAndClickListeners = function(eElement, action) {
                var touchListener = new touchListener_1.TouchListener(this.eCloseIcon);
                this.addDestroyableEventListener(touchListener, touchListener_1.TouchListener.EVENT_TAP, action);
                this.addDestroyFunc(function() {
                    return touchListener.destroy();
                });
                this.addDestroyableEventListener(eElement, "click", action);
            };
            HeaderGroupComp.prototype.updateIconVisibility = function() {
                var columnGroup = this.params.columnGroup;
                if (columnGroup.isExpandable()) {
                    var expanded = this.params.columnGroup.isExpanded();
                    utils_1.Utils.setVisible(this.eOpenIcon, !expanded);
                    utils_1.Utils.setVisible(this.eCloseIcon, expanded);
                } else {
                    utils_1.Utils.setVisible(this.eOpenIcon, false);
                    utils_1.Utils.setVisible(this.eCloseIcon, false);
                }
            };
            HeaderGroupComp.prototype.addInIcon = function(iconName, refName) {
                var eIcon = utils_1.Utils.createIconNoSpan(iconName, this.gridOptionsWrapper, null);
                this.getRefElement(refName).appendChild(eIcon);
            };
            HeaderGroupComp.prototype.addGroupExpandIcon = function() {
                if (!this.params.columnGroup.isExpandable()) {
                    utils_1.Utils.setVisible(this.eOpenIcon, false);
                    utils_1.Utils.setVisible(this.eCloseIcon, false);
                    return;
                }
            };
            HeaderGroupComp.prototype.setupLabel = function() {
                if (this.params.displayName && this.params.displayName !== "") {
                    var eInnerText = this.getRefElement("agLabel");
                    eInnerText.innerHTML = this.params.displayName;
                }
            };
            HeaderGroupComp.TEMPLATE = '<div class="ag-header-group-cell-label" ref="agContainer">' + '<span ref="agLabel" class="ag-header-group-text"></span>' + '<span ref="agOpened" class="ag-header-icon ag-header-expand-icon ag-header-expand-icon-expanded"></span>' + '<span ref="agClosed" class="ag-header-icon ag-header-expand-icon ag-header-expand-icon-collapsed"></span>' + "</div>";
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], HeaderGroupComp.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], HeaderGroupComp.prototype, "gridOptionsWrapper", void 0);
            __decorate([ componentAnnotations_1.RefSelector("agOpened"), __metadata("design:type", HTMLElement) ], HeaderGroupComp.prototype, "eOpenIcon", void 0);
            __decorate([ componentAnnotations_1.RefSelector("agClosed"), __metadata("design:type", HTMLElement) ], HeaderGroupComp.prototype, "eCloseIcon", void 0);
            return HeaderGroupComp;
        }(component_1.Component);
        exports.HeaderGroupComp = HeaderGroupComp;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var context_1 = __webpack_require__(0);
        var component_1 = __webpack_require__(8);
        var LoadingOverlayComponent = function(_super) {
            __extends(LoadingOverlayComponent, _super);
            function LoadingOverlayComponent() {
                return _super.call(this) || this;
            }
            LoadingOverlayComponent.prototype.init = function(params) {
                var template = this.gridOptionsWrapper.getOverlayLoadingTemplate() ? this.gridOptionsWrapper.getOverlayLoadingTemplate() : LoadingOverlayComponent.DEFAULT_LOADING_OVERLAY_TEMPLATE;
                var localeTextFunc = this.gridOptionsWrapper.getLocaleTextFunc();
                var localisedTemplate = template.replace("[LOADING...]", localeTextFunc("loadingOoo", "Loading..."));
                this.setTemplate(localisedTemplate);
            };
            LoadingOverlayComponent.DEFAULT_LOADING_OVERLAY_TEMPLATE = '<span class="ag-overlay-loading-center">[LOADING...]</span>';
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], LoadingOverlayComponent.prototype, "gridOptionsWrapper", void 0);
            return LoadingOverlayComponent;
        }(component_1.Component);
        exports.LoadingOverlayComponent = LoadingOverlayComponent;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var context_1 = __webpack_require__(0);
        var component_1 = __webpack_require__(8);
        var NoRowsOverlayComponent = function(_super) {
            __extends(NoRowsOverlayComponent, _super);
            function NoRowsOverlayComponent() {
                return _super.call(this) || this;
            }
            NoRowsOverlayComponent.prototype.init = function(params) {
                var template = this.gridOptionsWrapper.getOverlayNoRowsTemplate() ? this.gridOptionsWrapper.getOverlayNoRowsTemplate() : NoRowsOverlayComponent.DEFAULT_NO_ROWS_TEMPLATE;
                var localeTextFunc = this.gridOptionsWrapper.getLocaleTextFunc();
                var localisedTemplate = template.replace("[NO_ROWS_TO_SHOW]", localeTextFunc("noRowsToShow", "No Rows To Show"));
                this.setTemplate(localisedTemplate);
            };
            NoRowsOverlayComponent.DEFAULT_NO_ROWS_TEMPLATE = '<span class="ag-overlay-no-rows-center">[NO_ROWS_TO_SHOW]</span>';
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], NoRowsOverlayComponent.prototype, "gridOptionsWrapper", void 0);
            return NoRowsOverlayComponent;
        }(component_1.Component);
        exports.NoRowsOverlayComponent = NoRowsOverlayComponent;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var requestAnimationFrame$1 = function() {
            if (typeof requestAnimationFrame === "function") {
                return requestAnimationFrame.bind(window);
            }
            return function(callback) {
                return setTimeout(function() {
                    return callback(Date.now());
                }, 1e3 / 60);
            };
        }();
        var trailingTimeout = 2;
        var throttle = function(callback, delay) {
            var leadingCall = false;
            var trailingCall = false;
            var lastCallTime = 0;
            function resolvePending() {
                if (leadingCall) {
                    leadingCall = false;
                    callback();
                }
                if (trailingCall) {
                    proxy();
                }
            }
            function timeoutCallback() {
                requestAnimationFrame$1(resolvePending);
            }
            function proxy() {
                var timeStamp = Date.now();
                if (leadingCall) {
                    if (timeStamp - lastCallTime < trailingTimeout) {
                        return;
                    }
                    trailingCall = true;
                } else {
                    leadingCall = true;
                    trailingCall = false;
                    setTimeout(timeoutCallback, delay);
                }
                lastCallTime = timeStamp;
            }
            return proxy;
        };
        var REFRESH_DELAY = 20;
        var mutationObserverSupported = typeof MutationObserver !== "undefined";
        var getWindowOf = function(target) {
            var ownerGlobal = target && target.ownerDocument && target.ownerDocument.defaultView;
            return ownerGlobal || window;
        };
        var emptyRect = createRectInit(0, 0, 0, 0);
        function toFloat(value) {
            return parseFloat(value) || 0;
        }
        function getBordersSize(styles, start, end) {
            var positions = [ start, end ];
            return positions.reduce(function(size, position) {
                var value = styles.getPropertyValue("border-" + position + "-width");
                return size + toFloat(value);
            }, 0);
        }
        function getPaddings(styles) {
            var positions = [ "top", "right", "bottom", "left" ];
            var paddings = {
                top: null,
                left: null,
                right: null,
                bottom: null
            };
            for (var i = 0, list = positions; i < list.length; i += 1) {
                var position = list[i];
                var value = styles.getPropertyValue("padding-" + position);
                paddings[position] = toFloat(value);
            }
            return paddings;
        }
        function getHTMLElementContentRect(target) {
            var clientWidth = target.clientWidth;
            var clientHeight = target.clientHeight;
            if (!clientWidth && !clientHeight) {
                return emptyRect;
            }
            var styles = getWindowOf(target).getComputedStyle(target);
            var paddings = getPaddings(styles);
            var horizPad = paddings.left + paddings.right;
            var vertPad = paddings.top + paddings.bottom;
            var width = toFloat(styles.width);
            var height = toFloat(styles.height);
            if (styles.boxSizing === "border-box") {
                if (Math.round(width + horizPad) !== clientWidth) {
                    width -= getBordersSize(styles, "left", "right") + horizPad;
                }
                if (Math.round(height + vertPad) !== clientHeight) {
                    height -= getBordersSize(styles, "top", "bottom") + vertPad;
                }
            }
            var vertScrollbar = Math.round(width + horizPad) - clientWidth;
            var horizScrollbar = Math.round(height + vertPad) - clientHeight;
            if (Math.abs(vertScrollbar) !== 1) {
                width -= vertScrollbar;
            }
            if (Math.abs(horizScrollbar) !== 1) {
                height -= horizScrollbar;
            }
            return createRectInit(paddings.left, paddings.top, width, height);
        }
        function getContentRect(target) {
            return getHTMLElementContentRect(target);
        }
        function createReadOnlyRect(ref) {
            var x = ref.x;
            var y = ref.y;
            var width = ref.width;
            var height = ref.height;
            var Constr = window.DOMRectReadOnly ? window.DOMRectReadOnly : Object;
            var rect = Object.create(Constr.prototype);
            defineConfigurable(rect, {
                x: x,
                y: y,
                width: width,
                height: height,
                top: y,
                right: x + width,
                bottom: height + y,
                left: x
            });
            return rect;
        }
        function createRectInit(x, y, width, height) {
            return {
                x: x,
                y: y,
                width: width,
                height: height
            };
        }
        var ResizeObserverController = function() {
            function ResizeObserverController() {
                this.connected_ = false;
                this.mutationEventsAdded_ = false;
                this.mutationsObserver_ = null;
                this.observers_ = [];
                this.callback_ = null;
                this.refresh = throttle(this.refresh.bind(this), REFRESH_DELAY);
            }
            ResizeObserverController.prototype.addObserver = function(observer) {
                if (this.observers_.indexOf(observer) == -1) {
                    this.observers_.push(observer);
                }
                if (!this.connected_) {
                    this.connect_();
                }
            };
            ResizeObserverController.prototype.removeObserver = function(observer) {
                var observers = this.observers_;
                var index = observers.indexOf(observer);
                if (index > -1) {
                    observers.splice(index, 1);
                }
                if (!observers.length && this.connected_) {
                    this.disconnect_();
                }
            };
            ResizeObserverController.prototype.refresh = function() {
                var changesDetected = this.updateObservers_();
                if (changesDetected) {
                    this.refresh();
                }
            };
            ResizeObserverController.prototype.updateObservers_ = function() {
                var activeObservers = this.observers_.filter(function(observer) {
                    return observer.hasActive();
                });
                activeObservers.forEach(function(observer) {
                    return observer.broadcastActive();
                });
                return activeObservers.length > 0;
            };
            ResizeObserverController.prototype.connect_ = function() {
                if (this.connected_) {
                    return;
                }
                window.addEventListener("resize", this.refresh);
                if (mutationObserverSupported) {
                    this.mutationsObserver_ = new MutationObserver(this.refresh);
                    this.mutationsObserver_.observe(document, {
                        attributes: true,
                        childList: true,
                        characterData: true,
                        subtree: true
                    });
                } else {
                    document.addEventListener("DOMSubtreeModified", this.refresh);
                    this.mutationEventsAdded_ = true;
                }
                this.connected_ = true;
            };
            ResizeObserverController.prototype.disconnect_ = function() {
                if (!this.connected_) {
                    return;
                }
                window.removeEventListener("resize", this.refresh);
                if (this.mutationsObserver_) {
                    this.mutationsObserver_.disconnect();
                }
                if (this.mutationEventsAdded_) {
                    document.removeEventListener("DOMSubtreeModified", this.refresh);
                }
                this.mutationsObserver_ = null;
                this.mutationEventsAdded_ = false;
                this.connected_ = false;
            };
            ResizeObserverController.getInstance = function() {
                if (!this.instance_) {
                    this.instance_ = new ResizeObserverController();
                }
                return this.instance_;
            };
            ResizeObserverController.instance_ = null;
            return ResizeObserverController;
        }();
        var defineConfigurable = function(target, props) {
            for (var i = 0, list = Object.keys(props); i < list.length; i += 1) {
                var key = list[i];
                Object.defineProperty(target, key, {
                    value: props[key],
                    enumerable: false,
                    writable: false,
                    configurable: true
                });
            }
            return target;
        };
        var ResizeObservation = function() {
            function ResizeObservation(target) {
                this.target = target;
                this.broadcastWidth = 0;
                this.broadcastHeight = 0;
                this.contentRect_ = null;
                this.contentRect_ = createRectInit(0, 0, 0, 0);
            }
            ResizeObservation.prototype.isActive = function() {
                var rect = getContentRect(this.target);
                this.contentRect_ = rect;
                return rect.width !== this.broadcastWidth || rect.height !== this.broadcastHeight;
            };
            ResizeObservation.prototype.broadcastRect = function() {
                var rect = this.contentRect_;
                this.broadcastWidth = rect.width;
                this.broadcastHeight = rect.height;
                return rect;
            };
            return ResizeObservation;
        }();
        var ResizeObserverSPI = function() {
            function ResizeObserverSPI(callback, controller, callbackCtx) {
                this.observation = null;
                this.callback_ = null;
                this.controller_ = null;
                this.callbackCtx_ = null;
                this.observation = null;
                if (typeof callback !== "function") {
                    throw new TypeError("The callback provided as parameter 1 is not a function.");
                }
                this.callback_ = callback;
                this.controller_ = controller;
                this.callbackCtx_ = callbackCtx;
            }
            ResizeObserverSPI.prototype.observe = function(target) {
                this.observation = new ResizeObservation(target);
                this.controller_.addObserver(this);
                this.controller_.refresh();
            };
            ResizeObserverSPI.prototype.disconnect = function() {
                this.observation = null;
                this.controller_.removeObserver(this);
            };
            ResizeObserverSPI.prototype.broadcastActive = function() {
                if (!this.hasActive()) {
                    return;
                }
                var ctx = this.callbackCtx_;
                this.callback_.call(ctx, {
                    target: this.observation.target,
                    contentRect: createReadOnlyRect(this.observation.broadcastRect())
                }, ctx);
            };
            ResizeObserverSPI.prototype.hasActive = function() {
                return this.observation.isActive();
            };
            return ResizeObserverSPI;
        }();
        var ResizeObserverFallback = function() {
            function ResizeObserverFallback(callback) {
                var controller = ResizeObserverController.getInstance();
                var observer = new ResizeObserverSPI(callback, controller, this);
                this.observer_ = observer;
            }
            ResizeObserverFallback.prototype.observe = function(element) {
                this.observer_.observe(element);
            };
            ResizeObserverFallback.prototype.disconnect = function() {
                this.observer_.disconnect();
            };
            return ResizeObserverFallback;
        }();
        function observeResize(element, callback) {
            if (window.ResizeObserver) {
                var ro_1 = new window.ResizeObserver(function(entries, observer) {
                    for (var _i = 0, entries_1 = entries; _i < entries_1.length; _i++) {
                        var entry = entries_1[_i];
                        callback(entry);
                    }
                });
                ro_1.observe(element);
                return function unobserve() {
                    ro_1.disconnect();
                };
            } else {
                var ro_2 = new ResizeObserverFallback(function(entry) {
                    callback(entry);
                });
                ro_2.observe(element);
                return function unobserve() {
                    ro_2.disconnect();
                };
            }
        }
        exports.observeResize = observeResize;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var context_1 = __webpack_require__(0);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var RowContainerComponent = function() {
            function RowContainerComponent(params) {
                this.childCount = 0;
                this.rowTemplatesToAdd = [];
                this.afterGuiAttachedCallbacks = [];
                this.eContainer = params.eContainer;
                this.eViewport = params.eViewport;
                this.hideWhenNoChildren = params.hideWhenNoChildren;
            }
            RowContainerComponent.prototype.setVerticalScrollPosition = function(verticalScrollPosition) {
                this.scrollTop = verticalScrollPosition;
            };
            RowContainerComponent.prototype.postConstruct = function() {
                this.domOrder = this.gridOptionsWrapper.isEnsureDomOrder();
                this.checkVisibility();
            };
            RowContainerComponent.prototype.getRowElement = function(compId) {
                return this.eContainer.querySelector('[comp-id="' + compId + '"]');
            };
            RowContainerComponent.prototype.setHeight = function(height) {
                this.eContainer.style.height = height + "px";
            };
            RowContainerComponent.prototype.flushRowTemplates = function() {
                if (this.rowTemplatesToAdd.length !== 0) {
                    var htmlToAdd = this.rowTemplatesToAdd.join("");
                    utils_1.Utils.appendHtml(this.eContainer, htmlToAdd);
                    this.rowTemplatesToAdd.length = 0;
                }
                this.afterGuiAttachedCallbacks.forEach(function(func) {
                    return func();
                });
                this.afterGuiAttachedCallbacks.length = 0;
                this.lastPlacedElement = null;
            };
            RowContainerComponent.prototype.appendRowTemplate = function(rowTemplate, callback) {
                if (this.domOrder) {
                    this.lastPlacedElement = utils_1.Utils.insertTemplateWithDomOrder(this.eContainer, rowTemplate, this.lastPlacedElement);
                } else {
                    this.rowTemplatesToAdd.push(rowTemplate);
                }
                this.afterGuiAttachedCallbacks.push(callback);
                this.childCount++;
                this.checkVisibility();
            };
            RowContainerComponent.prototype.ensureDomOrder = function(eRow) {
                if (this.domOrder) {
                    utils_1.Utils.ensureDomOrder(this.eContainer, eRow, this.lastPlacedElement);
                    this.lastPlacedElement = eRow;
                }
            };
            RowContainerComponent.prototype.removeRowElement = function(eRow) {
                this.eContainer.removeChild(eRow);
                this.childCount--;
                this.checkVisibility();
            };
            RowContainerComponent.prototype.checkVisibility = function() {
                if (!this.hideWhenNoChildren) {
                    return;
                }
                var eGui = this.eViewport ? this.eViewport : this.eContainer;
                var visible = this.childCount > 0;
                if (this.visible !== visible) {
                    this.visible = visible;
                    utils_1.Utils.setVisible(eGui, visible);
                    if (visible && this.eViewport) {
                        this.eViewport.scrollTop = this.scrollTop;
                    }
                }
            };
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], RowContainerComponent.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], RowContainerComponent.prototype, "postConstruct", null);
            return RowContainerComponent;
        }();
        exports.RowContainerComponent = RowContainerComponent;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var dragAndDropService_1 = __webpack_require__(15);
        var context_1 = __webpack_require__(0);
        var focusedCellController_1 = __webpack_require__(22);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var eventService_1 = __webpack_require__(3);
        var eventKeys_1 = __webpack_require__(25);
        var RowDragFeature = function() {
            function RowDragFeature(eContainer, gridPanel) {
                this.eContainer = eContainer;
                this.gridPanel = gridPanel;
            }
            RowDragFeature.prototype.postConstruct = function() {
                if (this.gridOptionsWrapper.isRowModelDefault()) {
                    this.clientSideRowModel = this.rowModel;
                }
            };
            RowDragFeature.prototype.getContainer = function() {
                return this.eContainer;
            };
            RowDragFeature.prototype.isInterestedIn = function(type) {
                return type === dragAndDropService_1.DragSourceType.RowDrag;
            };
            RowDragFeature.prototype.getIconName = function() {
                return dragAndDropService_1.DragAndDropService.ICON_MOVE;
            };
            RowDragFeature.prototype.onDragEnter = function(draggingEvent) {
                this.dispatchEvent(eventKeys_1.Events.EVENT_ROW_DRAG_ENTER, draggingEvent);
                this.dragAndDropService.setGhostIcon(dragAndDropService_1.DragAndDropService.ICON_MOVE);
                draggingEvent.dragItem.rowNode.setDragging(true);
                this.onEnterOrDragging(draggingEvent);
            };
            RowDragFeature.prototype.onDragging = function(draggingEvent) {
                this.onEnterOrDragging(draggingEvent);
            };
            RowDragFeature.prototype.onEnterOrDragging = function(draggingEvent) {
                this.dispatchEvent(eventKeys_1.Events.EVENT_ROW_DRAG_MOVE, draggingEvent);
                this.lastDraggingEvent = draggingEvent;
                var pixel = this.normaliseForScroll(draggingEvent.y);
                var managedDrag = this.gridOptionsWrapper.isRowDragManaged();
                if (managedDrag) {
                    this.doManagedDrag(draggingEvent, pixel);
                }
                this.checkCenterForScrolling(pixel);
            };
            RowDragFeature.prototype.doManagedDrag = function(draggingEvent, pixel) {
                var rowNode = draggingEvent.dragItem.rowNode;
                var rowWasMoved = this.clientSideRowModel.ensureRowAtPixel(rowNode, pixel);
                if (rowWasMoved) {
                    this.focusedCellController.clearFocusedCell();
                    if (this.rangeController) {
                        this.rangeController.clearSelection();
                    }
                }
            };
            RowDragFeature.prototype.normaliseForScroll = function(pixel) {
                var gridPanelHasScrolls = !this.gridOptionsWrapper.isGridAutoHeight();
                if (gridPanelHasScrolls) {
                    var pixelRange = this.gridPanel.getVScrollPosition();
                    return pixel + pixelRange.top;
                } else {
                    return pixel;
                }
            };
            RowDragFeature.prototype.checkCenterForScrolling = function(pixel) {
                var pixelRange = this.gridPanel.getVScrollPosition();
                this.needToMoveUp = pixel < pixelRange.top + 50;
                this.needToMoveDown = pixel > pixelRange.bottom - 50;
                if (this.needToMoveUp || this.needToMoveDown) {
                    this.ensureIntervalStarted();
                } else {
                    this.ensureIntervalCleared();
                }
            };
            RowDragFeature.prototype.ensureIntervalStarted = function() {
                if (!this.movingIntervalId) {
                    this.intervalCount = 0;
                    this.movingIntervalId = setInterval(this.moveInterval.bind(this), 100);
                }
            };
            RowDragFeature.prototype.ensureIntervalCleared = function() {
                if (this.moveInterval) {
                    clearInterval(this.movingIntervalId);
                    this.movingIntervalId = null;
                }
            };
            RowDragFeature.prototype.moveInterval = function() {
                var pixelsToMove;
                this.intervalCount++;
                pixelsToMove = 10 + this.intervalCount * 5;
                if (pixelsToMove > 100) {
                    pixelsToMove = 100;
                }
                var pixelsMoved;
                if (this.needToMoveDown) {
                    pixelsMoved = this.gridPanel.scrollVertically(pixelsToMove);
                } else if (this.needToMoveUp) {
                    pixelsMoved = this.gridPanel.scrollVertically(-pixelsToMove);
                }
                if (pixelsMoved !== 0) {
                    this.onDragging(this.lastDraggingEvent);
                }
            };
            RowDragFeature.prototype.dispatchEvent = function(type, draggingEvent) {
                var yNormalised = this.normaliseForScroll(draggingEvent.y);
                var overIndex = -1;
                var overNode = null;
                var mouseIsPastLastRow = yNormalised > this.rowModel.getCurrentPageHeight();
                if (!mouseIsPastLastRow) {
                    overIndex = this.rowModel.getRowIndexAtPixel(yNormalised);
                    overNode = this.rowModel.getRow(overIndex);
                }
                var vDirectionString;
                switch (draggingEvent.vDirection) {
                  case dragAndDropService_1.VDirection.Down:
                    vDirectionString = "down";
                    break;

                  case dragAndDropService_1.VDirection.Up:
                    vDirectionString = "up";
                    break;

                  default:
                    vDirectionString = null;
                    break;
                }
                var event = {
                    type: type,
                    api: this.gridOptionsWrapper.getApi(),
                    columnApi: this.gridOptionsWrapper.getColumnApi(),
                    event: draggingEvent.event,
                    node: draggingEvent.dragItem.rowNode,
                    overIndex: overIndex,
                    overNode: overNode,
                    y: yNormalised,
                    vDirection: vDirectionString
                };
                this.eventService.dispatchEvent(event);
            };
            RowDragFeature.prototype.onDragLeave = function(draggingEvent) {
                this.dispatchEvent(eventKeys_1.Events.EVENT_ROW_DRAG_LEAVE, draggingEvent);
                this.stopDragging(draggingEvent);
            };
            RowDragFeature.prototype.onDragStop = function(draggingEvent) {
                this.dispatchEvent(eventKeys_1.Events.EVENT_ROW_DRAG_END, draggingEvent);
                this.stopDragging(draggingEvent);
            };
            RowDragFeature.prototype.stopDragging = function(draggingEvent) {
                this.ensureIntervalCleared();
                draggingEvent.dragItem.rowNode.setDragging(false);
            };
            __decorate([ context_1.Autowired("dragAndDropService"), __metadata("design:type", dragAndDropService_1.DragAndDropService) ], RowDragFeature.prototype, "dragAndDropService", void 0);
            __decorate([ context_1.Autowired("rowModel"), __metadata("design:type", Object) ], RowDragFeature.prototype, "rowModel", void 0);
            __decorate([ context_1.Autowired("focusedCellController"), __metadata("design:type", focusedCellController_1.FocusedCellController) ], RowDragFeature.prototype, "focusedCellController", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], RowDragFeature.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Optional("rangeController"), __metadata("design:type", Object) ], RowDragFeature.prototype, "rangeController", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], RowDragFeature.prototype, "eventService", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], RowDragFeature.prototype, "postConstruct", null);
            return RowDragFeature;
        }();
        exports.RowDragFeature = RowDragFeature;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var agCheckbox_1 = __webpack_require__(60);
        var beanStub_1 = __webpack_require__(13);
        var context_1 = __webpack_require__(0);
        var columnApi_1 = __webpack_require__(7);
        var gridApi_1 = __webpack_require__(6);
        var events_1 = __webpack_require__(5);
        var eventService_1 = __webpack_require__(3);
        var constants_1 = __webpack_require__(9);
        var selectionController_1 = __webpack_require__(17);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var SelectAllFeature = function(_super) {
            __extends(SelectAllFeature, _super);
            function SelectAllFeature(cbSelectAll, column) {
                var _this = _super.call(this) || this;
                _this.cbSelectAllVisible = false;
                _this.processingEventFromCheckbox = false;
                _this.cbSelectAll = cbSelectAll;
                _this.column = column;
                var colDef = column.getColDef();
                _this.filteredOnly = colDef ? !!colDef.headerCheckboxSelectionFilteredOnly : false;
                return _this;
            }
            SelectAllFeature.prototype.postConstruct = function() {
                this.showOrHideSelectAll();
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_DISPLAYED_COLUMNS_CHANGED, this.showOrHideSelectAll.bind(this));
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_SELECTION_CHANGED, this.onSelectionChanged.bind(this));
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_MODEL_UPDATED, this.onModelChanged.bind(this));
                this.addDestroyableEventListener(this.cbSelectAll, agCheckbox_1.AgCheckbox.EVENT_CHANGED, this.onCbSelectAll.bind(this));
            };
            SelectAllFeature.prototype.showOrHideSelectAll = function() {
                this.cbSelectAllVisible = this.isCheckboxSelection();
                this.cbSelectAll.setVisible(this.cbSelectAllVisible);
                if (this.cbSelectAllVisible) {
                    this.checkRightRowModelType();
                    this.updateStateOfCheckbox();
                }
            };
            SelectAllFeature.prototype.onModelChanged = function() {
                if (!this.cbSelectAllVisible) {
                    return;
                }
                this.updateStateOfCheckbox();
            };
            SelectAllFeature.prototype.onSelectionChanged = function() {
                if (!this.cbSelectAllVisible) {
                    return;
                }
                this.updateStateOfCheckbox();
            };
            SelectAllFeature.prototype.getNextCheckboxState = function(selectionCount) {
                if (selectionCount.selected === 0 && selectionCount.notSelected === 0) {
                    return false;
                } else if (selectionCount.selected > 0 && selectionCount.notSelected > 0) {
                    return null;
                } else if (selectionCount.selected > 0) {
                    return true;
                } else {
                    return false;
                }
            };
            SelectAllFeature.prototype.updateStateOfCheckbox = function() {
                if (this.processingEventFromCheckbox) {
                    return;
                }
                this.processingEventFromCheckbox = true;
                var selectionCount = this.getSelectionCount();
                var allSelected = this.getNextCheckboxState(selectionCount);
                this.cbSelectAll.setSelected(allSelected);
                this.processingEventFromCheckbox = false;
            };
            SelectAllFeature.prototype.getSelectionCount = function() {
                var selectedCount = 0;
                var notSelectedCount = 0;
                var callback = function(node) {
                    if (node.isSelected()) {
                        selectedCount++;
                    } else if (!node.selectable) {} else {
                        notSelectedCount++;
                    }
                };
                if (this.filteredOnly) {
                    this.gridApi.forEachNodeAfterFilter(callback);
                } else {
                    this.gridApi.forEachNode(callback);
                }
                return {
                    notSelected: notSelectedCount,
                    selected: selectedCount
                };
            };
            SelectAllFeature.prototype.checkRightRowModelType = function() {
                var rowModelType = this.rowModel.getType();
                var rowModelMatches = rowModelType === constants_1.Constants.ROW_MODEL_TYPE_CLIENT_SIDE;
                if (!rowModelMatches) {
                    console.log("ag-Grid: selectAllCheckbox is only available if using normal row model, you are using " + rowModelType);
                }
            };
            SelectAllFeature.prototype.onCbSelectAll = function() {
                if (this.processingEventFromCheckbox) {
                    return;
                }
                if (!this.cbSelectAllVisible) {
                    return;
                }
                var value = this.cbSelectAll.isSelected();
                if (value) {
                    this.selectionController.selectAllRowNodes(this.filteredOnly);
                } else {
                    this.selectionController.deselectAllRowNodes(this.filteredOnly);
                }
            };
            SelectAllFeature.prototype.isCheckboxSelection = function() {
                var result = this.column.getColDef().headerCheckboxSelection;
                if (typeof result === "function") {
                    var func = result;
                    result = func({
                        column: this.column,
                        colDef: this.column.getColDef(),
                        columnApi: this.columnApi,
                        api: this.gridApi
                    });
                }
                if (result) {
                    if (this.gridOptionsWrapper.isRowModelServerSide()) {
                        console.warn("headerCheckboxSelection is not supported for Server Side Row Model");
                        return false;
                    }
                    if (this.gridOptionsWrapper.isRowModelInfinite()) {
                        console.warn("headerCheckboxSelection is not supported for Infinite Row Model");
                        return false;
                    }
                    if (this.gridOptionsWrapper.isRowModelViewport()) {
                        console.warn("headerCheckboxSelection is not supported for Viewport Row Model");
                        return false;
                    }
                    return true;
                } else {
                    return false;
                }
            };
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], SelectAllFeature.prototype, "gridApi", void 0);
            __decorate([ context_1.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], SelectAllFeature.prototype, "columnApi", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], SelectAllFeature.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("rowModel"), __metadata("design:type", Object) ], SelectAllFeature.prototype, "rowModel", void 0);
            __decorate([ context_1.Autowired("selectionController"), __metadata("design:type", selectionController_1.SelectionController) ], SelectAllFeature.prototype, "selectionController", void 0);
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], SelectAllFeature.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], SelectAllFeature.prototype, "postConstruct", null);
            return SelectAllFeature;
        }(beanStub_1.BeanStub);
        exports.SelectAllFeature = SelectAllFeature;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var component_1 = __webpack_require__(8);
        var column_1 = __webpack_require__(10);
        var utils_1 = __webpack_require__(1);
        var columnGroup_1 = __webpack_require__(26);
        var columnApi_1 = __webpack_require__(7);
        var columnController_1 = __webpack_require__(4);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var horizontalResizeService_1 = __webpack_require__(59);
        var context_1 = __webpack_require__(0);
        var cssClassApplier_1 = __webpack_require__(81);
        var dragAndDropService_1 = __webpack_require__(15);
        var setLeftFeature_1 = __webpack_require__(52);
        var gridApi_1 = __webpack_require__(6);
        var componentRecipes_1 = __webpack_require__(21);
        var beans_1 = __webpack_require__(28);
        var hoverFeature_1 = __webpack_require__(74);
        var HeaderGroupWrapperComp = function(_super) {
            __extends(HeaderGroupWrapperComp, _super);
            function HeaderGroupWrapperComp(columnGroup, dragSourceDropTarget, pinned) {
                var _this = _super.call(this, HeaderGroupWrapperComp.TEMPLATE) || this;
                _this.childColumnsDestroyFuncs = [];
                _this.columnGroup = columnGroup;
                _this.dragSourceDropTarget = dragSourceDropTarget;
                _this.pinned = pinned;
                return _this;
            }
            HeaderGroupWrapperComp.prototype.postConstruct = function() {
                cssClassApplier_1.CssClassApplier.addHeaderClassesFromColDef(this.columnGroup.getColGroupDef(), this.getGui(), this.gridOptionsWrapper, null, this.columnGroup);
                var displayName = this.columnController.getDisplayNameForColumnGroup(this.columnGroup, "header");
                this.appendHeaderGroupComp(displayName);
                this.setupResize();
                this.addClasses();
                this.setupWidth();
                this.addAttributes();
                this.setupMovingCss();
                this.setupTooltip();
                this.addFeature(this.context, new hoverFeature_1.HoverFeature(this.columnGroup.getOriginalColumnGroup().getLeafColumns(), this.getGui()));
                var setLeftFeature = new setLeftFeature_1.SetLeftFeature(this.columnGroup, this.getGui(), this.beans);
                setLeftFeature.init();
                this.addDestroyFunc(setLeftFeature.destroy.bind(setLeftFeature));
            };
            HeaderGroupWrapperComp.prototype.setupMovingCss = function() {
                var _this = this;
                var originalColumnGroup = this.columnGroup.getOriginalColumnGroup();
                var leafColumns = originalColumnGroup.getLeafColumns();
                leafColumns.forEach(function(col) {
                    _this.addDestroyableEventListener(col, column_1.Column.EVENT_MOVING_CHANGED, _this.onColumnMovingChanged.bind(_this));
                });
                this.onColumnMovingChanged();
            };
            HeaderGroupWrapperComp.prototype.setupTooltip = function() {
                var colGroupDef = this.columnGroup.getColGroupDef();
                if (colGroupDef && colGroupDef.headerTooltip) {
                    this.getGui().title = colGroupDef.headerTooltip;
                }
            };
            HeaderGroupWrapperComp.prototype.onColumnMovingChanged = function() {
                if (this.columnGroup.isMoving()) {
                    utils_1.Utils.addCssClass(this.getGui(), "ag-header-cell-moving");
                } else {
                    utils_1.Utils.removeCssClass(this.getGui(), "ag-header-cell-moving");
                }
            };
            HeaderGroupWrapperComp.prototype.addAttributes = function() {
                this.getGui().setAttribute("col-id", this.columnGroup.getUniqueId());
            };
            HeaderGroupWrapperComp.prototype.appendHeaderGroupComp = function(displayName) {
                var _this = this;
                var params = {
                    displayName: displayName,
                    columnGroup: this.columnGroup,
                    setExpanded: function(expanded) {
                        _this.columnController.setColumnGroupOpened(_this.columnGroup.getOriginalColumnGroup(), expanded, "gridInitializing");
                    },
                    api: this.gridApi,
                    columnApi: this.columnApi,
                    context: this.gridOptionsWrapper.getContext()
                };
                if (!displayName) {
                    var leafCols = this.columnGroup.getLeafColumns();
                    displayName = leafCols ? leafCols[0].getColDef().headerName : "";
                }
                var callback = this.afterHeaderCompCreated.bind(this, displayName);
                this.componentRecipes.newHeaderGroupComponent(params).then(callback);
            };
            HeaderGroupWrapperComp.prototype.afterHeaderCompCreated = function(displayName, headerGroupComp) {
                this.appendChild(headerGroupComp);
                this.setupMove(headerGroupComp.getGui(), displayName);
                if (headerGroupComp.destroy) {
                    this.addDestroyFunc(headerGroupComp.destroy.bind(headerGroupComp));
                }
            };
            HeaderGroupWrapperComp.prototype.addClasses = function() {
                if (this.columnGroup.isPadding()) {
                    this.addCssClass("ag-header-group-cell-no-group");
                } else {
                    this.addCssClass("ag-header-group-cell-with-group");
                }
            };
            HeaderGroupWrapperComp.prototype.setupMove = function(eHeaderGroup, displayName) {
                var _this = this;
                if (!eHeaderGroup) {
                    return;
                }
                if (this.isSuppressMoving()) {
                    return;
                }
                var allLeafColumns = this.columnGroup.getOriginalColumnGroup().getLeafColumns();
                if (eHeaderGroup) {
                    var dragSource_1 = {
                        type: dragAndDropService_1.DragSourceType.HeaderCell,
                        eElement: eHeaderGroup,
                        dragItemName: displayName,
                        dragItemCallback: this.getDragItemForGroup.bind(this),
                        dragSourceDropTarget: this.dragSourceDropTarget,
                        dragStarted: function() {
                            return allLeafColumns.forEach(function(col) {
                                return col.setMoving(true, "uiColumnDragged");
                            });
                        },
                        dragStopped: function() {
                            return allLeafColumns.forEach(function(col) {
                                return col.setMoving(false, "uiColumnDragged");
                            });
                        }
                    };
                    this.dragAndDropService.addDragSource(dragSource_1, true);
                    this.addDestroyFunc(function() {
                        return _this.dragAndDropService.removeDragSource(dragSource_1);
                    });
                }
            };
            HeaderGroupWrapperComp.prototype.getDragItemForGroup = function() {
                var allColumnsOriginalOrder = this.columnGroup.getOriginalColumnGroup().getLeafColumns();
                var visibleState = {};
                allColumnsOriginalOrder.forEach(function(column) {
                    return visibleState[column.getId()] = column.isVisible();
                });
                var allColumnsCurrentOrder = [];
                this.columnController.getAllDisplayedColumns().forEach(function(column) {
                    if (allColumnsOriginalOrder.indexOf(column) >= 0) {
                        allColumnsCurrentOrder.push(column);
                        utils_1.Utils.removeFromArray(allColumnsOriginalOrder, column);
                    }
                });
                allColumnsOriginalOrder.forEach(function(column) {
                    return allColumnsCurrentOrder.push(column);
                });
                return {
                    columns: allColumnsCurrentOrder,
                    visibleState: visibleState
                };
            };
            HeaderGroupWrapperComp.prototype.isSuppressMoving = function() {
                var childSuppressesMoving = false;
                this.columnGroup.getLeafColumns().forEach(function(column) {
                    if (column.getColDef().suppressMovable || column.isLockPosition()) {
                        childSuppressesMoving = true;
                    }
                });
                var result = childSuppressesMoving || this.gridOptionsWrapper.isSuppressMovableColumns();
                return result;
            };
            HeaderGroupWrapperComp.prototype.setupWidth = function() {
                this.addListenersToChildrenColumns();
                this.addDestroyableEventListener(this.columnGroup, columnGroup_1.ColumnGroup.EVENT_DISPLAYED_CHILDREN_CHANGED, this.onDisplayedChildrenChanged.bind(this));
                this.onWidthChanged();
                this.addDestroyFunc(this.destroyListenersOnChildrenColumns.bind(this));
            };
            HeaderGroupWrapperComp.prototype.onDisplayedChildrenChanged = function() {
                this.addListenersToChildrenColumns();
                this.onWidthChanged();
            };
            HeaderGroupWrapperComp.prototype.addListenersToChildrenColumns = function() {
                var _this = this;
                this.destroyListenersOnChildrenColumns();
                var widthChangedListener = this.onWidthChanged.bind(this);
                this.columnGroup.getLeafColumns().forEach(function(column) {
                    column.addEventListener(column_1.Column.EVENT_WIDTH_CHANGED, widthChangedListener);
                    column.addEventListener(column_1.Column.EVENT_VISIBLE_CHANGED, widthChangedListener);
                    _this.childColumnsDestroyFuncs.push(function() {
                        column.removeEventListener(column_1.Column.EVENT_WIDTH_CHANGED, widthChangedListener);
                        column.removeEventListener(column_1.Column.EVENT_VISIBLE_CHANGED, widthChangedListener);
                    });
                });
            };
            HeaderGroupWrapperComp.prototype.destroyListenersOnChildrenColumns = function() {
                this.childColumnsDestroyFuncs.forEach(function(func) {
                    return func();
                });
                this.childColumnsDestroyFuncs = [];
            };
            HeaderGroupWrapperComp.prototype.onWidthChanged = function() {
                this.getGui().style.width = this.columnGroup.getActualWidth() + "px";
            };
            HeaderGroupWrapperComp.prototype.setupResize = function() {
                var _this = this;
                this.eHeaderCellResize = this.getRefElement("agResize");
                if (!this.columnGroup.isResizable()) {
                    utils_1.Utils.removeFromParent(this.eHeaderCellResize);
                    return;
                }
                var finishedWithResizeFunc = this.horizontalResizeService.addResizeBar({
                    eResizeBar: this.eHeaderCellResize,
                    onResizeStart: this.onResizeStart.bind(this),
                    onResizing: this.onResizing.bind(this, false),
                    onResizeEnd: this.onResizing.bind(this, true)
                });
                this.addDestroyFunc(finishedWithResizeFunc);
                if (!this.gridOptionsWrapper.isSuppressAutoSize()) {
                    this.eHeaderCellResize.addEventListener("dblclick", function(event) {
                        var keys = [];
                        _this.columnGroup.getDisplayedLeafColumns().forEach(function(column) {
                            if (!column.getColDef().suppressAutoSize) {
                                keys.push(column.getColId());
                            }
                        });
                        if (keys.length > 0) {
                            _this.columnController.autoSizeColumns(keys, "uiColumnResized");
                        }
                    });
                }
            };
            HeaderGroupWrapperComp.prototype.onResizeStart = function(shiftKey) {
                var _this = this;
                var leafCols = this.columnGroup.getDisplayedLeafColumns();
                this.resizeCols = utils_1.Utils.filter(leafCols, function(col) {
                    return col.isResizable();
                });
                this.resizeStartWidth = 0;
                this.resizeCols.forEach(function(col) {
                    return _this.resizeStartWidth += col.getActualWidth();
                });
                this.resizeRatios = [];
                this.resizeCols.forEach(function(col) {
                    return _this.resizeRatios.push(col.getActualWidth() / _this.resizeStartWidth);
                });
                var takeFromGroup = null;
                if (shiftKey) {
                    takeFromGroup = this.columnController.getDisplayedGroupAfter(this.columnGroup);
                }
                if (takeFromGroup) {
                    var takeFromLeafCols = takeFromGroup.getDisplayedLeafColumns();
                    this.resizeTakeFromCols = utils_1.Utils.filter(takeFromLeafCols, function(col) {
                        return col.isResizable();
                    });
                    this.resizeTakeFromStartWidth = 0;
                    this.resizeTakeFromCols.forEach(function(col) {
                        return _this.resizeTakeFromStartWidth += col.getActualWidth();
                    });
                    this.resizeTakeFromRatios = [];
                    this.resizeTakeFromCols.forEach(function(col) {
                        return _this.resizeTakeFromRatios.push(col.getActualWidth() / _this.resizeTakeFromStartWidth);
                    });
                } else {
                    this.resizeTakeFromCols = null;
                    this.resizeTakeFromStartWidth = null;
                    this.resizeTakeFromRatios = null;
                }
            };
            HeaderGroupWrapperComp.prototype.onResizing = function(finished, resizeAmount) {
                var resizeSets = [];
                var resizeAmountNormalised = this.normaliseDragChange(resizeAmount);
                resizeSets.push({
                    columns: this.resizeCols,
                    ratios: this.resizeRatios,
                    width: this.resizeStartWidth + resizeAmountNormalised
                });
                if (this.resizeTakeFromCols) {
                    resizeSets.push({
                        columns: this.resizeTakeFromCols,
                        ratios: this.resizeTakeFromRatios,
                        width: this.resizeTakeFromStartWidth - resizeAmountNormalised
                    });
                }
                this.columnController.resizeColumnSets(resizeSets, finished, "uiColumnDragged");
            };
            HeaderGroupWrapperComp.prototype.normaliseDragChange = function(dragChange) {
                var result = dragChange;
                if (this.gridOptionsWrapper.isEnableRtl()) {
                    if (this.pinned !== column_1.Column.PINNED_LEFT) {
                        result *= -1;
                    }
                } else {
                    if (this.pinned === column_1.Column.PINNED_RIGHT) {
                        result *= -1;
                    }
                }
                return result;
            };
            HeaderGroupWrapperComp.TEMPLATE = '<div class="ag-header-group-cell">' + '<div ref="agResize" class="ag-header-cell-resize"></div>' + "</div>";
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], HeaderGroupWrapperComp.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], HeaderGroupWrapperComp.prototype, "columnController", void 0);
            __decorate([ context_1.Autowired("horizontalResizeService"), __metadata("design:type", horizontalResizeService_1.HorizontalResizeService) ], HeaderGroupWrapperComp.prototype, "horizontalResizeService", void 0);
            __decorate([ context_1.Autowired("dragAndDropService"), __metadata("design:type", dragAndDropService_1.DragAndDropService) ], HeaderGroupWrapperComp.prototype, "dragAndDropService", void 0);
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], HeaderGroupWrapperComp.prototype, "context", void 0);
            __decorate([ context_1.Autowired("componentRecipes"), __metadata("design:type", componentRecipes_1.ComponentRecipes) ], HeaderGroupWrapperComp.prototype, "componentRecipes", void 0);
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], HeaderGroupWrapperComp.prototype, "gridApi", void 0);
            __decorate([ context_1.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], HeaderGroupWrapperComp.prototype, "columnApi", void 0);
            __decorate([ context_1.Autowired("beans"), __metadata("design:type", beans_1.Beans) ], HeaderGroupWrapperComp.prototype, "beans", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], HeaderGroupWrapperComp.prototype, "postConstruct", null);
            return HeaderGroupWrapperComp;
        }(component_1.Component);
        exports.HeaderGroupWrapperComp = HeaderGroupWrapperComp;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        exports.DefaultColumnTypes = {
            numericColumn: {
                headerClass: "ag-numeric-header",
                cellClass: "ag-numeric-cell"
            }
        };
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var grid_1 = __webpack_require__(85);
        function initialiseAgGridWithAngular1(angular) {
            var angularModule = angular.module("agGrid", []);
            angularModule.directive("agGrid", function() {
                return {
                    restrict: "A",
                    controller: [ "$element", "$scope", "$compile", "$attrs", AngularDirectiveController ],
                    scope: true
                };
            });
        }
        exports.initialiseAgGridWithAngular1 = initialiseAgGridWithAngular1;
        function AngularDirectiveController($element, $scope, $compile, $attrs) {
            var gridOptions;
            var quickFilterOnScope;
            var keyOfGridInScope = $attrs.agGrid;
            quickFilterOnScope = keyOfGridInScope + ".quickFilterText";
            gridOptions = $scope.$eval(keyOfGridInScope);
            if (!gridOptions) {
                console.warn("WARNING - grid options for ag-Grid not found. Please ensure the attribute ag-grid points to a valid object on the scope");
                return;
            }
            var eGridDiv = $element[0];
            var gridParams = {
                $scope: $scope,
                $compile: $compile,
                quickFilterOnScope: quickFilterOnScope
            };
            var grid = new grid_1.Grid(eGridDiv, gridOptions, gridParams);
            $scope.$on("$destroy", function() {
                grid.destroy();
                grid = null;
            });
        }
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        var __param = this && this.__param || function(paramIndex, decorator) {
            return function(target, key) {
                decorator(target, key, paramIndex);
            };
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var eventService_1 = __webpack_require__(3);
        var events_1 = __webpack_require__(5);
        var logger_1 = __webpack_require__(12);
        var infiniteBlock_1 = __webpack_require__(137);
        var rowNodeCache_1 = __webpack_require__(87);
        var gridApi_1 = __webpack_require__(6);
        var columnApi_1 = __webpack_require__(7);
        var InfiniteCache = function(_super) {
            __extends(InfiniteCache, _super);
            function InfiniteCache(params) {
                return _super.call(this, params) || this;
            }
            InfiniteCache.prototype.setBeans = function(loggerFactory) {
                this.logger = loggerFactory.create("InfiniteCache");
            };
            InfiniteCache.prototype.init = function() {
                _super.prototype.init.call(this);
                this.getRow(0);
            };
            InfiniteCache.prototype.moveItemsDown = function(block, moveFromIndex, moveCount) {
                var startRow = block.getStartRow();
                var endRow = block.getEndRow();
                var indexOfLastRowToMove = moveFromIndex + moveCount;
                for (var currentRowIndex = endRow - 1; currentRowIndex >= startRow; currentRowIndex--) {
                    if (currentRowIndex < indexOfLastRowToMove) {
                        continue;
                    }
                    var indexOfNodeWeWant = currentRowIndex - moveCount;
                    var nodeForThisIndex = this.getRow(indexOfNodeWeWant, true);
                    if (nodeForThisIndex) {
                        block.setRowNode(currentRowIndex, nodeForThisIndex);
                    } else {
                        block.setBlankRowNode(currentRowIndex);
                        block.setDirty();
                    }
                }
            };
            InfiniteCache.prototype.insertItems = function(block, indexToInsert, items) {
                var pageStartRow = block.getStartRow();
                var pageEndRow = block.getEndRow();
                var newRowNodes = [];
                for (var index = 0; index < items.length; index++) {
                    var rowIndex = indexToInsert + index;
                    var currentRowInThisPage = rowIndex >= pageStartRow && rowIndex < pageEndRow;
                    if (currentRowInThisPage) {
                        var dataItem = items[index];
                        var newRowNode = block.setNewData(rowIndex, dataItem);
                        newRowNodes.push(newRowNode);
                    }
                }
                return newRowNodes;
            };
            InfiniteCache.prototype.insertItemsAtIndex = function(indexToInsert, items) {
                var _this = this;
                var newNodes = [];
                this.forEachBlockInReverseOrder(function(block) {
                    var pageEndRow = block.getEndRow();
                    if (pageEndRow <= indexToInsert) {
                        return;
                    }
                    _this.moveItemsDown(block, indexToInsert, items.length);
                    var newNodesThisPage = _this.insertItems(block, indexToInsert, items);
                    newNodesThisPage.forEach(function(rowNode) {
                        return newNodes.push(rowNode);
                    });
                });
                if (this.isMaxRowFound()) {
                    this.hack_setVirtualRowCount(this.getVirtualRowCount() + items.length);
                }
                this.onCacheUpdated();
                var event = {
                    type: events_1.Events.EVENT_ROW_DATA_UPDATED,
                    api: this.gridApi,
                    columnApi: this.columnApi
                };
                this.eventService.dispatchEvent(event);
            };
            InfiniteCache.prototype.getRow = function(rowIndex, dontCreatePage) {
                if (dontCreatePage === void 0) {
                    dontCreatePage = false;
                }
                var blockId = Math.floor(rowIndex / this.cacheParams.blockSize);
                var block = this.getBlock(blockId);
                if (!block) {
                    if (dontCreatePage) {
                        return null;
                    } else {
                        block = this.createBlock(blockId);
                    }
                }
                return block.getRow(rowIndex);
            };
            InfiniteCache.prototype.createBlock = function(blockNumber) {
                var newBlock = new infiniteBlock_1.InfiniteBlock(blockNumber, this.cacheParams);
                this.context.wireBean(newBlock);
                this.postCreateBlock(newBlock);
                return newBlock;
            };
            InfiniteCache.prototype.refreshCache = function() {
                this.forEachBlockInOrder(function(block) {
                    return block.setDirty();
                });
                this.checkBlockToLoad();
            };
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], InfiniteCache.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], InfiniteCache.prototype, "context", void 0);
            __decorate([ context_1.Autowired("columnApi"), __metadata("design:type", columnApi_1.ColumnApi) ], InfiniteCache.prototype, "columnApi", void 0);
            __decorate([ context_1.Autowired("gridApi"), __metadata("design:type", gridApi_1.GridApi) ], InfiniteCache.prototype, "gridApi", void 0);
            __decorate([ __param(0, context_1.Qualifier("loggerFactory")), __metadata("design:type", Function), __metadata("design:paramtypes", [ logger_1.LoggerFactory ]), __metadata("design:returntype", void 0) ], InfiniteCache.prototype, "setBeans", null);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], InfiniteCache.prototype, "init", null);
            return InfiniteCache;
        }(rowNodeCache_1.RowNodeCache);
        exports.InfiniteCache = InfiniteCache;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var context_1 = __webpack_require__(0);
        var rowNodeBlock_1 = __webpack_require__(61);
        var rowRenderer_1 = __webpack_require__(20);
        var InfiniteBlock = function(_super) {
            __extends(InfiniteBlock, _super);
            function InfiniteBlock(pageNumber, params) {
                var _this = _super.call(this, pageNumber, params) || this;
                _this.cacheParams = params;
                return _this;
            }
            InfiniteBlock.prototype.createBlankRowNode = function(rowIndex) {
                var rowNode = _super.prototype.createBlankRowNode.call(this, rowIndex);
                rowNode.uiLevel = 0;
                this.setIndexAndTopOnRowNode(rowNode, rowIndex);
                return rowNode;
            };
            InfiniteBlock.prototype.setDataAndId = function(rowNode, data, index) {
                if (utils_1.Utils.exists(data)) {
                    rowNode.setDataAndId(data, index.toString());
                } else {
                    rowNode.setDataAndId(undefined, undefined);
                }
            };
            InfiniteBlock.prototype.setRowNode = function(rowIndex, rowNode) {
                _super.prototype.setRowNode.call(this, rowIndex, rowNode);
                this.setIndexAndTopOnRowNode(rowNode, rowIndex);
            };
            InfiniteBlock.prototype.init = function() {
                _super.prototype.init.call(this, {
                    context: this.context,
                    rowRenderer: this.rowRenderer
                });
            };
            InfiniteBlock.prototype.getNodeIdPrefix = function() {
                return null;
            };
            InfiniteBlock.prototype.getRow = function(displayIndex) {
                return this.getRowUsingLocalIndex(displayIndex);
            };
            InfiniteBlock.prototype.setIndexAndTopOnRowNode = function(rowNode, rowIndex) {
                rowNode.setRowIndex(rowIndex);
                rowNode.rowTop = this.cacheParams.rowHeight * rowIndex;
            };
            InfiniteBlock.prototype.loadFromDatasource = function() {
                var _this = this;
                var params = {
                    startRow: this.getStartRow(),
                    endRow: this.getEndRow(),
                    successCallback: this.pageLoaded.bind(this, this.getVersion()),
                    failCallback: this.pageLoadFailed.bind(this),
                    sortModel: this.cacheParams.sortModel,
                    filterModel: this.cacheParams.filterModel,
                    context: this.gridOptionsWrapper.getContext()
                };
                if (utils_1.Utils.missing(this.cacheParams.datasource.getRows)) {
                    console.warn("ag-Grid: datasource is missing getRows method");
                    return;
                }
                var getRowsParams = utils_1.Utils.getFunctionParameters(this.cacheParams.datasource.getRows);
                if (getRowsParams.length > 1) {
                    console.warn("ag-grid: It looks like your paging datasource is of the old type, taking more than one parameter.");
                    console.warn("ag-grid: From ag-grid 1.9.0, now the getRows takes one parameter. See the documentation for details.");
                }
                setTimeout(function() {
                    _this.cacheParams.datasource.getRows(params);
                }, 0);
            };
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], InfiniteBlock.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], InfiniteBlock.prototype, "context", void 0);
            __decorate([ context_1.Autowired("rowRenderer"), __metadata("design:type", rowRenderer_1.RowRenderer) ], InfiniteBlock.prototype, "rowRenderer", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], InfiniteBlock.prototype, "init", null);
            return InfiniteBlock;
        }(rowNodeBlock_1.RowNodeBlock);
        exports.InfiniteBlock = InfiniteBlock;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var rowNode_1 = __webpack_require__(14);
        var clientSideNodeManager_1 = __webpack_require__(88);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var eventService_1 = __webpack_require__(3);
        var context_1 = __webpack_require__(0);
        var columnController_1 = __webpack_require__(4);
        var RowNodeFactory = function() {
            function RowNodeFactory() {}
            RowNodeFactory.prototype.create = function(data) {
                var rootNode = new rowNode_1.RowNode();
                var nodeManager = new clientSideNodeManager_1.ClientSideNodeManager(rootNode, this.gridOptionsWrapper, this.context, this.eventService, this.columnController);
                this.context.wireBean(rootNode);
                nodeManager.setRowData(data);
                return rootNode;
            };
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], RowNodeFactory.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], RowNodeFactory.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("context"), __metadata("design:type", context_1.Context) ], RowNodeFactory.prototype, "context", void 0);
            __decorate([ context_1.Autowired("columnController"), __metadata("design:type", columnController_1.ColumnController) ], RowNodeFactory.prototype, "columnController", void 0);
            RowNodeFactory = __decorate([ context_1.Bean("rowNodeFactory") ], RowNodeFactory);
            return RowNodeFactory;
        }();
        exports.RowNodeFactory = RowNodeFactory;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var context_1 = __webpack_require__(0);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var changedPath_1 = __webpack_require__(89);
        var rowRenderer_1 = __webpack_require__(20);
        var eventService_1 = __webpack_require__(3);
        var constants_1 = __webpack_require__(9);
        var beanStub_1 = __webpack_require__(13);
        var events_1 = __webpack_require__(5);
        var ChangeDetectionService = function(_super) {
            __extends(ChangeDetectionService, _super);
            function ChangeDetectionService() {
                return _super !== null && _super.apply(this, arguments) || this;
            }
            ChangeDetectionService.prototype.init = function() {
                if (this.rowModel.getType() === constants_1.Constants.ROW_MODEL_TYPE_CLIENT_SIDE) {
                    this.clientSideRowModel = this.rowModel;
                }
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_CELL_VALUE_CHANGED, this.onCellValueChanged.bind(this));
            };
            ChangeDetectionService.prototype.onCellValueChanged = function(event) {
                this.doChangeDetection(event.node, event.column);
            };
            ChangeDetectionService.prototype.doChangeDetection = function(rowNode, column) {
                if (this.gridOptionsWrapper.isSuppressChangeDetection()) {
                    return;
                }
                if (this.clientSideRowModel && !rowNode.isRowPinned()) {
                    var onlyChangedColumns = this.gridOptionsWrapper.isAggregateOnlyChangedColumns();
                    var changedPath = new changedPath_1.ChangedPath(onlyChangedColumns);
                    changedPath.addParentNode(rowNode.parent, [ column ]);
                    this.clientSideRowModel.doAggregate(changedPath);
                }
                this.rowRenderer.refreshCells();
            };
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], ChangeDetectionService.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("rowModel"), __metadata("design:type", Object) ], ChangeDetectionService.prototype, "rowModel", void 0);
            __decorate([ context_1.Autowired("rowRenderer"), __metadata("design:type", rowRenderer_1.RowRenderer) ], ChangeDetectionService.prototype, "rowRenderer", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], ChangeDetectionService.prototype, "eventService", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], ChangeDetectionService.prototype, "init", null);
            ChangeDetectionService = __decorate([ context_1.Bean("changeDetectionService") ], ChangeDetectionService);
            return ChangeDetectionService;
        }(beanStub_1.BeanStub);
        exports.ChangeDetectionService = ChangeDetectionService;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        var __extends = this && this.__extends || function() {
            var extendStatics = Object.setPrototypeOf || {
                __proto__: []
            } instanceof Array && function(d, b) {
                d.__proto__ = b;
            } || function(d, b) {
                for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
            };
            return function(d, b) {
                extendStatics(d, b);
                function __() {
                    this.constructor = d;
                }
                d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, 
                new __());
            };
        }();
        var __decorate = this && this.__decorate || function(decorators, target, key, desc) {
            var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
            if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
            return c > 3 && r && Object.defineProperty(target, key, r), r;
        };
        var __metadata = this && this.__metadata || function(k, v) {
            if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
        };
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var component_1 = __webpack_require__(8);
        var context_1 = __webpack_require__(0);
        var gridOptionsWrapper_1 = __webpack_require__(2);
        var componentAnnotations_1 = __webpack_require__(11);
        var utils_1 = __webpack_require__(1);
        var eventService_1 = __webpack_require__(3);
        var events_1 = __webpack_require__(5);
        var rowRenderer_1 = __webpack_require__(20);
        var paginationProxy_1 = __webpack_require__(29);
        var PaginationComp = function(_super) {
            __extends(PaginationComp, _super);
            function PaginationComp() {
                return _super.call(this) || this;
            }
            PaginationComp.prototype.postConstruct = function() {
                this.setTemplate(this.getTemplate());
                var isPaging = this.gridOptionsWrapper.isPagination();
                var paginationPanelEnabled = isPaging && !this.gridOptionsWrapper.isSuppressPaginationPanel();
                if (!paginationPanelEnabled) {
                    this.setVisible(false);
                    return;
                }
                this.addDestroyableEventListener(this.eventService, events_1.Events.EVENT_PAGINATION_CHANGED, this.onPaginationChanged.bind(this));
                this.addDestroyableEventListener(this.btFirst, "click", this.onBtFirst.bind(this));
                this.addDestroyableEventListener(this.btLast, "click", this.onBtLast.bind(this));
                this.addDestroyableEventListener(this.btNext, "click", this.onBtNext.bind(this));
                this.addDestroyableEventListener(this.btPrevious, "click", this.onBtPrevious.bind(this));
                this.onPaginationChanged();
            };
            PaginationComp.prototype.onPaginationChanged = function() {
                this.enableOrDisableButtons();
                this.updateRowLabels();
                this.setCurrentPageLabel();
                this.setTotalLabels();
            };
            PaginationComp.prototype.setCurrentPageLabel = function() {
                var pagesExist = this.paginationProxy.getTotalPages() > 0;
                var currentPage = this.paginationProxy.getCurrentPage();
                var toDisplay = pagesExist ? currentPage + 1 : 0;
                this.lbCurrent.innerHTML = this.formatNumber(toDisplay);
            };
            PaginationComp.prototype.formatNumber = function(value) {
                var userFunc = this.gridOptionsWrapper.getPaginationNumberFormatterFunc();
                if (userFunc) {
                    return userFunc({
                        value: value
                    });
                } else {
                    return utils_1._.formatNumberCommas(value);
                }
            };
            PaginationComp.prototype.getTemplate = function() {
                var localeTextFunc = this.gridOptionsWrapper.getLocaleTextFunc();
                var strPage = localeTextFunc("page", "Page");
                var strTo = localeTextFunc("to", "to");
                var strOf = localeTextFunc("of", "of");
                var strFirst = localeTextFunc("first", "First");
                var strPrevious = localeTextFunc("previous", "Previous");
                var strNext = localeTextFunc("next", "Next");
                var strLast = localeTextFunc("last", "Last");
                return '<div class="ag-paging-panel ag-font-style">\n                <span ref="eSummaryPanel" class="ag-paging-row-summary-panel">\n                    <span ref="lbFirstRowOnPage"></span> ' + strTo + ' <span ref="lbLastRowOnPage"></span> ' + strOf + ' <span ref="lbRecordCount"></span>\n                </span>\n                <span class="ag-paging-page-summary-panel">\n                    <button type="button" class="ag-paging-button" ref="btFirst">' + strFirst + '</button>\n                    <button type="button" class="ag-paging-button" ref="btPrevious">' + strPrevious + "</button>\n                    " + strPage + ' <span ref="lbCurrent"></span> ' + strOf + ' <span ref="lbTotal"></span>\n                    <button type="button" class="ag-paging-button" ref="btNext">' + strNext + '</button>\n                    <button type="button" class="ag-paging-button" ref="btLast">' + strLast + "</button>\n                </span>\n            </div>";
            };
            PaginationComp.prototype.onBtNext = function() {
                this.paginationProxy.goToNextPage();
            };
            PaginationComp.prototype.onBtPrevious = function() {
                this.paginationProxy.goToPreviousPage();
            };
            PaginationComp.prototype.onBtFirst = function() {
                this.paginationProxy.goToFirstPage();
            };
            PaginationComp.prototype.onBtLast = function() {
                this.paginationProxy.goToLastPage();
            };
            PaginationComp.prototype.enableOrDisableButtons = function() {
                var currentPage = this.paginationProxy.getCurrentPage();
                var maxRowFound = this.paginationProxy.isLastPageFound();
                var totalPages = this.paginationProxy.getTotalPages();
                var disablePreviousAndFirst = currentPage === 0;
                this.btPrevious.disabled = disablePreviousAndFirst;
                this.btFirst.disabled = disablePreviousAndFirst;
                var zeroPagesToDisplay = this.isZeroPagesToDisplay();
                var onLastPage = maxRowFound && currentPage === totalPages - 1;
                var disableNext = onLastPage || zeroPagesToDisplay;
                this.btNext.disabled = disableNext;
                var disableLast = !maxRowFound || zeroPagesToDisplay || currentPage === totalPages - 1;
                this.btLast.disabled = disableLast;
            };
            PaginationComp.prototype.updateRowLabels = function() {
                var currentPage = this.paginationProxy.getCurrentPage();
                var pageSize = this.paginationProxy.getPageSize();
                var maxRowFound = this.paginationProxy.isLastPageFound();
                var rowCount = this.paginationProxy.isLastPageFound() ? this.paginationProxy.getTotalRowCount() : null;
                var startRow;
                var endRow;
                if (this.isZeroPagesToDisplay()) {
                    startRow = 0;
                    endRow = 0;
                } else {
                    startRow = pageSize * currentPage + 1;
                    endRow = startRow + pageSize - 1;
                    if (maxRowFound && endRow > rowCount) {
                        endRow = rowCount;
                    }
                }
                this.lbFirstRowOnPage.innerHTML = this.formatNumber(startRow);
                this.lbLastRowOnPage.innerHTML = this.formatNumber(endRow);
            };
            PaginationComp.prototype.isZeroPagesToDisplay = function() {
                var maxRowFound = this.paginationProxy.isLastPageFound();
                var totalPages = this.paginationProxy.getTotalPages();
                return maxRowFound && totalPages === 0;
            };
            PaginationComp.prototype.setTotalLabels = function() {
                var lastPageFound = this.paginationProxy.isLastPageFound();
                var totalPages = this.paginationProxy.getTotalPages();
                var rowCount = this.paginationProxy.isLastPageFound() ? this.paginationProxy.getTotalRowCount() : null;
                if (lastPageFound) {
                    this.lbTotal.innerHTML = this.formatNumber(totalPages);
                    this.lbRecordCount.innerHTML = this.formatNumber(rowCount);
                } else {
                    var moreText = this.gridOptionsWrapper.getLocaleTextFunc()("more", "more");
                    this.lbTotal.innerHTML = moreText;
                    this.lbRecordCount.innerHTML = moreText;
                }
            };
            __decorate([ context_1.Autowired("gridOptionsWrapper"), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], PaginationComp.prototype, "gridOptionsWrapper", void 0);
            __decorate([ context_1.Autowired("eventService"), __metadata("design:type", eventService_1.EventService) ], PaginationComp.prototype, "eventService", void 0);
            __decorate([ context_1.Autowired("paginationProxy"), __metadata("design:type", paginationProxy_1.PaginationProxy) ], PaginationComp.prototype, "paginationProxy", void 0);
            __decorate([ context_1.Autowired("rowRenderer"), __metadata("design:type", rowRenderer_1.RowRenderer) ], PaginationComp.prototype, "rowRenderer", void 0);
            __decorate([ componentAnnotations_1.RefSelector("btFirst"), __metadata("design:type", HTMLButtonElement) ], PaginationComp.prototype, "btFirst", void 0);
            __decorate([ componentAnnotations_1.RefSelector("btPrevious"), __metadata("design:type", HTMLButtonElement) ], PaginationComp.prototype, "btPrevious", void 0);
            __decorate([ componentAnnotations_1.RefSelector("btNext"), __metadata("design:type", HTMLButtonElement) ], PaginationComp.prototype, "btNext", void 0);
            __decorate([ componentAnnotations_1.RefSelector("btLast"), __metadata("design:type", HTMLButtonElement) ], PaginationComp.prototype, "btLast", void 0);
            __decorate([ componentAnnotations_1.RefSelector("lbRecordCount"), __metadata("design:type", Object) ], PaginationComp.prototype, "lbRecordCount", void 0);
            __decorate([ componentAnnotations_1.RefSelector("lbFirstRowOnPage"), __metadata("design:type", Object) ], PaginationComp.prototype, "lbFirstRowOnPage", void 0);
            __decorate([ componentAnnotations_1.RefSelector("lbLastRowOnPage"), __metadata("design:type", Object) ], PaginationComp.prototype, "lbLastRowOnPage", void 0);
            __decorate([ componentAnnotations_1.RefSelector("eSummaryPanel"), __metadata("design:type", Object) ], PaginationComp.prototype, "eSummaryPanel", void 0);
            __decorate([ componentAnnotations_1.RefSelector("lbCurrent"), __metadata("design:type", Object) ], PaginationComp.prototype, "lbCurrent", void 0);
            __decorate([ componentAnnotations_1.RefSelector("lbTotal"), __metadata("design:type", Object) ], PaginationComp.prototype, "lbTotal", void 0);
            __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], PaginationComp.prototype, "postConstruct", null);
            return PaginationComp;
        }(component_1.Component);
        exports.PaginationComp = PaginationComp;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var componentUtil_1 = __webpack_require__(62);
        var grid_1 = __webpack_require__(85);
        var registered = false;
        function initialiseAgGridWithWebComponents() {
            console.warn("ag-grid: initialiseAgGridWithWebComponents is deprecated. Please use the ag-grid-webcomponent dependency instead. ");
            if (registered) {
                return;
            }
            registered = true;
            if (typeof document === "undefined" || !document.registerElement) {
                console.error("ag-Grid: unable to find document.registerElement() function, unable to initialise ag-Grid as a Web Component");
            }
            var AgileGridProto = Object.create(HTMLElement.prototype);
            componentUtil_1.ComponentUtil.ALL_PROPERTIES.forEach(function(key) {
                Object.defineProperty(AgileGridProto, key, {
                    set: function(v) {
                        this.__agGridSetProperty(key, v);
                    },
                    get: function() {
                        return this.__agGridGetProperty(key);
                    },
                    enumerable: true,
                    configurable: true
                });
            });
            var agGridProtoNoType = AgileGridProto;
            agGridProtoNoType.__agGridSetProperty = function(key, value) {
                if (!this.__attributes) {
                    this.__attributes = {};
                }
                this.__attributes[key] = value;
                var changeObject = {};
                changeObject[key] = {
                    currentValue: value
                };
                this.onChange(changeObject);
            };
            agGridProtoNoType.onChange = function(changes) {
                if (this._initialised) {
                    componentUtil_1.ComponentUtil.processOnChange(changes, this._gridOptions, this.api, this.columnApi);
                }
            };
            agGridProtoNoType.__agGridGetProperty = function(key) {
                if (!this.__attributes) {
                    this.__attributes = {};
                }
                return this.__attributes[key];
            };
            agGridProtoNoType.setGridOptions = function(options) {
                var globalEventListener = this.globalEventListener.bind(this);
                this._gridOptions = componentUtil_1.ComponentUtil.copyAttributesToGridOptions(options, this);
                var gridParams = {
                    globalEventListener: globalEventListener
                };
                this._agGrid = new grid_1.Grid(this, this._gridOptions, gridParams);
                this.api = options.api;
                this.columnApi = options.columnApi;
                this._initialised = true;
            };
            agGridProtoNoType.createdCallback = function() {
                for (var i = 0; i < this.attributes.length; i++) {
                    var attribute = this.attributes[i];
                    this.setPropertyFromAttribute(attribute);
                }
            };
            agGridProtoNoType.setPropertyFromAttribute = function(attribute) {
                var name = toCamelCase(attribute.nodeName);
                var value = attribute.nodeValue;
                if (componentUtil_1.ComponentUtil.ALL_PROPERTIES.indexOf(name) >= 0) {
                    this[name] = value;
                }
            };
            agGridProtoNoType.attachedCallback = function(params) {};
            agGridProtoNoType.detachedCallback = function(params) {};
            agGridProtoNoType.attributeChangedCallback = function(attributeName) {
                var attribute = this.attributes[attributeName];
                this.setPropertyFromAttribute(attribute);
            };
            agGridProtoNoType.globalEventListener = function(eventType, event) {
                var eventLowerCase = eventType.toLowerCase();
                var browserEvent = new Event(eventLowerCase);
                var browserEventNoType = browserEvent;
                browserEventNoType.agGridDetails = event;
                this.dispatchEvent(browserEvent);
                var callbackMethod = "on" + eventLowerCase;
                if (typeof this[callbackMethod] === "function") {
                    this[callbackMethod](browserEvent);
                }
            };
            document.registerElement("ag-grid", {
                prototype: AgileGridProto
            });
        }
        exports.initialiseAgGridWithWebComponents = initialiseAgGridWithWebComponents;
        function toCamelCase(myString) {
            if (typeof myString === "string") {
                var result = myString.replace(/-([a-z])/g, function(g) {
                    return g[1].toUpperCase();
                });
                return result;
            } else {
                return myString;
            }
        }
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        var TabbedLayout = function() {
            function TabbedLayout(params) {
                var _this = this;
                this.items = [];
                this.params = params;
                this.eGui = document.createElement("div");
                this.eGui.innerHTML = TabbedLayout.TEMPLATE;
                this.eHeader = this.eGui.querySelector('[ref="tabHeader"]');
                this.eBody = this.eGui.querySelector('[ref="tabBody"]');
                utils_1.Utils.addCssClass(this.eGui, params.cssClass);
                if (params.items) {
                    params.items.forEach(function(item) {
                        return _this.addItem(item);
                    });
                }
            }
            TabbedLayout.prototype.setAfterAttachedParams = function(params) {
                this.afterAttachedParams = params;
            };
            TabbedLayout.prototype.getMinWidth = function() {
                var eDummyContainer = document.createElement("span");
                eDummyContainer.style.position = "fixed";
                this.eGui.appendChild(eDummyContainer);
                var minWidth = 0;
                this.items.forEach(function(itemWrapper) {
                    utils_1.Utils.removeAllChildren(eDummyContainer);
                    var eClone = itemWrapper.tabbedItem.bodyPromise.resolveNow(null, function(body) {
                        return body.cloneNode(true);
                    });
                    if (eClone == null) {
                        return;
                    }
                    eDummyContainer.appendChild(eClone);
                    if (minWidth < eDummyContainer.offsetWidth) {
                        minWidth = eDummyContainer.offsetWidth;
                    }
                });
                this.eGui.removeChild(eDummyContainer);
                return minWidth;
            };
            TabbedLayout.prototype.showFirstItem = function() {
                if (this.items.length > 0) {
                    this.showItemWrapper(this.items[0]);
                }
            };
            TabbedLayout.prototype.addItem = function(item) {
                var eHeaderButton = document.createElement("span");
                eHeaderButton.appendChild(item.title);
                utils_1.Utils.addCssClass(eHeaderButton, "ag-tab");
                this.eHeader.appendChild(eHeaderButton);
                var wrapper = {
                    tabbedItem: item,
                    eHeaderButton: eHeaderButton
                };
                this.items.push(wrapper);
                eHeaderButton.addEventListener("click", this.showItemWrapper.bind(this, wrapper));
            };
            TabbedLayout.prototype.showItem = function(tabbedItem) {
                var itemWrapper = utils_1.Utils.find(this.items, function(itemWrapper) {
                    return itemWrapper.tabbedItem === tabbedItem;
                });
                if (itemWrapper) {
                    this.showItemWrapper(itemWrapper);
                }
            };
            TabbedLayout.prototype.showItemWrapper = function(wrapper) {
                var _this = this;
                if (this.params.onItemClicked) {
                    this.params.onItemClicked({
                        item: wrapper.tabbedItem
                    });
                }
                if (this.activeItem === wrapper) {
                    utils_1.Utils.callIfPresent(this.params.onActiveItemClicked);
                    return;
                }
                utils_1.Utils.removeAllChildren(this.eBody);
                wrapper.tabbedItem.bodyPromise.then(function(body) {
                    _this.eBody.appendChild(body);
                });
                if (this.activeItem) {
                    utils_1.Utils.removeCssClass(this.activeItem.eHeaderButton, "ag-tab-selected");
                }
                utils_1.Utils.addCssClass(wrapper.eHeaderButton, "ag-tab-selected");
                this.activeItem = wrapper;
                if (wrapper.tabbedItem.afterAttachedCallback) {
                    wrapper.tabbedItem.afterAttachedCallback(this.afterAttachedParams);
                }
            };
            TabbedLayout.prototype.getGui = function() {
                return this.eGui;
            };
            TabbedLayout.TEMPLATE = "<div>" + '<div ref="tabHeader" class="ag-tab-header"></div>' + '<div ref="tabBody" class="ag-tab-body"></div>' + "</div>";
            return TabbedLayout;
        }();
        exports.TabbedLayout = TabbedLayout;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var VerticalStack = function() {
            function VerticalStack() {
                this.isLayoutPanel = true;
                this.childPanels = [];
                this.eGui = document.createElement("div");
                this.eGui.style.height = "100%";
            }
            VerticalStack.prototype.addPanel = function(panel, height) {
                var component;
                if (panel.isLayoutPanel) {
                    this.childPanels.push(panel);
                    component = panel.getGui();
                } else {
                    component = panel;
                }
                if (height) {
                    component.style.height = height;
                }
                this.eGui.appendChild(component);
            };
            VerticalStack.prototype.getGui = function() {
                return this.eGui;
            };
            VerticalStack.prototype.doLayout = function() {
                for (var i = 0; i < this.childPanels.length; i++) {
                    this.childPanels[i].doLayout();
                }
            };
            return VerticalStack;
        }();
        exports.VerticalStack = VerticalStack;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        function simpleHttpRequest(params) {
            return new utils_1.Promise(function(resolve) {
                var httpRequest = new XMLHttpRequest();
                httpRequest.open("GET", params.url);
                httpRequest.send();
                httpRequest.onreadystatechange = function() {
                    if (httpRequest.readyState == 4 && httpRequest.status == 200) {
                        var httpResponse = JSON.parse(httpRequest.responseText);
                        resolve(httpResponse);
                    }
                };
            });
        }
        exports.simpleHttpRequest = simpleHttpRequest;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var utils_1 = __webpack_require__(1);
        function defaultGroupComparator(valueA, valueB, nodeA, nodeB, accentedCompare) {
            if (accentedCompare === void 0) {
                accentedCompare = false;
            }
            console.warn("ag-Grid: Since ag-grid 11.0.0 defaultGroupComparator is not necessary. You can remove this from your colDef");
            var nodeAIsGroup = utils_1.Utils.exists(nodeA) && nodeA.group;
            var nodeBIsGroup = utils_1.Utils.exists(nodeB) && nodeB.group;
            var bothAreGroups = nodeAIsGroup && nodeBIsGroup;
            var bothAreNormal = !nodeAIsGroup && !nodeBIsGroup;
            if (bothAreGroups) {
                return utils_1.Utils.defaultComparator(nodeA.key, nodeB.key, accentedCompare);
            } else if (bothAreNormal) {
                return utils_1.Utils.defaultComparator(valueA, valueB, accentedCompare);
            } else if (nodeAIsGroup) {
                return 1;
            } else {
                return -1;
            }
        }
        exports.defaultGroupComparator = defaultGroupComparator;
    }, function(module, exports, __webpack_require__) {
        "use strict";
        Object.defineProperty(exports, "__esModule", {
            value: true
        });
        var BaseComponentWrapper = function() {
            function BaseComponentWrapper() {}
            BaseComponentWrapper.prototype.wrap = function(OriginalConstructor, mandatoryMethodList, optionalMethodList, componentName) {
                var _this = this;
                var wrapper = this.createWrapper(OriginalConstructor, componentName);
                mandatoryMethodList.forEach(function(methodName) {
                    _this.createMethod(wrapper, methodName, true);
                });
                if (optionalMethodList) {
                    optionalMethodList.forEach(function(methodName) {
                        _this.createMethod(wrapper, methodName, false);
                    });
                }
                return wrapper;
            };
            BaseComponentWrapper.prototype.createMethod = function(wrapper, methodName, mandatory) {
                wrapper.addMethod(methodName, this.createMethodProxy(wrapper, methodName, mandatory));
            };
            BaseComponentWrapper.prototype.createMethodProxy = function(wrapper, methodName, mandatory) {
                return function() {
                    if (wrapper.hasMethod(methodName)) {
                        return wrapper.callMethod(methodName, arguments);
                    }
                    if (mandatory) {
                        console.warn("ag-Grid: Framework component is missing the method " + methodName + "()");
                    }
                    return null;
                };
            };
            return BaseComponentWrapper;
        }();
        exports.BaseComponentWrapper = BaseComponentWrapper;
    } ]);
});

(function() {
    var flatten = function(hash) {
        var result = {};
        _.each(hash, function(value, key) {
            if (_.isPlainObject(value)) {
                _.each(flatten(value), function(hValue, hKey) {
                    result[key + "." + hKey] = hValue;
                });
            } else {
                result[key] = value;
            }
        });
        return result;
    };
    $.i18n.load(flatten(window.I18n));
    window.t = function() {
        return $.i18n._.apply($.i18n, Array.prototype.slice.call(arguments));
    };
})();

AGN = window.AGN || (window.AGN = {});

AGN.Lib = window.AGN.Lib || (window.AGN.Lib = {});

AGN.Lib.WM = window.AGN.Lib.WM || (window.AGN.Lib.WM = {});

AGN.Opt = window.AGN.Opt || (window.AGN.Opt = {});

AGN.Opt.Fields = window.AGN.Opt.Fields || (window.AGN.Opt.Fields = {});

AGN.Opt.Forms = window.AGN.Opt.Forms || (window.AGN.Opt.Forms = {});

AGN.Opt.Controllers = window.AGN.Opt.Controllers || (window.AGN.Opt.Controllers = {});

AGN.Opt.Templates = window.AGN.Opt.Templates || (window.AGN.Opt.Templates = {});

AGN.Opt.TableCellRenderers = window.AGN.Opt.TableCellRenderers || (window.AGN.Opt.TableCellRenderers = {});

AGN.Opt.Table = window.AGN.Opt.Table || (window.AGN.Opt.Table = {
    comparators: {}
});

AGN.Opt.TableHeaderComponents = window.AGN.Opt.TableHeaderComponents || (window.AGN.Opt.TableHeaderComponents = {});

AGN.Opt.Charts = window.AGN.Opt.Charts || (window.AGN.Opt.Charts = {});

AGN.Opt.Validators = window.AGN.Opt.Validators || (window.AGN.Opt.Validators = {});

AGN.Opt.Components = window.AGN.Opt.Components || (window.AGN.Opt.Components = {});

AGN.url = function(address, excludeSessionId) {
    if (window.agnResolveRelativeUrl) {
        if (address && address.charAt(0) === "/") {
            address = address.substring(1);
        }
        return window.agnResolveRelativeUrl(address, excludeSessionId);
    } else {
        console.error("window.agnResolveRelativeUrl is not defined");
        return address;
    }
};

AGN.isIE = /MSIE|Trident/.test(window.navigator.userAgent);

AGN.runAll = function($scope) {
    AGN.Lib.CoreInitializer.autorun($scope);
    AGN.Lib.DomInitializer.autorun($scope);
};

(function() {
    if (!Array.prototype.find) {
        Object.defineProperty(Array.prototype, "find", {
            value: function(predicate) {
                "use strict";
                if (this == null) {
                    throw new TypeError("Array.prototype.find called on null or undefined");
                }
                if (typeof predicate !== "function") {
                    throw new TypeError("predicate must be a function");
                }
                var list = Object(this);
                var length = list.length >>> 0;
                var thisArg = arguments[1];
                var value;
                for (var i = 0; i < length; i++) {
                    value = list[i];
                    if (predicate.call(thisArg, value, i, list)) {
                        return value;
                    }
                }
                return undefined;
            }
        });
    }
    if (!Array.prototype.findIndex) {
        Object.defineProperty(Array.prototype, "findIndex", {
            value: function(predicate) {
                "use strict";
                if (this == null) {
                    throw new TypeError("Array.prototype.findIndex called on null or undefined");
                }
                if (typeof predicate !== "function") {
                    throw new TypeError("predicate must be a function");
                }
                var list = Object(this);
                var length = list.length >>> 0;
                var thisArg = arguments[1];
                var value;
                for (var i = 0; i < length; i++) {
                    value = list[i];
                    if (predicate.call(thisArg, value, i, list)) {
                        return i;
                    }
                }
                return -1;
            },
            enumerable: false,
            configurable: false,
            writable: false
        });
    }
    if (!Array.prototype.includes) {
        Object.defineProperty(Array.prototype, "includes", {
            value: function(searchElement, fromIndex) {
                if (this == null) {
                    throw new TypeError('"this" is null or not defined');
                }
                var o = Object(this);
                var len = o.length >>> 0;
                if (len === 0) {
                    return false;
                }
                var n = fromIndex | 0;
                var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);
                function sameValueZero(x, y) {
                    return x === y || typeof x === "number" && typeof y === "number" && isNaN(x) && isNaN(y);
                }
                while (k < len) {
                    if (sameValueZero(o[k], searchElement)) {
                        return true;
                    }
                    k++;
                }
                return false;
            }
        });
    }
})();

(function() {
    var orig_allowInteraction = $.ui.dialog.prototype._allowInteraction;
    $.ui.dialog.prototype._allowInteraction = function(event) {
        var $target = $(event.target);
        if ($target.closest(".cke_dialog").length || $target.closest(".cke_panel_frame").length) {
            return true;
        }
        return orig_allowInteraction.apply(this, arguments);
    };
})();

if (Function.prototype.bind && window.console && typeof console.log == "object") {
    [ "log", "info", "warn", "error", "assert", "dir", "clear", "profile", "profileEnd" ].forEach(function(method) {
        console[method] = this.bind(console[method], console);
    }, Function.prototype.call);
}

(function(root, factory) {
    if (typeof exports == "object") {
        module.exports = factory(root);
    } else if (typeof define == "function" && define.amd) {
        define([], factory.bind(root, root));
    } else {
        factory(root);
    }
})(typeof global != "undefined" ? global : this, function(root) {
    if (root.CSS && root.CSS.escape) {
        return root.CSS.escape;
    }
    var cssEscape = function(value) {
        if (arguments.length == 0) {
            throw new TypeError("`CSS.escape` requires an argument.");
        }
        var string = String(value);
        var length = string.length;
        var index = -1;
        var codeUnit;
        var result = "";
        var firstCodeUnit = string.charCodeAt(0);
        while (++index < length) {
            codeUnit = string.charCodeAt(index);
            if (codeUnit == 0) {
                result += "�";
                continue;
            }
            if (codeUnit >= 1 && codeUnit <= 31 || codeUnit == 127 || index == 0 && codeUnit >= 48 && codeUnit <= 57 || index == 1 && codeUnit >= 48 && codeUnit <= 57 && firstCodeUnit == 45) {
                result += "\\" + codeUnit.toString(16) + " ";
                continue;
            }
            if (index == 0 && length == 1 && codeUnit == 45) {
                result += "\\" + string.charAt(index);
                continue;
            }
            if (codeUnit >= 128 || codeUnit == 45 || codeUnit == 95 || codeUnit >= 48 && codeUnit <= 57 || codeUnit >= 65 && codeUnit <= 90 || codeUnit >= 97 && codeUnit <= 122) {
                result += string.charAt(index);
                continue;
            }
            result += "\\" + string.charAt(index);
        }
        return result;
    };
    if (!root.CSS) {
        root.CSS = {};
    }
    root.CSS.escape = cssEscape;
    return cssEscape;
});

(function($) {
    $.fn.modal.Constructor.prototype.escape = function() {
        if (this.isShown && this.options.keyboard) {
            this.$element.on("keydown.dismiss.bs.modal", $.proxy(function(e) {
                setTimeout($.proxy(function() {
                    e.which == 27 && this.hide();
                }, this), 100);
            }, this));
        } else if (!this.isShown) {
            this.$element.off("keydown.dismiss.bs.modal");
        }
    };
})(jQuery);

(function() {
    jQuery.browser = getBrowserInformation().browser;
    function getBrowserInformation() {
        var userAgent = navigator.userAgent.toLowerCase();
        var regexMsie = /(msie) ([\w.]+)/;
        var regexWebkit = /(webkit)[ \/]([\w.]+)/;
        var regexOpera = /(opera)(?:.*version)?[ \/]([\w.]+)/;
        var regexMozilla = /(mozilla)(?:.*? rv:([\w.]+))?/;
        var match = regexWebkit.exec(userAgent) || regexOpera.exec(userAgent) || regexMsie.exec(userAgent) || userAgent.indexOf("compatible") < 0 && regexMozilla.exec(userAgent) || [];
        return {
            browser: match[1] || "",
            version: match[2] || "0"
        };
    }
})(jQuery);

(function($) {
    $.extend(true, $.fn.dirty.prototype, {
        checkValues: function(e) {
            var d = this;
            var formIsDirty = false;
            this.form.find("select").each(function(_, el) {
                var $el = $(el);
                var thisIsDirty = d.isSelectFieldDirty($el);
                $el.data(d.statuses.dataIsDirty, thisIsDirty);
                formIsDirty |= thisIsDirty;
            });
            this.form.find("input, textarea").each(function(_, el) {
                var isRadioOrCheckbox = d.isRadioOrCheckbox(el);
                var isFile = d.isFileInput(el);
                var $el = $(el);
                var thisIsDirty;
                if (isRadioOrCheckbox) {
                    thisIsDirty = d.isCheckboxDirty($el);
                } else if (isFile) {
                    thisIsDirty = d.isFileInputDirty($el);
                } else {
                    if (!$el.is(".select2-input[placeholder]")) {
                        thisIsDirty = d.isFieldDirty($el);
                    }
                }
                $el.data(d.statuses.dataIsDirty, thisIsDirty);
                formIsDirty |= thisIsDirty;
            });
            if (formIsDirty) {
                d.setDirty();
            } else {
                d.setClean();
            }
        },
        saveInitialValues: function() {
            var d = this;
            this.form.find("input, select, textarea").each(function(uid, e) {
                var $el = $(e);
                if ($el.attr("id") || $el.attr("name")) {
                    $el.attr("id", $el.prop("tagName" + "__" + uid));
                }
                var isRadioOrCheckbox = d.isRadioOrCheckbox(e);
                var isFile = d.isFileInput(e);
                if (isRadioOrCheckbox) {
                    var isChecked = $(e).is(":checked") ? "checked" : "unchecked";
                    $el.data(d.statuses.dataInitialValue, isChecked);
                } else if (isFile) {
                    $el.data(d.statuses.dataInitialValue, JSON.stringify(e.files));
                } else {
                    $el.data(d.statuses.dataInitialValue, $el.val() || "");
                }
            });
        },
        backupData: function() {
            var d = this;
            var json = {};
            d.form.find("input, select, textarea").each(function(_, el) {
                var $el = $(el);
                var id = $el.attr("id") || $el.attr("name");
                var data = {};
                data[d.statuses.dataInitialValue] = $el.data(d.statuses.dataInitialValue);
                data[d.statuses.dataIsDirty] = $el.data(d.statuses.dataIsDirty);
                json[id] = data;
            });
            return json;
        },
        restoreData: function(json) {
            var d = this;
            if (json) {
                d.form.find("input, select, textarea").each(function(_, el) {
                    var $el = $(el);
                    var id = $el.attr("id") || $el.attr("name");
                    var data = json[id];
                    if (data) {
                        $el.data(d.statuses.dataInitialValue, data[d.statuses.dataInitialValue]);
                        $el.data(d.statuses.dataIsDirty, data[d.statuses.dataIsDirty]);
                    }
                });
            }
            d.checkValues();
        },
        isSelectFieldDirty: function($field) {
            var d = this;
            var initialValue = $field.data(d.statuses.dataInitialValue) || "";
            var currentValue = $field.val() || "";
            return !_.isEqual(currentValue, initialValue);
        },
        resetForm: function() {
            var d = this;
            this.form.find("select").each(function(_, e) {
                var $e = $(e);
                var value = $e.data(d.statuses.dataInitialValue);
                if ($e.data("select2")) {
                    $e.select2("val", value);
                } else {
                    $e.val(value);
                }
            });
            this.form.find("input, textarea").each(function(_, e) {
                var $e = $(e);
                var isRadioOrCheckbox = d.isRadioOrCheckbox(e);
                var isFile = d.isFileInput(e);
                if (isRadioOrCheckbox) {
                    var initialCheckedState = $e.data(d.statuses.dataInitialValue);
                    var isChecked = initialCheckedState === "checked";
                    $e.prop("checked", isChecked);
                }
                if (isFile) {
                    e.value = "";
                    $(e).data(d.statuses.dataInitialValue, JSON.stringify(e.files));
                } else {
                    var value = $e.data(d.statuses.dataInitialValue);
                    $e.val(value);
                }
            });
            this.checkValues();
        }
    });
})(jQuery);

(function($) {
    if ($.fn.all) {
        console.error("$.fn.all is already defined");
    } else {
        $.fn.extend({
            all: function(selectors) {
                return this.filter(selectors).add(this.find(selectors));
            }
        });
    }
    if ($.fn.exists) {
        console.error("$.fn.exists is already defined");
    } else {
        $.fn.extend({
            exists: function() {
                return this.length > 0;
            }
        });
    }
    if ($.fn.json) {
        console.error("$.fn.json is already defined");
    } else {
        $.fn.extend({
            json: function() {
                return JSON.parse(this.html());
            }
        });
    }
    $.expr[":"].truncated = function(el) {
        return el.clientWidth < el.scrollWidth;
    };
})(jQuery);

(function($) {
    $.fn.extend({
        ensureLoad: function(handler) {
            return this.each(function() {
                if (this.complete) {
                    handler.call(this);
                } else {
                    $(this).on("load", handler);
                }
            });
        }
    });
})(jQuery);

$.extend(true, $.inputmask.defaults.aliases, {
    datetime: {
        regex: {
            quartspre: new RegExp("0|1|3|4"),
            quartspost: new RegExp("00|15|30|45"),
            halfspre: new RegExp("0|3"),
            halfspost: new RegExp("00|30")
        },
        definitions: {
            q: {
                validator: function(chrs, maskset, pos, strict, opts) {
                    var isValid = opts.regex.quartspost.test(chrs);
                    if (!strict && !isValid) {
                        if (opts.regex.quartspost.test(chrs[0] + "5")) {
                            return {
                                c: "5"
                            };
                        } else {
                            return {
                                c: "0"
                            };
                        }
                    }
                    return true;
                },
                cardinality: 2,
                prevalidator: [ {
                    validator: function(chrs, maskset, pos, strict, opts) {
                        var isValid = opts.regex.quartspre.test(chrs);
                        isValid = false;
                        if (!strict && !isValid) {
                            var completedVal = parseInt(chrs + "0"), acceptableVals = [ "00", "15", "30", "45" ], diffVal = 100, acceptedVal, command;
                            for (var i = 0; i < acceptableVals.length; i++) {
                                var num = acceptableVals[i];
                                parsedNum = parseInt(num);
                                if (Math.abs(parsedNum - completedVal) < diffVal) {
                                    diffVal = Math.abs(parsedNum - completedVal);
                                    acceptedVal = num;
                                }
                            }
                            command = {
                                caret: pos + 2,
                                insert: [ {
                                    pos: pos,
                                    c: acceptedVal[0]
                                }, {
                                    pos: pos + 1,
                                    c: acceptedVal[1]
                                } ]
                            };
                            return command;
                        }
                        return true;
                    },
                    cardinality: 1
                } ]
            },
            u: {
                validator: function(chrs, maskset, pos, strict, opts) {
                    var isValid = opts.regex.halfspost.test(chrs);
                    if (!strict && !isValid) {
                        return {
                            c: "0"
                        };
                    }
                    return true;
                },
                cardinality: 2,
                prevalidator: [ {
                    validator: function(chrs, maskset, pos, strict, opts) {
                        var isValid = opts.regex.halfspre.test(chrs);
                        isValid = false;
                        if (!strict && !isValid) {
                            var completedVal = parseInt(chrs + "0"), acceptableVals = [ "00", "30" ], diffVal = 100, acceptedVal, command;
                            for (var i = 0; i < acceptableVals.length; i++) {
                                var num = acceptableVals[i];
                                parsedNum = parseInt(num);
                                if (Math.abs(parsedNum - completedVal) < diffVal) {
                                    diffVal = Math.abs(parsedNum - completedVal);
                                    acceptedVal = num;
                                }
                            }
                            command = {
                                caret: pos + 2,
                                insert: [ {
                                    pos: pos,
                                    c: acceptedVal[0]
                                }, {
                                    pos: pos + 1,
                                    c: acceptedVal[1]
                                } ]
                            };
                            return command;
                        }
                        return true;
                    },
                    cardinality: 1
                } ]
            }
        }
    },
    "h:quarts t": {
        mask: "h:q t\\m",
        placeholder: "hh:mm xm",
        alias: "datetime",
        hourFormat: "12"
    },
    "h:quarts": {
        mask: "h:q",
        placeholder: "hh:mm",
        alias: "datetime",
        hourFormat: "24"
    },
    "h:halfs t": {
        mask: "h:u t\\m",
        placeholder: "hh:mm xm",
        alias: "datetime",
        hourFormat: "12"
    },
    "h:halfs": {
        mask: "h:u",
        placeholder: "hh:mm",
        alias: "datetime",
        hourFormat: "24"
    },
    "h:00 t": {
        mask: "h:00 t\\m",
        placeholder: "hh:00 xm",
        alias: "datetime",
        hourFormat: "12"
    },
    "h:00": {
        mask: "h:00",
        placeholder: "hh:00",
        alias: "datetime",
        hourFormat: "24"
    }
});

$.fn.serializeObject = function() {
    var map = {};
    $.each(this.serializeArray(), function() {
        if (map[this.name]) {
            if (!map[this.name].push) {
                map[this.name] = [ map[this.name] ];
            }
            map[this.name].push(this.value || "");
        } else {
            map[this.name] = this.value || "";
        }
    });
    return map;
};

$.fn.serializeFormDataObject = function() {
    var map = this.serializeObject();
    this.find("input[type=file]").each(function() {
        if (!$(this).is(":disabled") && this.name) {
            var files = this.files;
            if (files.length == 0) {
                files = [ new File([], "", {
                    type: "application/octet-stream"
                }) ];
            }
            if (map[this.name]) {
                var previousValues = map[this.name];
                if ($.isArray(previousValues)) {
                    map[this.name] = previousValues.concat(files);
                } else {
                    map[this.name] = [ previousValues ].concat(files);
                }
            } else {
                if (files.length > 1) {
                    map[this.name] = files;
                } else {
                    map[this.name] = files[0];
                }
            }
        }
    });
    return map;
};

(function($) {
    if ($.fn.style) {
        console.error("$.fn.style is already defined");
    } else {
        $.fn.extend({
            style: function(property, value, priority) {
                if (value === undefined) {
                    return this.css(property);
                }
                if ($.isFunction(value)) {
                    this.each(function() {
                        if (this.style) {
                            var newValue = value.call(this, this.style.getPropertyValue(property));
                            this.style.setProperty(property, newValue, priority);
                        }
                    });
                } else {
                    this.each(function() {
                        if (this.style) {
                            this.style.setProperty(property, value, priority);
                        }
                    });
                }
            }
        });
    }
})(jQuery);

(function($) {
    if (String.prototype.trim) {
        $.trim = function(text) {
            return text == null ? "" : (text + "").trim();
        };
    }
})(jQuery);

$.widget("ui.dialog", $.extend({}, $.ui.dialog.prototype, {
    _title: function(title) {
        if (!this.options.title) {
            title.html("&#160;");
        }
        title.html(this.options.title);
    }
}));

AGN.Opt.Components.JsPlumbFixedBezierConnector = function(params) {
    var _super = jsPlumb.Connectors.AbstractConnector.apply(this, arguments);
    this.type = "FixedBezierConnector";
    this._compute = function(d) {
        var k = d.anchorOrientation === "opposite" ? 2 : 1.5;
        _super.addSegment(this, "Bezier", {
            x1: d.tx,
            y1: d.ty,
            x2: d.sx,
            y2: d.sy,
            cp1x: d.tx + d.to[0] * d.w / k,
            cp1y: d.ty + d.to[1] * d.h / k,
            cp2x: d.sx + d.so[0] * d.w / k,
            cp2y: d.sy + d.so[1] * d.h / k
        });
    };
};

_.templateSettings = {
    evaluate: /\{\{(.+?)\}\}/g,
    interpolate: /\{\{=(.+?)\}\}/g,
    escape: /\{\{-(.+?)\}\}/g
};

jQuery.extend(jQuery.fn.pickadate.defaults, {
    monthsFull: t("date.monthsFull"),
    monthsShort: t("date.monthsShort"),
    weekdaysFull: t("date.weekdaysFull"),
    weekdaysShort: t("date.weekdaysShort"),
    labelMonthNext: t("date.nextMonth"),
    labelMonthPrev: t("date.prevMonth"),
    labelMonthSelect: t("date.selectMonth"),
    labelYearSelect: t("date.selectYear"),
    today: t("defaults.today"),
    clear: t("defaults.delete"),
    close: t("defaults.close"),
    firstDay: t("date.firstDayOfWeek"),
    format: t("date.format"),
    hiddenName: true
});

jQuery.extend(jQuery.fn.pickatime.defaults, {
    clear: t("defaults.delete"),
    format: t("time.format"),
    hiddenName: true
});

window.onpopstate = function() {
    window.location.reload();
};

jQuery.extend($.fn.select2.defaults, {
    formatNoMatches: function(term) {
        return t("selects.noMatches", term);
    },
    formatInputTooShort: function(input, min) {
        return t("selects.errors.inputTooShort", min);
    },
    formatInputTooLong: function(input, max) {
        return t("selects.errors.inputTooLong", max);
    },
    formatSelectionTooBig: function(limit) {
        return t("selects.errors.selectionTooBig", limit);
    },
    formatLoadMore: function(pageNumber) {
        return t("selects.loadMore");
    },
    formatSearching: function() {
        return t("selects.loadMore");
    },
    formatAjaxError: function() {
        return t("selects.errors.ajax");
    },
    formatMatches: function(matches) {
        if (matches > 1) {
            return t("selects.matches", matches);
        } else {
            return t("selects.matchesSing", matches);
        }
    }
});

(function() {
    if (!String.prototype.startsWith) {
        String.prototype.startsWith = function(search, pos) {
            return this.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search;
        };
    }
    if (!String.prototype.endsWith) {
        String.prototype.endsWith = function(search, len) {
            if (len === undefined || len > this.length) {
                len = this.length;
            }
            return this.substring(len - search.length, len) === search;
        };
    }
    if (!String.prototype.includes) {
        String.prototype.includes = function(search, start) {
            "use strict";
            if (typeof start !== "number") {
                start = 0;
            }
            if (start + search.length > this.length) {
                return false;
            } else {
                return this.indexOf(search, start) !== -1;
            }
        };
    }
})();

!function(root, factory) {
    "function" == typeof define && define.amd ? define([], function() {
        return root.svg4everybody = factory();
    }) : "object" == typeof exports ? module.exports = factory() : root.svg4everybody = factory();
}(this, function() {
    function embed(svg, g) {
        if (g) {
            var viewBox = !svg.getAttribute("viewBox") && g.getAttribute("viewBox"), fragment = document.createDocumentFragment(), clone = g.cloneNode(!0);
            for (viewBox && svg.setAttribute("viewBox", viewBox); clone.childNodes.length; ) {
                fragment.appendChild(clone.firstChild);
            }
            svg.appendChild(fragment);
        }
    }
    function loadreadystatechange(xhr) {
        xhr.onreadystatechange = function() {
            if (4 === xhr.readyState) {
                var x = document.createElement("x");
                x.innerHTML = xhr.responseText, xhr.s.splice(0).map(function(array) {
                    embed(array[0], x.querySelector("#" + array[1].replace(/(\W)/g, "\\$1")));
                });
            }
        }, xhr.onreadystatechange();
    }
    function svg4everybody(opts) {
        function oninterval() {
            for (var use; use = uses[0]; ) {
                var svg = use.parentNode;
                if (svg && /svg/i.test(svg.nodeName)) {
                    var src = use.getAttribute("xlink:href");
                    if (polyfill && (!validate || validate(src, svg, use))) {
                        var url = src.split("#"), url_root = url[0], url_hash = url[1];
                        if (svg.removeChild(use), url_root.length) {
                            var xhr = svgCache[url_root] = svgCache[url_root] || new XMLHttpRequest();
                            xhr.s || (xhr.s = [], xhr.open("GET", url_root), xhr.send()), 
                            xhr.s.push([ svg, url_hash ]), loadreadystatechange(xhr);
                        } else {
                            embed(svg, document.getElementById(url_hash));
                        }
                    }
                }
            }
            requestAnimationFrame(oninterval, 17);
        }
        opts = opts || {};
        var uses = document.getElementsByTagName("use"), polyfill = "polyfill" in opts ? opts.polyfill : /\bEdge\/12\b|\bTrident\/[567]\b|\bVersion\/7.0 Safari\b/.test(navigator.userAgent) || (navigator.userAgent.match(/AppleWebKit\/(\d+)/) || [])[1] < 537, validate = opts.validate, requestAnimationFrame = window.requestAnimationFrame || setTimeout, svgCache = {};
        polyfill && oninterval();
    }
    return svg4everybody;
});

AGN.Opt.Templates["modal"] = '<div class="modal">   <div class="modal-dialog {{= modalClass }}">     <div class="modal-content">       <div class="modal-header">         <button type="button" class="close-icon close" data-dismiss="modal">           <i aria-hidden="true" class="icon icon-times-circle"></i>         </button>         <h4 class="modal-title">{{= title }}</h4>       </div>       <div class="modal-body">         {{= content }}       </div>     </div>   </div> </div>';

AGN.Opt.Templates["csrf-error"] = '    <div class="backdrop backdrop-error js-close-error" style="position: fixed; top: 0; left: 0; bottom: 0; right:0; z-index: 1100; background-color: rgba(0,0,0,0.5)">        <div class="notification notification-alert" style="position: fixed; top: 50%; left: 50%; width: 420px; margin: -80px 0 0 -210px; z-index: 1101;">            <div class="notification-header">                <p class="headline">                    <i class="icon icon-state-alert"></i>                    <span class="text">{{= headline }}</span>                    <i class="icon icon-times-circle close-icon js-close-error"></i>                </p>            </div>            <div class="notification-content">                <p>{{= content }}</p>                <a href="#" class="btn btn-regular btn-primary vspace-top-10" onclick="location.reload();">                    <i class="icon icon-repeat"></i>                    <span class="text">{{= reload }}</span>                </a>            </div>        </div>    </div>';

AGN.Opt.Templates["modal-yes-no-cancel"] = '<div class="modal">   <div class="modal-dialog">     <div class="modal-content">       <form action="{{= action }}" method="{{= method }}">         <div class="modal-header">           <button type="button" class="close-icon close" data-dismiss="modal">             <i aria-hidden="true" class="icon icon-times-circle"></i>           </button>           <h4 class="modal-title">{{= title }}</h4>         </div>         <div class="modal-body">           {{= content }}         </div>         <div class="modal-footer">           <div class="btn-group">             <button type="button" class="btn btn-default btn-large js-confirm-negative" data-dismiss="modal">               <i class="icon icon-times"></i>               <span class="text">{{= t(\'defaults.no\') }}</span>             </button>             <button type="button" class="btn btn-primary btn-large js-confirm-positive" data-dismiss="modal">               <i class="icon icon-check"></i>               <span class="text">{{= t(\'defaults.yes\') }}</span>             </button>           </div>         </div>       </form>     </div>   </div> </div>';

AGN.Opt.Templates["modal-yes-no-cancel-save-choice"] = '<div class="modal">   <div class="modal-dialog {{= modalClass }}">     <div class="modal-content">       <div class="modal-header">         <button type="button" class="close-icon close" data-dismiss="modal">           <i aria-hidden="true" class="icon icon-times-circle"></i>         </button>         <h4 class="modal-title">{{= title }}</h4>       </div>       <div class="modal-body">         <div class="form-group">           <div class="col-sm-12">           {{= content }}           </div>         </div>         <div class="form-group">           <div class="col-sm-8">             <label class="control-label-left">               {{ if(!choiceContent) { }}                 {{= t(\'defaults.remember.choice\') }}               {{ } else { }}                 {{= choiceContent }}               {{ } }}             </label>           </div>           <div class="col-sm-4">             <label class="toggle">               <input type="checkbox" name="confirm-save-choice">               <div class="toggle-control"></div>             </label>           </div>         </div>       </div>       <div class="modal-footer">         <div class="btn-group">           <button type="button" class="btn btn-default btn-large pull-left" data-confirm-negative="cancel" data-dismiss="modal">             <i class="icon icon-times"></i>             <span class="text">{{= t(\'defaults.cancel\') }}</span>           </button>           <button type="button" class="btn btn-default btn-large" data-confirm-negative="no" data-dismiss="modal">             <i class="icon icon-times"></i>             <span class="text">{{= t(\'defaults.no\') }}</span>           </button>           <button type="button" class="btn btn-primary btn-large" data-confirm-positive="yes" data-dismiss="modal">             <i class="icon icon-check"></i>             <span class="text">{{= t(\'defaults.yes\') }}</span>           </button>         </div>       </div>     </div>   </div> </div>';

AGN.Opt.Templates["error"] = '<div class="backdrop backdrop-error js-close-error overlay-box">     <div class="notification notification-alert overlay-content">         <div class="notification-header">             <p class="headline">                 <i class="icon icon-state-alert"></i>                 <span class="text">{{= headline }}</span>                 <i class="icon icon-times-circle close-icon js-close-error"></i>             </p>         </div>         <div class="notification-content">             <p>{{= text }}</p>             <button type="button" class="btn btn-regular btn-primary vspace-top-10" onclick="location.reload();">                 <i class="icon icon-repeat"></i>                 <span class="text">{{= reload }}</span>             </button>         </div>     </div> </div>';

AGN.Opt.Templates["permission-denied"] = '<div class="backdrop backdrop-error js-close-error overlay-box">     <div class="notification notification-alert overlay-content">         <div class="notification-header">             <p class="headline">                 <i class="icon icon-state-alert"></i>                 <span class="text">{{= title }}</span>                 <i class="icon icon-times-circle close-icon js-close-error"></i>             </p>         </div>         <div class="notification-content">             <p>{{= text }}</p>             <button type="button" class="btn btn-regular btn-primary vspace-top-10 vspace-bottom-10 js-close-error" style="float: right">                 <i class="icon icon-check"></i>                 <span class="text">{{= btn }}</span>             </button>         </div>     </div> </div>';

AGN.Opt.Templates["autosave-restore"] = '<div class="modal">   <div class="modal-dialog {{= modalClass }}">     <div class="modal-content">       <div class="modal-header">         <button type="button" class="close-icon close" data-dismiss="modal">           <i aria-hidden="true" class="icon icon-times-circle"></i>         </button>         <h4 class="modal-title">{{= title }}</h4>       </div>       <div class="modal-body">         {{= content }}       </div>       <div class="modal-footer">         <div class="btn-group">           <button type="button" class="btn btn-default btn-large js-confirm-negative" data-dismiss="modal">             <i class="icon icon-times"></i>             <span class="text">{{= negative }}</span>           </button>           <button type="button" class="btn btn-primary btn-large js-confirm-positive" data-dismiss="modal">             <i class="icon icon-check"></i>             <span class="text">{{= positive }}</span>           </button>         </div>       </div>     </div>   </div> </div>';

AGN.Opt.Templates["tooltip-template"] = '<div class="tooltip {{= tooltipStyle }}" role="tooltip">   <div class="tooltip-arrow {{= arrowStyle }}"></div>   <div class="tooltip-inner {{= innerStyle }}"></div> </div>';

AGN.Opt.Templates["tooltip-message-with-title"] = '<div class="helper-popup-header">{{= title }}</div> <div class="helper-popup-content">{{= content }}</div>';

AGN.Opt.Templates["tooltip-message-just-content"] = '<div class="helper-popup-content">{{= content }}</div>';

AGN.Opt.Templates["table-controls-top"] = '{{ if (showRecordsCount || pagination) { }} <div class="table-controls clearfix">   {{ if (showRecordsCount) { }}   <div class="table-control pull-left">     <div class="well">{{= t(\'tables.range\', itemStart, itemEnd, itemTotal) }}</div>   </div>   {{ } }}  <div class="table-control pull-left" id="filtersDescription"></div>   {{ if (pagination) { }}   <div class="table-control pull-right">     <ul class="pagination">       <li class="js-data-table-first-page {{= currentPage == 1 ? \'disabled\' : \'\' }}">         <span><i class="icon icon-angle-double-left"></i> {{= t(\'tables.first\') }}</span>       </li>       <li class="js-data-table-prev-page {{= currentPage == 1 ? \'disabled\' : \'\' }}">         <span><i class="icon icon-angle-left"></i> {{= t(\'tables.previous\') }}</span>       </li>       {{ _.each(pageSelects, function(page) { }}       <li class="{{= page == currentPage ? \'active\' : \'js-data-table-page\' }}" data-page="{{= page - 1 }}">         <span>{{= page }}</span>       </li>       {{ }) }}       <li class="js-data-table-next-page {{= currentPage == totalPages ? \'disabled\' : \'\' }}">         <span>{{= t(\'tables.next\') }} <i class="icon icon-angle-right"></i></span>       </li>       <li class="js-data-table-last-page {{= currentPage == totalPages ? \'disabled\' : \'\' }}">         <span>{{= t(\'tables.last\') }} <i class="icon icon-angle-double-right"></i></span>       </li>     </ul>   </div>   {{ } }}  </div>{{ } }}';

AGN.Opt.Templates["table-controls-bottom"] = "<div class=\"table-controls clearfix\">   {{ if (showRecordsCount) { }}   <div class=\"table-control pull-left\">     <div class=\"well\">{{= t('tables.range', itemStart, itemEnd, itemTotal) }}</div>   </div>   {{ } }}   {{ if (pagination) { }}   <div class=\"table-control pull-right\">     <ul class=\"pagination\">       <li class=\"js-data-table-first-page {{= currentPage == 1 ? 'disabled' : '' }}\">         <span><i class=\"icon icon-angle-double-left\"></i> {{= t('tables.first') }}</span>       </li>       <li class=\"js-data-table-prev-page {{= currentPage == 1 ? 'disabled' : '' }}\">         <span><i class=\"icon icon-angle-left\"></i> {{= t('tables.previous') }}</span>       </li>       {{ _.each(pageSelects, function(page) { }}        <li class=\"{{= page == currentPage ? 'active' : 'js-data-table-page' }}\" data-page=\"{{= page - 1 }}\">         <span>{{= page }}</span>       </li>       {{ }) }}       <li class=\"js-data-table-next-page {{= currentPage == totalPages ? 'disabled' : '' }}\">         <span>{{= t('tables.next') }} <i class=\"icon icon-angle-right\"></i></span>       </li>       <li class=\"js-data-table-last-page {{= currentPage == totalPages ? 'disabled' : '' }}\">         <span>{{= t('tables.last') }} <i class=\"icon icon-angle-double-right\"></i></span>       </li>     </ul>   </div>   {{ } }} </div>";

AGN.Opt.Templates["session-expired"] = '<div class="backdrop backdrop-warning overlay-box" id="session-expired-overlay">     <div class="notification notification-warning overlay-content">         <div class="notification-header">             <p class="headline">                 <i class="icon icon-state-alert"></i>                 <span class="text">{{= t(\'logon.session.expired\') }}</span>             </p>         </div>         <div class="notification-content">             <div class="form-group">               {{= t(\'logon.session.notification\') }}             </div>            <div class="form-group">               <a href="{{= AGN.url("/logon.action", true) }}">                 {{= t(\'defaults.relogin\') }}               </a>             </div>        </div>     </div> </div>';

AGN.Opt.Templates["datetime-picker"] = '<div class="row">  <div class="col-sm-8">     <div class="input-group">       <div class="input-group-controls">         <input type="text" id="{{- property }}_date" class="form-control datepicker-input js-datepicker"           data-value="{{- date}}" data-datepicker-options="format: {{- dateFormat}}"/>       </div>       <div class="input-group-btn">         <button type="button" class="btn btn-regular btn-toggle js-open-datepicker" tabindex="-1">           <i class="icon icon-calendar-o"></i>         </button>       </div>     </div>   </div>   <div class="col-sm-4">     <div class="input-group">       <div class="input-group-controls">         <input type="text" id="{{- property }}_time" class="form-control js-timepicker" value="{{- time}}"              data-timepicker-options="mask: \'h:s\'"/>       </div>       <div class="input-group-addon">         <span class="addon"><i class="icon icon-clock-o"></i></span>       </div>     </div>   </div> </div>';

AGN.Opt.Templates["trackablelink-extension-table-row"] = '<tr data-extension-row="{{- index}}">     <td>         <input type="text" class="form-control" data-extension-name value="{{- name}}"/>     </td>     <td>         <input type="text" class="form-control" data-extension-value value="{{- value}}"/>     </td>     <td class="table-actions">         {{ if (name == "" && value == "") { }}             <a href="#" class="btn btn-regular btn-primary" data-extension-add id="newExtensionBtn">                 <i class="icon icon-plus"></i>             </a>         {{ } else { }}             <a href="#" class="btn btn-regular btn-alert" data-extension-delete>                 <i class="icon icon-trash-o"></i>             </a>         {{ } }}     </td> </tr>';

AGN.Opt.Templates["mailing-param-row"] = '  <tr data-param-row="{{- index}}">       <td>           <input type="text" value="{{- name}}" data-param-name class="form-control" data-action="param-enterdown" {{ isChangeable ? print("") : print("readonly") }} />       </td>       <td>           <input type="text" value="{{- value}}" data-param-value class="form-control" data-action="param-enterdown" {{ isChangeable ? print("") : print("readonly") }} />       </td>       <td>           <input type="text" value="{{- description}}" data-param-description class="form-control" data-action="param-enterdown" {{ isChangeable ? print("") : print("readonly") }} />       </td>       {{ if (isChangeable) { }}       <td class="table-actions">         {{ if (name == "" && value == "") { }}             <a href="#" class="btn btn-regular btn-primary" data-action="add-param-row" id="newParamBtn">                 <i class="icon icon-plus"></i>             </a>         {{ } else { }}             <a href="#" class="btn btn-regular btn-alert" data-action="delete-param-row">                 <i class="icon icon-trash-o"></i>             </a>         {{ } }}       </td>       {{ } }}   </tr>';

AGN.Opt.Templates["mailing-reference-content-item"] = '   <div class="form-group">       <div class="col-sm-4">           <label class="control-label" for="input-{{- name }}">{{- name }}</label>       </div>       <div class="col-sm-8">           <div class="input-group-controls">               <input type="text" class="form-control" name="referenceContentSettings.items" value="{{- value }}" {{ disable ? print("disabled") : print("")}} id="input-{{- name }}"/>           </div>           <div class="input-group-btn">               <button type="button" class="btn btn-regular btn-alert" {{ disable ? print("disabled") : print("")}}                       data-action="delete-reference-content-item">                   <i class="icon icon-trash-o"></i>               </button>           </div>       </div>   </div>';

(function() {
    if (window.agnTimeZoneId) {
        moment.tz.setDefault(window.agnTimeZoneId);
    }
})();

(function(root, factory) {
    if (typeof define == "function" && define.amd) {
        define([ "jquery", "dot/doT", "jquery-extendext" ], factory);
    } else if (typeof module === "object" && module.exports) {
        module.exports = factory(require("jquery"), require("dot/doT"), require("jquery-extendext"));
    } else {
        factory(root.jQuery, root.doT);
    }
})(this, function($, doT) {
    "use strict";
    var QueryBuilder = function($el, options) {
        $el[0].queryBuilder = this;
        this.$el = $el;
        this.settings = $.extendext(true, "replace", {}, QueryBuilder.DEFAULTS, options);
        this.model = new Model();
        this.status = {
            id: null,
            generated_id: false,
            group_id: 0,
            rule_id: 0,
            has_optgroup: false,
            has_operator_optgroup: false
        };
        this.filters = this.settings.filters;
        this.icons = this.settings.icons;
        this.operators = this.settings.operators;
        this.templates = this.settings.templates;
        this.plugins = this.settings.plugins;
        this.lang = null;
        if (QueryBuilder.regional["en"] === undefined) {
            Utils.error("Config", '"i18n/en.js" not loaded.');
        }
        this.lang = $.extendext(true, "replace", {}, QueryBuilder.regional["en"], QueryBuilder.regional[this.settings.lang_code], this.settings.lang);
        if (this.settings.allow_groups === false) {
            this.settings.allow_groups = 0;
        } else if (this.settings.allow_groups === true) {
            this.settings.allow_groups = -1;
        }
        Object.keys(this.templates).forEach(function(tpl) {
            if (!this.templates[tpl]) {
                this.templates[tpl] = QueryBuilder.templates[tpl];
            }
            if (typeof this.templates[tpl] == "string") {
                this.templates[tpl] = doT.template(this.templates[tpl]);
            }
        }, this);
        if (!this.$el.attr("id")) {
            this.$el.attr("id", "qb_" + Math.floor(Math.random() * 99999));
            this.status.generated_id = true;
        }
        this.status.id = this.$el.attr("id");
        this.$el.addClass("query-builder form-inline");
        this.filters = this.checkFilters(this.filters);
        this.operators = this.checkOperators(this.operators);
        this.bindEvents();
        this.initPlugins();
    };
    $.extend(QueryBuilder.prototype, {
        trigger: function(type) {
            var event = new $.Event(this._tojQueryEvent(type), {
                builder: this
            });
            this.$el.triggerHandler(event, Array.prototype.slice.call(arguments, 1));
            return event;
        },
        change: function(type, value) {
            var event = new $.Event(this._tojQueryEvent(type, true), {
                builder: this,
                value: value
            });
            this.$el.triggerHandler(event, Array.prototype.slice.call(arguments, 2));
            return event.value;
        },
        on: function(type, cb) {
            this.$el.on(this._tojQueryEvent(type), cb);
            return this;
        },
        off: function(type, cb) {
            this.$el.off(this._tojQueryEvent(type), cb);
            return this;
        },
        once: function(type, cb) {
            this.$el.one(this._tojQueryEvent(type), cb);
            return this;
        },
        _tojQueryEvent: function(name, filter) {
            return name.split(" ").map(function(type) {
                return type + ".queryBuilder" + (filter ? ".filter" : "");
            }).join(" ");
        }
    });
    QueryBuilder.types = {
        string: "string",
        integer: "number",
        double: "number",
        date: "datetime",
        time: "datetime",
        datetime: "datetime",
        boolean: "boolean"
    };
    QueryBuilder.inputs = [ "text", "number", "textarea", "radio", "checkbox", "select" ];
    QueryBuilder.modifiable_options = [ "display_errors", "allow_groups", "allow_empty", "default_condition", "default_filter" ];
    QueryBuilder.selectors = {
        group_container: ".rules-group-container",
        rule_container: ".rule-container",
        filter_container: ".rule-filter-container",
        operator_container: ".rule-operator-container",
        value_container: ".rule-value-container",
        error_container: ".error-container",
        condition_container: ".rules-group-header .group-conditions",
        rule_header: ".rule-header",
        group_header: ".rules-group-header",
        group_actions: ".group-actions",
        rule_actions: ".rule-actions",
        rules_list: ".rules-group-body>.rules-list",
        group_btns: ".btn",
        group_condition: ".rules-group-header [name$=_cond]",
        rule_filter: ".rule-filter-container [name$=_filter]",
        rule_operator: ".rule-operator-container [name$=_operator]",
        rule_value: ".rule-value-container :input:not(.icon-help)",
        add_rule: "[data-add=rule]",
        delete_rule: "[data-delete=rule]",
        add_group: "[data-add=group]",
        delete_group: "[data-delete=group]"
    };
    QueryBuilder.templates = {};
    QueryBuilder.regional = {};
    QueryBuilder.OPERATORS = {
        equal: {
            type: "equal",
            nb_inputs: 1,
            multiple: false,
            apply_to: [ "string", "number", "datetime", "boolean" ]
        },
        not_equal: {
            type: "not_equal",
            nb_inputs: 1,
            multiple: false,
            apply_to: [ "string", "number", "datetime", "boolean" ]
        },
        in: {
            type: "in",
            nb_inputs: 1,
            multiple: true,
            apply_to: [ "string", "number", "datetime" ]
        },
        not_in: {
            type: "not_in",
            nb_inputs: 1,
            multiple: true,
            apply_to: [ "string", "number", "datetime" ]
        },
        less: {
            type: "less",
            nb_inputs: 1,
            multiple: false,
            apply_to: [ "number", "datetime" ]
        },
        less_or_equal: {
            type: "less_or_equal",
            nb_inputs: 1,
            multiple: false,
            apply_to: [ "number", "datetime" ]
        },
        greater: {
            type: "greater",
            nb_inputs: 1,
            multiple: false,
            apply_to: [ "number", "datetime" ]
        },
        greater_or_equal: {
            type: "greater_or_equal",
            nb_inputs: 1,
            multiple: false,
            apply_to: [ "number", "datetime" ]
        },
        between: {
            type: "between",
            nb_inputs: 2,
            multiple: false,
            apply_to: [ "number", "datetime" ]
        },
        not_between: {
            type: "not_between",
            nb_inputs: 2,
            multiple: false,
            apply_to: [ "number", "datetime" ]
        },
        begins_with: {
            type: "begins_with",
            nb_inputs: 1,
            multiple: false,
            apply_to: [ "string" ]
        },
        not_begins_with: {
            type: "not_begins_with",
            nb_inputs: 1,
            multiple: false,
            apply_to: [ "string" ]
        },
        contains: {
            type: "contains",
            nb_inputs: 1,
            multiple: false,
            apply_to: [ "string" ]
        },
        not_contains: {
            type: "not_contains",
            nb_inputs: 1,
            multiple: false,
            apply_to: [ "string" ]
        },
        ends_with: {
            type: "ends_with",
            nb_inputs: 1,
            multiple: false,
            apply_to: [ "string" ]
        },
        not_ends_with: {
            type: "not_ends_with",
            nb_inputs: 1,
            multiple: false,
            apply_to: [ "string" ]
        },
        is_empty: {
            type: "is_empty",
            nb_inputs: 0,
            multiple: false,
            apply_to: [ "string" ]
        },
        is_not_empty: {
            type: "is_not_empty",
            nb_inputs: 0,
            multiple: false,
            apply_to: [ "string" ]
        },
        is_null: {
            type: "is_null",
            nb_inputs: 0,
            multiple: false,
            apply_to: [ "string", "number", "datetime", "boolean" ]
        },
        is_not_null: {
            type: "is_not_null",
            nb_inputs: 0,
            multiple: false,
            apply_to: [ "string", "number", "datetime", "boolean" ]
        }
    };
    QueryBuilder.DEFAULTS = {
        filters: [],
        plugins: [],
        sort_filters: false,
        display_errors: true,
        allow_groups: -1,
        allow_empty: false,
        conditions: [ "AND", "OR" ],
        default_condition: "AND",
        inputs_separator: " , ",
        select_placeholder: "------",
        display_empty_filter: true,
        default_filter: null,
        optgroups: {},
        default_rule_flags: {
            filter_readonly: false,
            operator_readonly: false,
            value_readonly: false,
            no_delete: false
        },
        default_group_flags: {
            condition_readonly: false,
            no_add_rule: false,
            no_add_group: false,
            no_delete: false
        },
        templates: {
            group: null,
            rule: null,
            filterSelect: null,
            operatorSelect: null,
            ruleValueSelect: null
        },
        lang_code: "en",
        lang: {},
        operators: [ "equal", "not_equal", "in", "not_in", "less", "less_or_equal", "greater", "greater_or_equal", "between", "not_between", "begins_with", "not_begins_with", "contains", "not_contains", "ends_with", "not_ends_with", "is_empty", "is_not_empty", "is_null", "is_not_null" ],
        icons: {
            add_group: "glyphicon glyphicon-plus-sign",
            add_rule: "glyphicon glyphicon-plus",
            remove_group: "glyphicon glyphicon-remove",
            remove_rule: "glyphicon glyphicon-remove",
            error: "glyphicon glyphicon-warning-sign"
        }
    };
    QueryBuilder.plugins = {};
    QueryBuilder.defaults = function(options) {
        if (typeof options == "object") {
            $.extendext(true, "replace", QueryBuilder.DEFAULTS, options);
        } else if (typeof options == "string") {
            if (typeof QueryBuilder.DEFAULTS[options] == "object") {
                return $.extend(true, {}, QueryBuilder.DEFAULTS[options]);
            } else {
                return QueryBuilder.DEFAULTS[options];
            }
        } else {
            return $.extend(true, {}, QueryBuilder.DEFAULTS);
        }
    };
    QueryBuilder.define = function(name, fct, def) {
        QueryBuilder.plugins[name] = {
            fct: fct,
            def: def || {}
        };
    };
    QueryBuilder.extend = function(methods) {
        $.extend(QueryBuilder.prototype, methods);
    };
    QueryBuilder.prototype.initPlugins = function() {
        if (!this.plugins) {
            return;
        }
        if ($.isArray(this.plugins)) {
            var tmp = {};
            this.plugins.forEach(function(plugin) {
                tmp[plugin] = null;
            });
            this.plugins = tmp;
        }
        Object.keys(this.plugins).forEach(function(plugin) {
            if (plugin in QueryBuilder.plugins) {
                this.plugins[plugin] = $.extend(true, {}, QueryBuilder.plugins[plugin].def, this.plugins[plugin] || {});
                QueryBuilder.plugins[plugin].fct.call(this, this.plugins[plugin]);
            } else {
                Utils.error("Config", 'Unable to find plugin "{0}"', plugin);
            }
        }, this);
    };
    QueryBuilder.prototype.getPluginOptions = function(name, property) {
        var plugin;
        if (this.plugins && this.plugins[name]) {
            plugin = this.plugins[name];
        } else if (QueryBuilder.plugins[name]) {
            plugin = QueryBuilder.plugins[name].def;
        }
        if (plugin) {
            if (property) {
                return plugin[property];
            } else {
                return plugin;
            }
        } else {
            Utils.error("Config", 'Unable to find plugin "{0}"', name);
        }
    };
    QueryBuilder.prototype.init = function(rules) {
        this.trigger("afterInit");
        if (rules) {
            this.setRules(rules);
            delete this.settings.rules;
        } else {
            this.setRoot(true);
        }
    };
    QueryBuilder.prototype.checkFilters = function(filters) {
        var definedFilters = [];
        if (!filters || filters.length === 0) {
            Utils.error("Config", "Missing filters list");
        }
        filters.forEach(function(filter, i) {
            if (!filter.id) {
                Utils.error("Config", "Missing filter {0} id", i);
            }
            if (definedFilters.indexOf(filter.id) != -1) {
                Utils.error("Config", 'Filter "{0}" already defined', filter.id);
            }
            definedFilters.push(filter.id);
            if (!filter.type) {
                filter.type = "string";
            } else if (!QueryBuilder.types[filter.type]) {
                Utils.error("Config", 'Invalid type "{0}"', filter.type);
            }
            if (!filter.input) {
                filter.input = QueryBuilder.types[filter.type] === "number" ? "number" : "text";
            } else if (typeof filter.input != "function" && QueryBuilder.inputs.indexOf(filter.input) == -1) {
                Utils.error("Config", 'Invalid input "{0}"', filter.input);
            }
            if (filter.operators) {
                filter.operators.forEach(function(operator) {
                    if (typeof operator != "string") {
                        Utils.error("Config", "Filter operators must be global operators types (string)");
                    }
                });
            }
            if (!filter.field) {
                filter.field = filter.id;
            }
            if (!filter.label) {
                filter.label = filter.field;
            }
            if (!filter.optgroup) {
                filter.optgroup = null;
            } else {
                this.status.has_optgroup = true;
                if (!this.settings.optgroups[filter.optgroup]) {
                    this.settings.optgroups[filter.optgroup] = filter.optgroup;
                }
            }
            switch (filter.input) {
              case "radio":
              case "checkbox":
                if (!filter.values || filter.values.length < 1) {
                    Utils.error("Config", 'Missing filter "{0}" values', filter.id);
                }
                break;

              case "select":
                var cleanValues = [];
                filter.has_optgroup = false;
                Utils.iterateOptions(filter.values, function(value, label, optgroup) {
                    cleanValues.push({
                        value: value,
                        label: label,
                        optgroup: optgroup || null
                    });
                    if (optgroup) {
                        filter.has_optgroup = true;
                        if (!this.settings.optgroups[optgroup]) {
                            this.settings.optgroups[optgroup] = optgroup;
                        }
                    }
                }.bind(this));
                if (filter.has_optgroup) {
                    filter.values = Utils.groupSort(cleanValues, "optgroup");
                } else {
                    filter.values = cleanValues;
                }
                if (filter.placeholder) {
                    if (filter.placeholder_value === undefined) {
                        filter.placeholder_value = -1;
                    }
                    filter.values.forEach(function(entry) {
                        if (entry.value == filter.placeholder_value) {
                            Utils.error("Config", 'Placeholder of filter "{0}" overlaps with one of its values', filter.id);
                        }
                    });
                }
                break;
            }
        }, this);
        if (this.settings.sort_filters) {
            if (typeof this.settings.sort_filters == "function") {
                filters.sort(this.settings.sort_filters);
            } else {
                var self = this;
                filters.sort(function(a, b) {
                    return self.translate(a.label).localeCompare(self.translate(b.label));
                });
            }
        }
        if (this.status.has_optgroup) {
            filters = Utils.groupSort(filters, "optgroup");
        }
        return filters;
    };
    QueryBuilder.prototype.checkOperators = function(operators) {
        var definedOperators = [];
        operators.forEach(function(operator, i) {
            if (typeof operator == "string") {
                if (!QueryBuilder.OPERATORS[operator]) {
                    Utils.error("Config", 'Unknown operator "{0}"', operator);
                }
                operators[i] = operator = $.extendext(true, "replace", {}, QueryBuilder.OPERATORS[operator]);
            } else {
                if (!operator.type) {
                    Utils.error("Config", 'Missing "type" for operator {0}', i);
                }
                if (QueryBuilder.OPERATORS[operator.type]) {
                    operators[i] = operator = $.extendext(true, "replace", {}, QueryBuilder.OPERATORS[operator.type], operator);
                }
                if (operator.nb_inputs === undefined || operator.apply_to === undefined) {
                    Utils.error("Config", 'Missing "nb_inputs" and/or "apply_to" for operator "{0}"', operator.type);
                }
            }
            if (definedOperators.indexOf(operator.type) != -1) {
                Utils.error("Config", 'Operator "{0}" already defined', operator.type);
            }
            definedOperators.push(operator.type);
            if (!operator.optgroup) {
                operator.optgroup = null;
            } else {
                this.status.has_operator_optgroup = true;
                if (!this.settings.optgroups[operator.optgroup]) {
                    this.settings.optgroups[operator.optgroup] = operator.optgroup;
                }
            }
        }, this);
        if (this.status.has_operator_optgroup) {
            operators = Utils.groupSort(operators, "optgroup");
        }
        return operators;
    };
    QueryBuilder.prototype.bindEvents = function() {
        var self = this;
        var Selectors = QueryBuilder.selectors;
        this.$el.on("change.queryBuilder", Selectors.group_condition, function() {
            if ($(this).is(":checked")) {
                var $group = $(this).closest(Selectors.group_container);
                self.getModel($group).condition = $(this).val();
            }
        });
        this.$el.on("change.queryBuilder", Selectors.rule_filter, function() {
            var $rule = $(this).closest(Selectors.rule_container);
            self.getModel($rule).filter = self.getFilterById($(this).val());
        });
        this.$el.on("change.queryBuilder", Selectors.rule_operator, function() {
            var $rule = $(this).closest(Selectors.rule_container);
            self.getModel($rule).operator = self.getOperatorByType($(this).val());
        });
        this.$el.on("click.queryBuilder", Selectors.add_rule, function() {
            var $group = $(this).closest(Selectors.group_container);
            self.addRule(self.getModel($group));
        });
        this.$el.on("click.queryBuilder", Selectors.delete_rule, function() {
            var $rule = $(this).closest(Selectors.rule_container);
            self.deleteRule(self.getModel($rule));
        });
        if (this.settings.allow_groups !== 0) {
            this.$el.on("click.queryBuilder", Selectors.add_group, function() {
                var $group = $(this).closest(Selectors.group_container);
                self.addGroup(self.getModel($group));
            });
            this.$el.on("click.queryBuilder", Selectors.delete_group, function() {
                var $group = $(this).closest(Selectors.group_container);
                self.deleteGroup(self.getModel($group));
            });
        }
        this.model.on({
            drop: function(e, node) {
                node.$el.remove();
                self.refreshGroupsConditions();
            },
            add: function(e, parent, node, index) {
                if (index === 0) {
                    node.$el.prependTo(parent.$el.find(">" + QueryBuilder.selectors.rules_list));
                } else {
                    node.$el.insertAfter(parent.rules[index - 1].$el);
                }
                self.refreshGroupsConditions();
            },
            move: function(e, node, group, index) {
                node.$el.detach();
                if (index === 0) {
                    node.$el.prependTo(group.$el.find(">" + QueryBuilder.selectors.rules_list));
                } else {
                    node.$el.insertAfter(group.rules[index - 1].$el);
                }
                self.refreshGroupsConditions();
            },
            update: function(e, node, field, value, oldValue) {
                if (node instanceof Rule) {
                    switch (field) {
                      case "error":
                        self.updateError(node);
                        break;

                      case "flags":
                        self.applyRuleFlags(node);
                        break;

                      case "filter":
                        self.updateRuleFilter(node, oldValue);
                        break;

                      case "operator":
                        self.updateRuleOperator(node, oldValue);
                        break;

                      case "value":
                        self.updateRuleValue(node, oldValue);
                        break;
                    }
                } else {
                    switch (field) {
                      case "error":
                        self.updateError(node);
                        break;

                      case "flags":
                        self.applyGroupFlags(node);
                        break;

                      case "condition":
                        self.updateGroupCondition(node, oldValue);
                        break;
                    }
                }
            }
        });
    };
    QueryBuilder.prototype.setRoot = function(addRule, data, flags) {
        addRule = addRule === undefined || addRule === true;
        var group_id = this.nextGroupId();
        var $group = $(this.getGroupTemplate(group_id, 1));
        $group.find(QueryBuilder.selectors.group_btns).addClass(this.settings.readonly ? "disabled" : "");
        this.$el.append($group);
        this.model.root = new Group(null, $group);
        this.model.root.model = this.model;
        this.model.root.data = data;
        this.model.root.flags = $.extend({}, this.settings.default_group_flags, flags);
        this.model.root.condition = this.settings.default_condition;
        this.trigger("afterAddGroup", this.model.root);
        if (addRule) {
            this.addRule(this.model.root);
        }
        return this.model.root;
    };
    QueryBuilder.prototype.addGroup = function(parent, addRule, data, flags) {
        addRule = addRule === undefined || addRule === true;
        var level = parent.level + 1;
        var e = this.trigger("beforeAddGroup", parent, addRule, level);
        if (e.isDefaultPrevented()) {
            return null;
        }
        var group_id = this.nextGroupId();
        var $group = $(this.getGroupTemplate(group_id, level));
        var model = parent.addGroup($group);
        model.data = data;
        model.flags = $.extend({}, this.settings.default_group_flags, flags);
        model.condition = this.settings.default_condition;
        this.trigger("afterAddGroup", model);
        this.trigger("rulesChanged");
        if (addRule) {
            this.addRule(model);
        }
        return model;
    };
    QueryBuilder.prototype.deleteGroup = function(group) {
        if (group.isRoot()) {
            return false;
        }
        var e = this.trigger("beforeDeleteGroup", group);
        if (e.isDefaultPrevented()) {
            return false;
        }
        var del = true;
        group.each("reverse", function(rule) {
            del &= this.deleteRule(rule);
        }, function(group) {
            del &= this.deleteGroup(group);
        }, this);
        if (del) {
            group.drop();
            this.trigger("afterDeleteGroup");
            this.trigger("rulesChanged");
        }
        return del;
    };
    QueryBuilder.prototype.updateGroupCondition = function(group, previousCondition) {
        group.$el.find(">" + QueryBuilder.selectors.group_condition).each(function() {
            var $this = $(this);
            $this.prop("checked", $this.val() === group.condition);
            $this.parent().toggleClass("active", $this.val() === group.condition);
        });
        this.trigger("afterUpdateGroupCondition", group, previousCondition);
        this.trigger("rulesChanged");
    };
    QueryBuilder.prototype.refreshGroupsConditions = function() {
        (function walk(group) {
            if (!group.flags || group.flags && !group.flags.condition_readonly) {
                group.$el.find(">" + QueryBuilder.selectors.group_condition).prop("disabled", group.rules.length <= 1).parent().toggleClass("disabled", group.rules.length <= 1);
            }
            group.each(null, function(group) {
                walk(group);
            }, this);
        })(this.model.root);
    };
    QueryBuilder.prototype.addRule = function(parent, data, flags) {
        var e = this.trigger("beforeAddRule", parent);
        if (e.isDefaultPrevented()) {
            return null;
        }
        var rule_id = this.nextRuleId();
        var $rule = $(this.getRuleTemplate(rule_id));
        var model = parent.addRule($rule);
        model.data = data;
        model.flags = $.extend({}, this.settings.default_rule_flags, flags);
        this.trigger("afterAddRule", model);
        this.trigger("rulesChanged");
        this.createRuleFilters(model);
        if (this.settings.default_filter || !this.settings.display_empty_filter) {
            model.filter = this.change("getDefaultFilter", this.getFilterById(this.settings.default_filter || this.filters[0].id), model);
        }
        return model;
    };
    QueryBuilder.prototype.deleteRule = function(rule) {
        if (rule.flags.no_delete) {
            return false;
        }
        var e = this.trigger("beforeDeleteRule", rule);
        if (e.isDefaultPrevented()) {
            return false;
        }
        rule.drop();
        this.trigger("afterDeleteRule");
        this.trigger("rulesChanged");
        return true;
    };
    QueryBuilder.prototype.createRuleFilters = function(rule) {
        var filters = this.change("getRuleFilters", this.filters, rule);
        var $filterSelect = $(this.getRuleFilterSelect(rule, filters));
        rule.$el.find(QueryBuilder.selectors.filter_container).html($filterSelect);
        this.trigger("afterCreateRuleFilters", rule);
        this.applyRuleFlags(rule);
    };
    QueryBuilder.prototype.createRuleOperators = function(rule) {
        var $operatorContainer = rule.$el.find(QueryBuilder.selectors.operator_container).empty();
        if (!rule.filter) {
            return;
        }
        var operators = this.getOperators(rule.filter);
        var $operatorSelect = $(this.getRuleOperatorSelect(rule, operators));
        $operatorContainer.html($operatorSelect);
        if (rule.filter.default_operator) {
            rule.__.operator = this.getOperatorByType(rule.filter.default_operator);
        } else {
            rule.__.operator = operators[0];
        }
        rule.$el.find(QueryBuilder.selectors.rule_operator).val(rule.operator.type);
        this.trigger("afterCreateRuleOperators", rule, operators);
        this.applyRuleFlags(rule);
    };
    QueryBuilder.prototype.createRuleInput = function(rule) {
        var $valueContainer = rule.$el.find(QueryBuilder.selectors.value_container).empty();
        rule.__.value = undefined;
        if (!rule.filter || !rule.operator || rule.operator.nb_inputs === 0) {
            return;
        }
        var self = this;
        var $inputs = $();
        var filter = rule.filter;
        for (var i = 0; i < rule.operator.nb_inputs; i++) {
            var $ruleInput = $(this.getRuleInput(rule, i));
            if (i > 0) $valueContainer.append(this.settings.inputs_separator);
            $valueContainer.append($ruleInput);
            $inputs = $inputs.add($ruleInput);
        }
        $valueContainer.css("display", "");
        $inputs.on("change " + (filter.input_event || ""), function() {
            if (!rule._updating_input) {
                rule._updating_value = true;
                rule.value = self.getRuleInputValue(rule);
                rule._updating_value = false;
            }
        });
        if (filter.plugin) {
            $inputs[filter.plugin](filter.plugin_config || {});
        }
        this.trigger("afterCreateRuleInput", rule);
        if (filter.default_value !== undefined) {
            rule.value = filter.default_value;
        } else {
            rule._updating_value = true;
            rule.value = self.getRuleInputValue(rule);
            rule._updating_value = false;
        }
        this.applyRuleFlags(rule);
    };
    QueryBuilder.prototype.updateRuleFilter = function(rule, previousFilter) {
        this.createRuleOperators(rule);
        this.createRuleInput(rule);
        rule.$el.find(QueryBuilder.selectors.rule_filter).val(rule.filter ? rule.filter.id : "-1");
        if (previousFilter && rule.filter && previousFilter.id !== rule.filter.id) {
            rule.data = undefined;
        }
        this.trigger("afterUpdateRuleFilter", rule, previousFilter);
        this.trigger("rulesChanged");
    };
    QueryBuilder.prototype.updateRuleOperator = function(rule, previousOperator) {
        var $valueContainer = rule.$el.find(QueryBuilder.selectors.value_container);
        if (!rule.operator || rule.operator.nb_inputs === 0) {
            $valueContainer.hide();
            rule.__.value = undefined;
        } else {
            $valueContainer.css("display", "");
            if ($valueContainer.is(":empty") || !previousOperator || rule.operator.nb_inputs !== previousOperator.nb_inputs || rule.operator.optgroup !== previousOperator.optgroup) {
                this.createRuleInput(rule);
            }
        }
        if (rule.operator) {
            rule.$el.find(QueryBuilder.selectors.rule_operator).val(rule.operator.type);
            rule.__.value = this.getRuleInputValue(rule);
        }
        this.trigger("afterUpdateRuleOperator", rule, previousOperator);
        this.trigger("rulesChanged");
    };
    QueryBuilder.prototype.updateRuleValue = function(rule, previousValue) {
        if (!rule._updating_value) {
            this.setRuleInputValue(rule, rule.value);
        }
        this.trigger("afterUpdateRuleValue", rule, previousValue);
        this.trigger("rulesChanged");
    };
    QueryBuilder.prototype.applyRuleFlags = function(rule) {
        var flags = rule.flags;
        var Selectors = QueryBuilder.selectors;
        rule.$el.find(Selectors.rule_filter).prop("disabled", flags.filter_readonly);
        rule.$el.find(Selectors.rule_operator).prop("disabled", flags.operator_readonly);
        rule.$el.find(Selectors.rule_value).prop("disabled", flags.value_readonly);
        if (flags.no_delete) {
            rule.$el.find(Selectors.delete_rule).remove();
        }
        this.trigger("afterApplyRuleFlags", rule);
    };
    QueryBuilder.prototype.applyGroupFlags = function(group) {
        var flags = group.flags;
        var Selectors = QueryBuilder.selectors;
        group.$el.find(">" + Selectors.group_condition).prop("disabled", flags.condition_readonly).parent().toggleClass("readonly", flags.condition_readonly);
        if (flags.no_add_rule) {
            group.$el.find(Selectors.add_rule).remove();
        }
        if (flags.no_add_group) {
            group.$el.find(Selectors.add_group).remove();
        }
        if (flags.no_delete) {
            group.$el.find(Selectors.delete_group).remove();
        }
        this.trigger("afterApplyGroupFlags", group);
    };
    QueryBuilder.prototype.clearErrors = function(node) {
        node = node || this.model.root;
        if (!node) {
            return;
        }
        node.error = null;
        if (node instanceof Group) {
            node.each(function(rule) {
                rule.error = null;
            }, function(group) {
                this.clearErrors(group);
            }, this);
        }
    };
    QueryBuilder.prototype.updateError = function(node) {
        if (this.settings.display_errors) {
            if (node.error === null) {
                node.$el.removeClass("has-error");
            } else {
                var errorMessage = this.translate("errors", node.error[0]);
                errorMessage = Utils.fmt(errorMessage, node.error.slice(1));
                errorMessage = this.change("displayError", errorMessage, node.error, node);
                node.$el.addClass("has-error").find(QueryBuilder.selectors.error_container).eq(0).attr("title", errorMessage);
            }
        }
    };
    QueryBuilder.prototype.triggerValidationError = function(node, error, value) {
        if (!$.isArray(error)) {
            error = [ error ];
        }
        var e = this.trigger("validationError", node, error, value);
        if (!e.isDefaultPrevented()) {
            node.error = error;
        }
    };
    QueryBuilder.prototype.destroy = function() {
        this.trigger("beforeDestroy");
        if (this.status.generated_id) {
            this.$el.removeAttr("id");
        }
        this.clear();
        this.model = null;
        this.$el.off(".queryBuilder").removeClass("query-builder").removeData("queryBuilder");
        delete this.$el[0].queryBuilder;
    };
    QueryBuilder.prototype.reset = function() {
        var e = this.trigger("beforeReset");
        if (e.isDefaultPrevented()) {
            return;
        }
        this.status.group_id = 1;
        this.status.rule_id = 0;
        this.model.root.empty();
        this.model.root.data = undefined;
        this.model.root.flags = $.extend({}, this.settings.default_group_flags);
        this.model.root.condition = this.settings.default_condition;
        this.addRule(this.model.root);
        this.trigger("afterReset");
        this.trigger("rulesChanged");
    };
    QueryBuilder.prototype.clear = function() {
        var e = this.trigger("beforeClear");
        if (e.isDefaultPrevented()) {
            return;
        }
        this.status.group_id = 0;
        this.status.rule_id = 0;
        if (this.model.root) {
            this.model.root.drop();
            this.model.root = null;
        }
        this.trigger("afterClear");
        this.trigger("rulesChanged");
    };
    QueryBuilder.prototype.setOptions = function(options) {
        $.each(options, function(opt, value) {
            if (QueryBuilder.modifiable_options.indexOf(opt) !== -1) {
                this.settings[opt] = value;
            }
        }.bind(this));
    };
    QueryBuilder.prototype.getModel = function(target) {
        if (!target) {
            return this.model.root;
        } else if (target instanceof Node) {
            return target;
        } else {
            return $(target).data("queryBuilderModel");
        }
    };
    QueryBuilder.prototype.validate = function(options) {
        options = $.extend({
            skip_empty: false
        }, options);
        this.clearErrors();
        var self = this;
        var valid = function parse(group) {
            var done = 0;
            var errors = 0;
            group.each(function(rule) {
                if (!rule.filter && options.skip_empty) {
                    return;
                }
                if (!rule.filter) {
                    self.triggerValidationError(rule, "no_filter", null);
                    errors++;
                    return;
                }
                if (!rule.operator) {
                    self.triggerValidationError(rule, "no_operator", null);
                    errors++;
                    return;
                }
                if (rule.operator.nb_inputs !== 0) {
                    var valid = self.validateValue(rule, rule.value);
                    if (valid !== true) {
                        self.triggerValidationError(rule, valid, rule.value);
                        errors++;
                        return;
                    }
                }
                done++;
            }, function(group) {
                var res = parse(group);
                if (res === true) {
                    done++;
                } else if (res === false) {
                    errors++;
                }
            });
            if (errors > 0) {
                return false;
            } else if (done === 0 && !group.isRoot() && options.skip_empty) {
                return null;
            } else if (done === 0 && (!self.settings.allow_empty || !group.isRoot())) {
                self.triggerValidationError(group, "empty_group", null);
                return false;
            }
            return true;
        }(this.model.root);
        return this.change("validate", valid);
    };
    QueryBuilder.prototype.getRules = function(options) {
        options = $.extend({
            get_flags: false,
            allow_invalid: false,
            skip_empty: false
        }, options);
        var valid = this.validate(options);
        if (!valid && !options.allow_invalid) {
            return null;
        }
        var self = this;
        var out = function parse(group) {
            var groupData = {
                condition: group.condition,
                rules: []
            };
            if (group.data) {
                groupData.data = $.extendext(true, "replace", {}, group.data);
            }
            if (options.get_flags) {
                var flags = self.getGroupFlags(group.flags, options.get_flags === "all");
                if (!$.isEmptyObject(flags)) {
                    groupData.flags = flags;
                }
            }
            group.each(function(rule) {
                if (!rule.filter && options.skip_empty) {
                    return;
                }
                var value = null;
                if (!rule.operator || rule.operator.nb_inputs !== 0) {
                    value = rule.value;
                }
                var ruleData = {
                    id: rule.filter ? rule.filter.id : null,
                    field: rule.filter ? rule.filter.field : null,
                    type: rule.filter ? rule.filter.type : null,
                    input: rule.filter ? rule.filter.input : null,
                    operator: rule.operator ? rule.operator.type : null,
                    value: value
                };
                if (rule.filter && rule.filter.data || rule.data) {
                    ruleData.data = $.extendext(true, "replace", {}, rule.filter.data, rule.data);
                }
                if (options.get_flags) {
                    var flags = self.getRuleFlags(rule.flags, options.get_flags === "all");
                    if (!$.isEmptyObject(flags)) {
                        ruleData.flags = flags;
                    }
                }
                groupData.rules.push(self.change("ruleToJson", ruleData, rule));
            }, function(model) {
                var data = parse(model);
                if (data.rules.length !== 0 || !options.skip_empty) {
                    groupData.rules.push(data);
                }
            }, this);
            return self.change("groupToJson", groupData, group);
        }(this.model.root);
        out.valid = valid;
        return this.change("getRules", out);
    };
    QueryBuilder.prototype.setRules = function(data, options) {
        options = $.extend({
            allow_invalid: false
        }, options);
        if ($.isArray(data)) {
            data = {
                condition: this.settings.default_condition,
                rules: data
            };
        }
        if (!data || !data.rules || data.rules.length === 0 && !this.settings.allow_empty) {
            Utils.error("RulesParse", "Incorrect data object passed");
        }
        this.clear();
        this.setRoot(false, data.data, this.parseGroupFlags(data));
        data = this.change("setRules", data, options);
        var self = this;
        (function add(data, group) {
            if (group === null) {
                return;
            }
            if (data.condition === undefined) {
                data.condition = self.settings.default_condition;
            } else if (self.settings.conditions.indexOf(data.condition) == -1) {
                Utils.error(!options.allow_invalid, "UndefinedCondition", 'Invalid condition "{0}"', data.condition);
                data.condition = self.settings.default_condition;
            }
            group.condition = data.condition;
            data.rules.forEach(function(item) {
                var model;
                if (item.rules !== undefined) {
                    if (self.settings.allow_groups !== -1 && self.settings.allow_groups < group.level) {
                        Utils.error(!options.allow_invalid, "RulesParse", "No more than {0} groups are allowed", self.settings.allow_groups);
                        self.reset();
                    } else {
                        model = self.addGroup(group, false, item.data, self.parseGroupFlags(item));
                        if (model === null) {
                            return;
                        }
                        add(item, model);
                    }
                } else {
                    if (!item.empty) {
                        if (item.id === undefined) {
                            Utils.error(!options.allow_invalid, "RulesParse", "Missing rule field id");
                            item.empty = true;
                        }
                        if (item.operator === undefined) {
                            item.operator = "equal";
                        }
                    }
                    model = self.addRule(group, item.data, self.parseRuleFlags(item));
                    if (model === null) {
                        return;
                    }
                    if (!item.empty) {
                        model.filter = self.getFilterById(item.id, !options.allow_invalid);
                    }
                    if (model.filter) {
                        model.operator = self.getOperatorByType(item.operator, !options.allow_invalid);
                        if (!model.operator) {
                            model.operator = self.getOperators(model.filter)[0];
                        }
                    }
                    if (model.operator && model.operator.nb_inputs !== 0) {
                        if (item.value !== undefined) {
                            model.value = item.value;
                        } else if (model.filter.default_value !== undefined) {
                            model.value = model.filter.default_value;
                        }
                    }
                    if (self.change("jsonToRule", model, item) != model) {
                        Utils.error("RulesParse", "Plugin tried to change rule reference");
                    }
                }
            });
            if (self.change("jsonToGroup", group, data) != group) {
                Utils.error("RulesParse", "Plugin tried to change group reference");
            }
        })(data, this.model.root);
        this.trigger("afterSetRules");
    };
    QueryBuilder.prototype.validateValue = function(rule, value) {
        var validation = rule.filter.validation || {};
        var result = true;
        if (validation.callback) {
            result = validation.callback.call(this, value, rule);
        } else {
            result = this._validateValue(rule, value);
        }
        return this.change("validateValue", result, value, rule);
    };
    QueryBuilder.prototype._validateValue = function(rule, value) {
        var filter = rule.filter;
        var operator = rule.operator;
        var validation = filter.validation || {};
        var result = true;
        var tmp, tempValue;
        if (rule.operator.nb_inputs === 1) {
            value = [ value ];
        }
        for (var i = 0; i < operator.nb_inputs; i++) {
            if (!operator.multiple && $.isArray(value[i]) && value[i].length > 1) {
                result = [ "operator_not_multiple", operator.type, this.translate("operators", operator.type) ];
                break;
            }
            switch (filter.input) {
              case "radio":
                if (value[i] === undefined || value[i].length === 0) {
                    if (!validation.allow_empty_value) {
                        result = [ "radio_empty" ];
                    }
                    break;
                }
                break;

              case "checkbox":
                if (value[i] === undefined || value[i].length === 0) {
                    if (!validation.allow_empty_value) {
                        result = [ "checkbox_empty" ];
                    }
                    break;
                }
                break;

              case "select":
                if (value[i] === undefined || value[i].length === 0 || filter.placeholder && value[i] == filter.placeholder_value) {
                    if (!validation.allow_empty_value) {
                        result = [ "select_empty" ];
                    }
                    break;
                }
                break;

              default:
                tempValue = $.isArray(value[i]) ? value[i] : [ value[i] ];
                for (var j = 0; j < tempValue.length; j++) {
                    switch (QueryBuilder.types[filter.type]) {
                      case "string":
                        if (tempValue[j] === undefined || tempValue[j].length === 0) {
                            if (!validation.allow_empty_value) {
                                result = [ "string_empty" ];
                            }
                            break;
                        }
                        if (validation.min !== undefined) {
                            if (tempValue[j].length < parseInt(validation.min)) {
                                result = [ this.getValidationMessage(validation, "min", "string_exceed_min_length"), validation.min ];
                                break;
                            }
                        }
                        if (validation.max !== undefined) {
                            if (tempValue[j].length > parseInt(validation.max)) {
                                result = [ this.getValidationMessage(validation, "max", "string_exceed_max_length"), validation.max ];
                                break;
                            }
                        }
                        if (validation.format) {
                            if (typeof validation.format == "string") {
                                validation.format = new RegExp(validation.format);
                            }
                            if (!validation.format.test(tempValue[j])) {
                                result = [ this.getValidationMessage(validation, "format", "string_invalid_format"), validation.format ];
                                break;
                            }
                        }
                        break;

                      case "number":
                        if (tempValue[j] === undefined || tempValue[j].length === 0) {
                            if (!validation.allow_empty_value) {
                                result = [ "number_nan" ];
                            }
                            break;
                        }
                        if (isNaN(tempValue[j])) {
                            result = [ "number_nan" ];
                            break;
                        }
                        if (filter.type == "integer") {
                            if (parseInt(tempValue[j]) != tempValue[j]) {
                                result = [ "number_not_integer" ];
                                break;
                            }
                        } else {
                            if (parseFloat(tempValue[j]) != tempValue[j]) {
                                result = [ "number_not_double" ];
                                break;
                            }
                        }
                        if (validation.min !== undefined) {
                            if (tempValue[j] < parseFloat(validation.min)) {
                                result = [ this.getValidationMessage(validation, "min", "number_exceed_min"), validation.min ];
                                break;
                            }
                        }
                        if (validation.max !== undefined) {
                            if (tempValue[j] > parseFloat(validation.max)) {
                                result = [ this.getValidationMessage(validation, "max", "number_exceed_max"), validation.max ];
                                break;
                            }
                        }
                        if (validation.step !== undefined && validation.step !== "any") {
                            var v = (tempValue[j] / validation.step).toPrecision(14);
                            if (parseInt(v) != v) {
                                result = [ this.getValidationMessage(validation, "step", "number_wrong_step"), validation.step ];
                                break;
                            }
                        }
                        break;

                      case "datetime":
                        if (tempValue[j] === undefined || tempValue[j].length === 0) {
                            if (!validation.allow_empty_value) {
                                result = [ "datetime_empty" ];
                            }
                            break;
                        }
                        if (validation.format) {
                            if (!("moment" in window)) {
                                Utils.error("MissingLibrary", "MomentJS is required for Date/Time validation. Get it here http://momentjs.com");
                            }
                            var datetime = moment(tempValue[j], validation.format);
                            if (!datetime.isValid()) {
                                result = [ this.getValidationMessage(validation, "format", "datetime_invalid"), validation.format ];
                                break;
                            } else {
                                if (validation.min) {
                                    if (datetime < moment(validation.min, validation.format)) {
                                        result = [ this.getValidationMessage(validation, "min", "datetime_exceed_min"), validation.min ];
                                        break;
                                    }
                                }
                                if (validation.max) {
                                    if (datetime > moment(validation.max, validation.format)) {
                                        result = [ this.getValidationMessage(validation, "max", "datetime_exceed_max"), validation.max ];
                                        break;
                                    }
                                }
                            }
                        }
                        break;

                      case "boolean":
                        if (tempValue[j] === undefined || tempValue[j].length === 0) {
                            if (!validation.allow_empty_value) {
                                result = [ "boolean_not_valid" ];
                            }
                            break;
                        }
                        tmp = ("" + tempValue[j]).trim().toLowerCase();
                        if (tmp !== "true" && tmp !== "false" && tmp !== "1" && tmp !== "0" && tempValue[j] !== 1 && tempValue[j] !== 0) {
                            result = [ "boolean_not_valid" ];
                            break;
                        }
                    }
                    if (result !== true) {
                        break;
                    }
                }
            }
            if (result !== true) {
                break;
            }
        }
        if ((rule.operator.type === "between" || rule.operator.type === "not_between") && value.length === 2) {
            switch (QueryBuilder.types[filter.type]) {
              case "number":
                if (value[0] > value[1]) {
                    result = [ "number_between_invalid", value[0], value[1] ];
                }
                break;

              case "datetime":
                if (validation.format) {
                    if (!("moment" in window)) {
                        Utils.error("MissingLibrary", "MomentJS is required for Date/Time validation. Get it here http://momentjs.com");
                    }
                    if (moment(value[0], validation.format).isAfter(moment(value[1], validation.format))) {
                        result = [ "datetime_between_invalid", value[0], value[1] ];
                    }
                }
                break;
            }
        }
        return result;
    };
    QueryBuilder.prototype.nextGroupId = function() {
        return this.status.id + "_group_" + this.status.group_id++;
    };
    QueryBuilder.prototype.nextRuleId = function() {
        return this.status.id + "_rule_" + this.status.rule_id++;
    };
    QueryBuilder.prototype.getOperators = function(filter) {
        if (typeof filter == "string") {
            filter = this.getFilterById(filter);
        }
        var result = [];
        for (var i = 0, l = this.operators.length; i < l; i++) {
            if (filter.operators) {
                if (filter.operators.indexOf(this.operators[i].type) == -1) {
                    continue;
                }
            } else if (this.operators[i].apply_to.indexOf(QueryBuilder.types[filter.type]) == -1) {
                continue;
            }
            result.push(this.operators[i]);
        }
        if (filter.operators) {
            result.sort(function(a, b) {
                return filter.operators.indexOf(a.type) - filter.operators.indexOf(b.type);
            });
        }
        return this.change("getOperators", result, filter);
    };
    QueryBuilder.prototype.getFilterById = function(id, doThrow) {
        if (id == "-1") {
            return null;
        }
        for (var i = 0, l = this.filters.length; i < l; i++) {
            if (this.filters[i].id == id) {
                return this.filters[i];
            }
        }
        Utils.error(doThrow !== false, "UndefinedFilter", 'Undefined filter "{0}"', id);
        return null;
    };
    QueryBuilder.prototype.getOperatorByType = function(type, doThrow) {
        if (type == "-1") {
            return null;
        }
        for (var i = 0, l = this.operators.length; i < l; i++) {
            if (this.operators[i].type == type) {
                return this.operators[i];
            }
        }
        Utils.error(doThrow !== false, "UndefinedOperator", 'Undefined operator "{0}"', type);
        return null;
    };
    QueryBuilder.prototype.getRuleInputValue = function(rule) {
        var filter = rule.filter;
        var operator = rule.operator;
        var value = [];
        if (filter.valueGetter) {
            value = filter.valueGetter.call(this, rule);
        } else {
            var $value = rule.$el.find(QueryBuilder.selectors.value_container);
            for (var i = 0; i < operator.nb_inputs; i++) {
                var name = Utils.escapeElementId(rule.id + "_value_" + i);
                var tmp;
                switch (filter.input) {
                  case "radio":
                    value.push($value.find("[name=" + name + "]:checked").val());
                    break;

                  case "checkbox":
                    tmp = [];
                    $value.find("[name=" + name + "]:checked").each(function() {
                        tmp.push($(this).val());
                    });
                    value.push(tmp);
                    break;

                  case "select":
                    if (filter.multiple) {
                        tmp = [];
                        $value.find("[name=" + name + "] option:selected").each(function() {
                            tmp.push($(this).val());
                        });
                        value.push(tmp);
                    } else {
                        value.push($value.find("[name=" + name + "] option:selected").val());
                    }
                    break;

                  default:
                    value.push($value.find("[name=" + name + "]").val());
                }
            }
            value = value.map(function(val) {
                if (operator.multiple && filter.value_separator && typeof val == "string") {
                    val = val.split(filter.value_separator);
                }
                if ($.isArray(val)) {
                    return val.map(function(subval) {
                        return Utils.changeType(subval, filter.type);
                    });
                } else {
                    return Utils.changeType(val, filter.type);
                }
            });
            if (operator.nb_inputs === 1) {
                value = value[0];
            }
            if (filter.valueParser) {
                value = filter.valueParser.call(this, rule, value);
            }
        }
        return this.change("getRuleValue", value, rule);
    };
    QueryBuilder.prototype.setRuleInputValue = function(rule, value) {
        var filter = rule.filter;
        var operator = rule.operator;
        if (!filter || !operator) {
            return;
        }
        rule._updating_input = true;
        if (filter.valueSetter) {
            filter.valueSetter.call(this, rule, value);
        } else {
            var $value = rule.$el.find(QueryBuilder.selectors.value_container);
            if (operator.nb_inputs == 1) {
                value = [ value ];
            }
            for (var i = 0; i < operator.nb_inputs; i++) {
                var name = Utils.escapeElementId(rule.id + "_value_" + i);
                switch (filter.input) {
                  case "radio":
                    $value.find("[name=" + name + '][value="' + value[i] + '"]').prop("checked", true).trigger("change");
                    break;

                  case "checkbox":
                    if (!$.isArray(value[i])) {
                        value[i] = [ value[i] ];
                    }
                    value[i].forEach(function(value) {
                        $value.find("[name=" + name + '][value="' + value + '"]').prop("checked", true).trigger("change");
                    });
                    break;

                  default:
                    if (operator.multiple && filter.value_separator && $.isArray(value[i])) {
                        value[i] = value[i].join(filter.value_separator);
                    }
                    $value.find("[name=" + name + "]").val(value[i]).trigger("change");
                    break;
                }
            }
        }
        rule._updating_input = false;
    };
    QueryBuilder.prototype.parseRuleFlags = function(rule) {
        var flags = $.extend({}, this.settings.default_rule_flags);
        if (rule.readonly) {
            $.extend(flags, {
                header_readonly: true,
                filter_readonly: true,
                operator_readonly: true,
                value_readonly: true,
                no_delete: true,
                no_sortable: true
            });
        }
        if (rule.flags) {
            $.extend(flags, rule.flags);
        }
        return this.change("parseRuleFlags", flags, rule);
    };
    QueryBuilder.prototype.getRuleFlags = function(flags, all) {
        if (all) {
            return $.extend({}, flags);
        } else {
            var ret = {};
            $.each(this.settings.default_rule_flags, function(key, value) {
                if (flags[key] !== value) {
                    ret[key] = flags[key];
                }
            });
            return ret;
        }
    };
    QueryBuilder.prototype.parseGroupFlags = function(group) {
        var flags = $.extend({}, this.settings.default_group_flags);
        if (group.readonly) {
            $.extend(flags, {
                condition_readonly: true,
                no_add_rule: true,
                no_add_group: true,
                no_delete: true
            });
        }
        if (group.flags) {
            $.extend(flags, group.flags);
        }
        return this.change("parseGroupFlags", flags, group);
    };
    QueryBuilder.prototype.getGroupFlags = function(flags, all) {
        if (all) {
            return $.extend({}, flags);
        } else {
            var ret = {};
            $.each(this.settings.default_group_flags, function(key, value) {
                if (flags[key] !== value) {
                    ret[key] = flags[key];
                }
            });
            return ret;
        }
    };
    QueryBuilder.prototype.translate = function(category, key) {
        if (!key) {
            key = category;
            category = undefined;
        }
        var translation;
        if (typeof key === "object") {
            translation = key[this.settings.lang_code] || key["en"];
        } else {
            translation = (category ? this.lang[category] : this.lang)[key] || key;
        }
        return this.change("translate", translation, key, category);
    };
    QueryBuilder.prototype.getValidationMessage = function(validation, type, def) {
        return validation.messages && validation.messages[type] || def;
    };
    QueryBuilder.templates.group = '<div id="{{= it.group_id }}" class="rules-group-container">   <div class="rules-group-header">     <div class="btn-group pull-right group-actions">       <button type="button" class="btn btn-xs btn-success" data-add="rule">         <i class="{{= it.icons.add_rule }}"></i> {{= it.translate("add_rule") }}       </button>       {{? it.settings.allow_groups===-1 || it.settings.allow_groups>=it.level }}         <button type="button" class="btn btn-xs btn-success" data-add="group">           <i class="{{= it.icons.add_group }}"></i> {{= it.translate("add_group") }}         </button>       {{?}}       {{? it.level>1 }}         <button type="button" class="btn btn-xs btn-danger" data-delete="group">           <i class="{{= it.icons.remove_group }}"></i> {{= it.translate("delete_group") }}         </button>       {{?}}     </div>     <div class="btn-group group-conditions">       {{~ it.conditions: condition }}         <label class="btn btn-xs btn-primary">           <input type="radio" name="{{= it.group_id }}_cond" value="{{= condition }}"> {{= it.translate("conditions", condition) }}         </label>       {{~}}     </div>     {{? it.settings.display_errors }}       <div class="error-container"><i class="{{= it.icons.error }}"></i></div>     {{?}}   </div>   <div class=rules-group-body>     <div class=rules-list></div>   </div> </div>';
    QueryBuilder.templates.rule = '<div id="{{= it.rule_id }}" class="rule-container">   <div class="rule-header">     <div class="btn-group pull-right rule-actions">       <button type="button" class="btn btn-xs btn-danger" data-delete="rule">         <i class="{{= it.icons.remove_rule }}"></i> {{= it.translate("delete_rule") }}       </button>     </div>   </div>   {{? it.settings.display_errors }}     <div class="error-container"><i class="{{= it.icons.error }}"></i></div>   {{?}}   <div class="rule-filter-container"></div>   <div class="rule-operator-container"></div>   <div class="rule-value-container"></div> </div>';
    QueryBuilder.templates.filterSelect = '{{ var optgroup = null; }} <select class="form-control" name="{{= it.rule.id }}_filter">   {{? it.settings.display_empty_filter }}     <option value="-1">{{= it.settings.select_placeholder }}</option>   {{?}}   {{~ it.filters: filter }}     {{? optgroup !== filter.optgroup }}       {{? optgroup !== null }}</optgroup>{{?}}       {{? (optgroup = filter.optgroup) !== null }}         <optgroup label="{{= it.translate(it.settings.optgroups[optgroup]) }}">       {{?}}     {{?}}     <option value="{{= filter.id }}" {{? filter.icon}}data-icon="{{= filter.icon}}"{{?}}>{{= it.translate(filter.label) }}</option>   {{~}}   {{? optgroup !== null }}</optgroup>{{?}} </select>';
    QueryBuilder.templates.operatorSelect = '{{? it.operators.length === 1 }} <span> {{= it.translate("operators", it.operators[0].type) }} </span> {{?}} {{ var optgroup = null; }} <select class="form-control {{? it.operators.length === 1 }}hide{{?}}" name="{{= it.rule.id }}_operator">   {{~ it.operators: operator }}     {{? optgroup !== operator.optgroup }}       {{? optgroup !== null }}</optgroup>{{?}}       {{? (optgroup = operator.optgroup) !== null }}         <optgroup label="{{= it.translate(it.settings.optgroups[optgroup]) }}">       {{?}}     {{?}}     <option value="{{= operator.type }}" {{? operator.icon}}data-icon="{{= operator.icon}}"{{?}}>{{= it.translate("operators", operator.type) }}</option>   {{~}}   {{? optgroup !== null }}</optgroup>{{?}} </select>';
    QueryBuilder.templates.ruleValueSelect = '{{ var optgroup = null; }} <select class="form-control" name="{{= it.name }}" {{? it.rule.filter.multiple }}multiple{{?}}>   {{? it.rule.filter.placeholder }}     <option value="{{= it.rule.filter.placeholder_value }}" disabled selected>{{= it.rule.filter.placeholder }}</option>   {{?}}   {{~ it.rule.filter.values: entry }}     {{? optgroup !== entry.optgroup }}       {{? optgroup !== null }}</optgroup>{{?}}       {{? (optgroup = entry.optgroup) !== null }}         <optgroup label="{{= it.translate(it.settings.optgroups[optgroup]) }}">       {{?}}     {{?}}     <option value="{{= entry.value }}">{{= entry.label }}</option>   {{~}}   {{? optgroup !== null }}</optgroup>{{?}} </select>';
    QueryBuilder.prototype.getGroupTemplate = function(group_id, level) {
        var h = this.templates.group({
            builder: this,
            group_id: group_id,
            level: level,
            conditions: this.settings.conditions,
            icons: this.icons,
            settings: this.settings,
            translate: this.translate.bind(this)
        });
        return this.change("getGroupTemplate", h, level);
    };
    QueryBuilder.prototype.getRuleTemplate = function(rule_id) {
        var h = this.templates.rule({
            builder: this,
            rule_id: rule_id,
            icons: this.icons,
            settings: this.settings,
            translate: this.translate.bind(this)
        });
        return this.change("getRuleTemplate", h);
    };
    QueryBuilder.prototype.getRuleFilterSelect = function(rule, filters) {
        var h = this.templates.filterSelect({
            builder: this,
            rule: rule,
            filters: filters,
            icons: this.icons,
            settings: this.settings,
            translate: this.translate.bind(this)
        });
        return this.change("getRuleFilterSelect", h, rule, filters);
    };
    QueryBuilder.prototype.getRuleOperatorSelect = function(rule, operators) {
        var h = this.templates.operatorSelect({
            builder: this,
            rule: rule,
            operators: operators,
            icons: this.icons,
            settings: this.settings,
            translate: this.translate.bind(this)
        });
        return this.change("getRuleOperatorSelect", h, rule, operators);
    };
    QueryBuilder.prototype.getRuleValueSelect = function(name, rule) {
        var h = this.templates.ruleValueSelect({
            builder: this,
            name: name,
            rule: rule,
            icons: this.icons,
            settings: this.settings,
            translate: this.translate.bind(this)
        });
        return this.change("getRuleValueSelect", h, name, rule);
    };
    QueryBuilder.prototype.getRuleInput = function(rule, value_id) {
        var filter = rule.filter;
        var validation = rule.filter.validation || {};
        var name = rule.id + "_value_" + value_id;
        var c = filter.vertical ? " class=block" : "";
        var h = "";
        if (typeof filter.input == "function") {
            h = filter.input.call(this, rule, name);
        } else {
            switch (filter.input) {
              case "radio":
              case "checkbox":
                Utils.iterateOptions(filter.values, function(key, val) {
                    h += "<label" + c + '><input type="' + filter.input + '" name="' + name + '" value="' + key + '"> ' + val + "</label> ";
                });
                break;

              case "select":
                h = this.getRuleValueSelect(name, rule);
                break;

              case "textarea":
                h += '<textarea class="form-control" name="' + name + '"';
                if (filter.size) h += ' cols="' + filter.size + '"';
                if (filter.rows) h += ' rows="' + filter.rows + '"';
                if (validation.min !== undefined) h += ' minlength="' + validation.min + '"';
                if (validation.max !== undefined) h += ' maxlength="' + validation.max + '"';
                if (filter.placeholder) h += ' placeholder="' + filter.placeholder + '"';
                h += "></textarea>";
                break;

              case "number":
                h += '<input class="form-control" type="number" name="' + name + '"';
                if (validation.step !== undefined) h += ' step="' + validation.step + '"';
                if (validation.min !== undefined) h += ' min="' + validation.min + '"';
                if (validation.max !== undefined) h += ' max="' + validation.max + '"';
                if (filter.placeholder) h += ' placeholder="' + filter.placeholder + '"';
                if (filter.size) h += ' size="' + filter.size + '"';
                h += ">";
                break;

              default:
                h += '<input class="form-control" type="text" name="' + name + '"';
                if (filter.placeholder) h += ' placeholder="' + filter.placeholder + '"';
                if (filter.type === "string" && validation.min !== undefined) h += ' minlength="' + validation.min + '"';
                if (filter.type === "string" && validation.max !== undefined) h += ' maxlength="' + validation.max + '"';
                if (filter.size) h += ' size="' + filter.size + '"';
                h += ">";
            }
        }
        return this.change("getRuleInput", h, rule, name);
    };
    var Utils = {};
    QueryBuilder.utils = Utils;
    Utils.iterateOptions = function(options, tpl) {
        if (options) {
            if ($.isArray(options)) {
                options.forEach(function(entry) {
                    if ($.isPlainObject(entry)) {
                        if ("value" in entry) {
                            tpl(entry.value, entry.label || entry.value, entry.optgroup);
                        } else {
                            $.each(entry, function(key, val) {
                                tpl(key, val);
                                return false;
                            });
                        }
                    } else {
                        tpl(entry, entry);
                    }
                });
            } else {
                $.each(options, function(key, val) {
                    tpl(key, val);
                });
            }
        }
    };
    Utils.fmt = function(str, args) {
        if (!Array.isArray(args)) {
            args = Array.prototype.slice.call(arguments, 1);
        }
        return str.replace(/{([0-9]+)}/g, function(m, i) {
            return args[parseInt(i)];
        });
    };
    Utils.error = function() {
        var i = 0;
        var doThrow = typeof arguments[i] === "boolean" ? arguments[i++] : true;
        var type = arguments[i++];
        var message = arguments[i++];
        var args = Array.isArray(arguments[i]) ? arguments[i] : Array.prototype.slice.call(arguments, i);
        if (doThrow) {
            var err = new Error(Utils.fmt(message, args));
            err.name = type + "Error";
            err.args = args;
            throw err;
        } else {
            console.error(type + "Error: " + Utils.fmt(message, args));
        }
    };
    Utils.changeType = function(value, type) {
        if (value === "" || value === undefined) {
            return undefined;
        }
        switch (type) {
          case "integer":
            if (typeof value === "string" && !/^-?\d+$/.test(value)) {
                return value;
            }
            return parseInt(value);

          case "double":
            if (typeof value === "string" && !/^-?\d+\.?\d*$/.test(value)) {
                return value;
            }
            return parseFloat(value);

          case "boolean":
            if (typeof value === "string" && !/^(0|1|true|false){1}$/i.test(value)) {
                return value;
            }
            return value === true || value === 1 || value.toLowerCase() === "true" || value === "1";

          default:
            return value;
        }
    };
    Utils.escapeString = function(value) {
        if (typeof value != "string") {
            return value;
        }
        return value.replace(/[\0\n\r\b\\\'\"]/g, function(s) {
            switch (s) {
              case "\0":
                return "\\0";

              case "\n":
                return "\\n";

              case "\r":
                return "\\r";

              case "\b":
                return "\\b";

              default:
                return "\\" + s;
            }
        }).replace(/\t/g, "\\t").replace(/\x1a/g, "\\Z");
    };
    Utils.escapeRegExp = function(str) {
        return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
    };
    Utils.escapeElementId = function(str) {
        return str ? str.replace(/(\\)?([:.\[\],])/g, function($0, $1, $2) {
            return $1 ? $0 : "\\" + $2;
        }) : str;
    };
    Utils.groupSort = function(items, key) {
        var optgroups = [];
        var newItems = [];
        items.forEach(function(item) {
            var idx;
            if (item[key]) {
                idx = optgroups.lastIndexOf(item[key]);
                if (idx == -1) {
                    idx = optgroups.length;
                } else {
                    idx++;
                }
            } else {
                idx = optgroups.length;
            }
            optgroups.splice(idx, 0, item[key]);
            newItems.splice(idx, 0, item);
        });
        return newItems;
    };
    Utils.defineModelProperties = function(obj, fields) {
        fields.forEach(function(field) {
            Object.defineProperty(obj.prototype, field, {
                enumerable: true,
                get: function() {
                    return this.__[field];
                },
                set: function(value) {
                    var previousValue = this.__[field] !== null && typeof this.__[field] == "object" ? $.extend({}, this.__[field]) : this.__[field];
                    this.__[field] = value;
                    if (this.model !== null) {
                        this.model.trigger("update", this, field, value, previousValue);
                    }
                }
            });
        });
    };
    function Model() {
        this.root = null;
        this.$ = $(this);
    }
    $.extend(Model.prototype, {
        trigger: function(type) {
            var event = new $.Event(type);
            this.$.triggerHandler(event, Array.prototype.slice.call(arguments, 1));
            return event;
        },
        on: function() {
            this.$.on.apply(this.$, Array.prototype.slice.call(arguments));
            return this;
        },
        off: function() {
            this.$.off.apply(this.$, Array.prototype.slice.call(arguments));
            return this;
        },
        once: function() {
            this.$.one.apply(this.$, Array.prototype.slice.call(arguments));
            return this;
        }
    });
    var Node = function(parent, $el) {
        if (!(this instanceof Node)) {
            return new Node(parent, $el);
        }
        Object.defineProperty(this, "__", {
            value: {}
        });
        $el.data("queryBuilderModel", this);
        this.__.level = 1;
        this.__.error = null;
        this.__.flags = {};
        this.__.data = undefined;
        this.$el = $el;
        this.id = $el[0].id;
        this.model = null;
        this.parent = parent;
    };
    Utils.defineModelProperties(Node, [ "level", "error", "data", "flags" ]);
    Object.defineProperty(Node.prototype, "parent", {
        enumerable: true,
        get: function() {
            return this.__.parent;
        },
        set: function(value) {
            this.__.parent = value;
            this.level = value === null ? 1 : value.level + 1;
            this.model = value === null ? null : value.model;
        }
    });
    Node.prototype.isRoot = function() {
        return this.level === 1;
    };
    Node.prototype.getPos = function() {
        if (this.isRoot()) {
            return -1;
        } else {
            return this.parent.getNodePos(this);
        }
    };
    Node.prototype.drop = function() {
        var model = this.model;
        if (!!this.parent) {
            this.parent.removeNode(this);
        }
        this.$el.removeData("queryBuilderModel");
        if (model !== null) {
            model.trigger("drop", this);
        }
    };
    Node.prototype.moveAfter = function(target) {
        if (!this.isRoot()) {
            this.move(target.parent, target.getPos() + 1);
        }
    };
    Node.prototype.moveAtBegin = function(target) {
        if (!this.isRoot()) {
            if (target === undefined) {
                target = this.parent;
            }
            this.move(target, 0);
        }
    };
    Node.prototype.moveAtEnd = function(target) {
        if (!this.isRoot()) {
            if (target === undefined) {
                target = this.parent;
            }
            this.move(target, target.length() === 0 ? 0 : target.length() - 1);
        }
    };
    Node.prototype.move = function(target, index) {
        if (!this.isRoot()) {
            if (typeof target === "number") {
                index = target;
                target = this.parent;
            }
            this.parent.removeNode(this);
            target.insertNode(this, index, false);
            if (this.model !== null) {
                this.model.trigger("move", this, target, index);
            }
        }
    };
    var Group = function(parent, $el) {
        if (!(this instanceof Group)) {
            return new Group(parent, $el);
        }
        Node.call(this, parent, $el);
        this.rules = [];
        this.__.condition = null;
    };
    Group.prototype = Object.create(Node.prototype);
    Group.prototype.constructor = Group;
    Utils.defineModelProperties(Group, [ "condition" ]);
    Group.prototype.empty = function() {
        this.each("reverse", function(rule) {
            rule.drop();
        }, function(group) {
            group.drop();
        });
    };
    Group.prototype.drop = function() {
        this.empty();
        Node.prototype.drop.call(this);
    };
    Group.prototype.length = function() {
        return this.rules.length;
    };
    Group.prototype.insertNode = function(node, index, trigger) {
        if (index === undefined) {
            index = this.length();
        }
        this.rules.splice(index, 0, node);
        node.parent = this;
        if (trigger && this.model !== null) {
            this.model.trigger("add", this, node, index);
        }
        return node;
    };
    Group.prototype.addGroup = function($el, index) {
        return this.insertNode(new Group(this, $el), index, true);
    };
    Group.prototype.addRule = function($el, index) {
        return this.insertNode(new Rule(this, $el), index, true);
    };
    Group.prototype.removeNode = function(node) {
        var index = this.getNodePos(node);
        if (index !== -1) {
            node.parent = null;
            this.rules.splice(index, 1);
        }
    };
    Group.prototype.getNodePos = function(node) {
        return this.rules.indexOf(node);
    };
    Group.prototype.each = function(reverse, cbRule, cbGroup, context) {
        if (typeof reverse !== "boolean" && typeof reverse !== "string") {
            context = cbGroup;
            cbGroup = cbRule;
            cbRule = reverse;
            reverse = false;
        }
        context = context === undefined ? null : context;
        var i = reverse ? this.rules.length - 1 : 0;
        var l = reverse ? 0 : this.rules.length - 1;
        var c = reverse ? -1 : 1;
        var next = function() {
            return reverse ? i >= l : i <= l;
        };
        var stop = false;
        for (;next(); i += c) {
            if (this.rules[i] instanceof Group) {
                if (!!cbGroup) {
                    stop = cbGroup.call(context, this.rules[i]) === false;
                }
            } else if (!!cbRule) {
                stop = cbRule.call(context, this.rules[i]) === false;
            }
            if (stop) {
                break;
            }
        }
        return !stop;
    };
    Group.prototype.contains = function(node, recursive) {
        if (this.getNodePos(node) !== -1) {
            return true;
        } else if (!recursive) {
            return false;
        } else {
            return !this.each(function() {
                return true;
            }, function(group) {
                return !group.contains(node, true);
            });
        }
    };
    var Rule = function(parent, $el) {
        if (!(this instanceof Rule)) {
            return new Rule(parent, $el);
        }
        Node.call(this, parent, $el);
        this._updating_value = false;
        this._updating_input = false;
        this.__.filter = null;
        this.__.operator = null;
        this.__.value = undefined;
    };
    Rule.prototype = Object.create(Node.prototype);
    Rule.prototype.constructor = Rule;
    Utils.defineModelProperties(Rule, [ "filter", "operator", "value" ]);
    Rule.prototype.isRoot = function() {
        return false;
    };
    QueryBuilder.Group = Group;
    QueryBuilder.Rule = Rule;
    $.fn.queryBuilder = function(option) {
        if (this.length === 0) {
            Utils.error("Config", "No target defined");
        }
        if (this.length > 1) {
            Utils.error("Config", "Unable to initialize on multiple target");
        }
        var data = this.data("queryBuilder");
        var options = typeof option == "object" && option || {};
        if (!data && option == "destroy") {
            return this;
        }
        if (!data) {
            var builder = new QueryBuilder(this, options);
            this.data("queryBuilder", builder);
            builder.init(options.rules);
        }
        if (typeof option == "string") {
            return data[option].apply(data, Array.prototype.slice.call(arguments, 1));
        }
        return this;
    };
    $.fn.queryBuilder.constructor = QueryBuilder;
    $.fn.queryBuilder.defaults = QueryBuilder.defaults;
    $.fn.queryBuilder.extend = QueryBuilder.extend;
    $.fn.queryBuilder.define = QueryBuilder.define;
    $.fn.queryBuilder.regional = QueryBuilder.regional;
    QueryBuilder.define("bt-checkbox", function(options) {
        if (options.font == "glyphicons") {
            this.$el.addClass("bt-checkbox-glyphicons");
        }
        this.on("getRuleInput.filter", function(h, rule, name) {
            var filter = rule.filter;
            if ((filter.input === "radio" || filter.input === "checkbox") && !filter.plugin) {
                h.value = "";
                if (!filter.colors) {
                    filter.colors = {};
                }
                if (filter.color) {
                    filter.colors._def_ = filter.color;
                }
                var style = filter.vertical ? ' style="display:block"' : "";
                var i = 0;
                Utils.iterateOptions(filter.values, function(key, val) {
                    var color = filter.colors[key] || filter.colors._def_ || options.color;
                    var id = name + "_" + i++;
                    h.value += "<div" + style + ' class="' + filter.input + " " + filter.input + "-" + color + '">   <input type="' + filter.input + '" name="' + name + '" id="' + id + '" value="' + key + '">   <label for="' + id + '">' + val + "</label> </div>";
                });
            }
        });
    }, {
        font: "glyphicons",
        color: "default"
    });
    QueryBuilder.define("bt-selectpicker", function(options) {
        if (!$.fn.selectpicker || !$.fn.selectpicker.Constructor) {
            Utils.error("MissingLibrary", 'Bootstrap Select is required to use "bt-selectpicker" plugin. Get it here: http://silviomoreto.github.io/bootstrap-select');
        }
        var Selectors = QueryBuilder.selectors;
        this.on("afterCreateRuleFilters", function(e, rule) {
            rule.$el.find(Selectors.rule_filter).removeClass("form-control").selectpicker(options);
        });
        this.on("afterCreateRuleOperators", function(e, rule) {
            rule.$el.find(Selectors.rule_operator).removeClass("form-control").selectpicker(options);
        });
        this.on("afterUpdateRuleFilter", function(e, rule) {
            rule.$el.find(Selectors.rule_filter).selectpicker("render");
        });
        this.on("afterUpdateRuleOperator", function(e, rule) {
            rule.$el.find(Selectors.rule_operator).selectpicker("render");
        });
        this.on("beforeDeleteRule", function(e, rule) {
            rule.$el.find(Selectors.rule_filter).selectpicker("destroy");
            rule.$el.find(Selectors.rule_operator).selectpicker("destroy");
        });
    }, {
        container: "body",
        style: "btn-inverse btn-xs",
        width: "auto",
        showIcon: false
    });
    QueryBuilder.define("bt-tooltip-errors", function(options) {
        if (!$.fn.tooltip || !$.fn.tooltip.Constructor || !$.fn.tooltip.Constructor.prototype.fixTitle) {
            Utils.error("MissingLibrary", 'Bootstrap Tooltip is required to use "bt-tooltip-errors" plugin. Get it here: http://getbootstrap.com');
        }
        var self = this;
        this.on("getRuleTemplate.filter getGroupTemplate.filter", function(h) {
            var $h = $(h.value);
            $h.find(QueryBuilder.selectors.error_container).attr("data-toggle", "tooltip");
            h.value = $h.prop("outerHTML");
        });
        this.model.on("update", function(e, node, field) {
            if (field == "error" && self.settings.display_errors) {
                node.$el.find(QueryBuilder.selectors.error_container).eq(0).tooltip(options).tooltip("hide").tooltip("fixTitle");
            }
        });
    }, {
        placement: "right"
    });
    QueryBuilder.extend({
        setFilters: function(deleteOrphans, filters) {
            var self = this;
            if (filters === undefined) {
                filters = deleteOrphans;
                deleteOrphans = false;
            }
            filters = this.checkFilters(filters);
            filters = this.change("setFilters", filters);
            var filtersIds = filters.map(function(filter) {
                return filter.id;
            });
            if (!deleteOrphans) {
                (function checkOrphans(node) {
                    node.each(function(rule) {
                        if (rule.filter && filtersIds.indexOf(rule.filter.id) === -1) {
                            Utils.error("ChangeFilter", 'A rule is using filter "{0}"', rule.filter.id);
                        }
                    }, checkOrphans);
                })(this.model.root);
            }
            this.filters = filters;
            (function updateBuilder(node) {
                node.each(true, function(rule) {
                    if (rule.filter && filtersIds.indexOf(rule.filter.id) === -1) {
                        rule.drop();
                        self.trigger("rulesChanged");
                    } else {
                        self.createRuleFilters(rule);
                        rule.$el.find(QueryBuilder.selectors.rule_filter).val(rule.filter ? rule.filter.id : "-1");
                        self.trigger("afterUpdateRuleFilter", rule);
                    }
                }, updateBuilder);
            })(this.model.root);
            if (this.settings.plugins) {
                if (this.settings.plugins["unique-filter"]) {
                    this.updateDisabledFilters();
                }
                if (this.settings.plugins["bt-selectpicker"]) {
                    this.$el.find(QueryBuilder.selectors.rule_filter).selectpicker("render");
                }
            }
            if (this.settings.default_filter) {
                try {
                    this.getFilterById(this.settings.default_filter);
                } catch (e) {
                    this.settings.default_filter = null;
                }
            }
            this.trigger("afterSetFilters", filters);
        },
        addFilter: function(newFilters, position) {
            if (position === undefined || position == "#end") {
                position = this.filters.length;
            } else if (position == "#start") {
                position = 0;
            }
            if (!$.isArray(newFilters)) {
                newFilters = [ newFilters ];
            }
            var filters = $.extend(true, [], this.filters);
            if (parseInt(position) == position) {
                Array.prototype.splice.apply(filters, [ position, 0 ].concat(newFilters));
            } else {
                if (this.filters.some(function(filter, index) {
                    if (filter.id == position) {
                        position = index + 1;
                        return true;
                    }
                })) {
                    Array.prototype.splice.apply(filters, [ position, 0 ].concat(newFilters));
                } else {
                    Array.prototype.push.apply(filters, newFilters);
                }
            }
            this.setFilters(filters);
        },
        removeFilter: function(filterIds, deleteOrphans) {
            var filters = $.extend(true, [], this.filters);
            if (typeof filterIds === "string") {
                filterIds = [ filterIds ];
            }
            filters = filters.filter(function(filter) {
                return filterIds.indexOf(filter.id) === -1;
            });
            this.setFilters(deleteOrphans, filters);
        }
    });
    QueryBuilder.define("chosen-selectpicker", function(options) {
        if (!$.fn.chosen) {
            Utils.error("MissingLibrary", 'chosen is required to use "chosen-selectpicker" plugin. Get it here: https://github.com/harvesthq/chosen');
        }
        if (this.settings.plugins["bt-selectpicker"]) {
            Utils.error("Conflict", "bt-selectpicker is already selected as the dropdown plugin. Please remove chosen-selectpicker from the plugin list");
        }
        var Selectors = QueryBuilder.selectors;
        this.on("afterCreateRuleFilters", function(e, rule) {
            rule.$el.find(Selectors.rule_filter).removeClass("form-control").chosen(options);
        });
        this.on("afterCreateRuleOperators", function(e, rule) {
            rule.$el.find(Selectors.rule_operator).removeClass("form-control").chosen(options);
        });
        this.on("afterUpdateRuleFilter", function(e, rule) {
            rule.$el.find(Selectors.rule_filter).trigger("chosen:updated");
        });
        this.on("afterUpdateRuleOperator", function(e, rule) {
            rule.$el.find(Selectors.rule_operator).trigger("chosen:updated");
        });
        this.on("beforeDeleteRule", function(e, rule) {
            rule.$el.find(Selectors.rule_filter).chosen("destroy");
            rule.$el.find(Selectors.rule_operator).chosen("destroy");
        });
    });
    QueryBuilder.define("filter-description", function(options) {
        if (options.mode === "inline") {
            this.on("afterUpdateRuleFilter afterUpdateRuleOperator", function(e, rule) {
                var $p = rule.$el.find("p.filter-description");
                var description = e.builder.getFilterDescription(rule.filter, rule);
                if (!description) {
                    $p.hide();
                } else {
                    if ($p.length === 0) {
                        $p = $('<p class="filter-description"></p>');
                        $p.appendTo(rule.$el);
                    } else {
                        $p.css("display", "");
                    }
                    $p.html('<i class="' + options.icon + '"></i> ' + description);
                }
            });
        } else if (options.mode === "popover") {
            if (!$.fn.popover || !$.fn.popover.Constructor || !$.fn.popover.Constructor.prototype.fixTitle) {
                Utils.error("MissingLibrary", 'Bootstrap Popover is required to use "filter-description" plugin. Get it here: http://getbootstrap.com');
            }
            this.on("afterUpdateRuleFilter afterUpdateRuleOperator", function(e, rule) {
                var $b = rule.$el.find("button.filter-description");
                var description = e.builder.getFilterDescription(rule.filter, rule);
                if (!description) {
                    $b.hide();
                    if ($b.data("bs.popover")) {
                        $b.popover("hide");
                    }
                } else {
                    if ($b.length === 0) {
                        $b = $('<button type="button" class="btn btn-xs btn-info filter-description" data-toggle="popover"><i class="' + options.icon + '"></i></button>');
                        $b.prependTo(rule.$el.find(QueryBuilder.selectors.rule_actions));
                        $b.popover({
                            placement: "left",
                            container: "body",
                            html: true
                        });
                        $b.on("mouseout", function() {
                            $b.popover("hide");
                        });
                    } else {
                        $b.css("display", "");
                    }
                    $b.data("bs.popover").options.content = description;
                    if ($b.attr("aria-describedby")) {
                        $b.popover("show");
                    }
                }
            });
        } else if (options.mode === "bootbox") {
            if (!("bootbox" in window)) {
                Utils.error("MissingLibrary", 'Bootbox is required to use "filter-description" plugin. Get it here: http://bootboxjs.com');
            }
            this.on("afterUpdateRuleFilter afterUpdateRuleOperator", function(e, rule) {
                var $b = rule.$el.find("button.filter-description");
                var description = e.builder.getFilterDescription(rule.filter, rule);
                if (!description) {
                    $b.hide();
                } else {
                    if ($b.length === 0) {
                        $b = $('<button type="button" class="btn btn-xs btn-info filter-description" data-toggle="bootbox"><i class="' + options.icon + '"></i></button>');
                        $b.prependTo(rule.$el.find(QueryBuilder.selectors.rule_actions));
                        $b.on("click", function() {
                            bootbox.alert($b.data("description"));
                        });
                    } else {
                        $b.css("display", "");
                    }
                    $b.data("description", description);
                }
            });
        }
    }, {
        icon: "glyphicon glyphicon-info-sign",
        mode: "popover"
    });
    QueryBuilder.extend({
        getFilterDescription: function(filter, rule) {
            if (!filter) {
                return undefined;
            } else if (typeof filter.description == "function") {
                return filter.description.call(this, rule);
            } else {
                return filter.description;
            }
        }
    });
    QueryBuilder.define("invert", function(options) {
        var self = this;
        var Selectors = QueryBuilder.selectors;
        this.on("afterInit", function() {
            self.$el.on("click.queryBuilder", "[data-invert=group]", function() {
                var $group = $(this).closest(Selectors.group_container);
                self.invert(self.getModel($group), options);
            });
            if (options.display_rules_button && options.invert_rules) {
                self.$el.on("click.queryBuilder", "[data-invert=rule]", function() {
                    var $rule = $(this).closest(Selectors.rule_container);
                    self.invert(self.getModel($rule), options);
                });
            }
        });
        if (!options.disable_template) {
            this.on("getGroupTemplate.filter", function(h) {
                var $h = $(h.value);
                $h.find(Selectors.condition_container).after('<button type="button" class="btn btn-xs btn-default" data-invert="group">' + '<i class="' + options.icon + '"></i> ' + self.translate("invert") + "</button>");
                h.value = $h.prop("outerHTML");
            });
            if (options.display_rules_button && options.invert_rules) {
                this.on("getRuleTemplate.filter", function(h) {
                    var $h = $(h.value);
                    $h.find(Selectors.rule_actions).prepend('<button type="button" class="btn btn-xs btn-default" data-invert="rule">' + '<i class="' + options.icon + '"></i> ' + self.translate("invert") + "</button>");
                    h.value = $h.prop("outerHTML");
                });
            }
        }
    }, {
        icon: "glyphicon glyphicon-random",
        recursive: true,
        invert_rules: true,
        display_rules_button: false,
        silent_fail: false,
        disable_template: false
    });
    QueryBuilder.defaults({
        operatorOpposites: {
            equal: "not_equal",
            not_equal: "equal",
            in: "not_in",
            not_in: "in",
            less: "greater_or_equal",
            less_or_equal: "greater",
            greater: "less_or_equal",
            greater_or_equal: "less",
            between: "not_between",
            not_between: "between",
            begins_with: "not_begins_with",
            not_begins_with: "begins_with",
            contains: "not_contains",
            not_contains: "contains",
            ends_with: "not_ends_with",
            not_ends_with: "ends_with",
            is_empty: "is_not_empty",
            is_not_empty: "is_empty",
            is_null: "is_not_null",
            is_not_null: "is_null"
        },
        conditionOpposites: {
            AND: "OR",
            OR: "AND"
        }
    });
    QueryBuilder.extend({
        invert: function(node, options) {
            if (!(node instanceof Node)) {
                if (!this.model.root) return;
                options = node;
                node = this.model.root;
            }
            if (typeof options != "object") options = {};
            if (options.recursive === undefined) options.recursive = true;
            if (options.invert_rules === undefined) options.invert_rules = true;
            if (options.silent_fail === undefined) options.silent_fail = false;
            if (options.trigger === undefined) options.trigger = true;
            if (node instanceof Group) {
                if (this.settings.conditionOpposites[node.condition]) {
                    node.condition = this.settings.conditionOpposites[node.condition];
                } else if (!options.silent_fail) {
                    Utils.error("InvertCondition", 'Unknown inverse of condition "{0}"', node.condition);
                }
                if (options.recursive) {
                    var tempOpts = $.extend({}, options, {
                        trigger: false
                    });
                    node.each(function(rule) {
                        if (options.invert_rules) {
                            this.invert(rule, tempOpts);
                        }
                    }, function(group) {
                        this.invert(group, tempOpts);
                    }, this);
                }
            } else if (node instanceof Rule) {
                if (node.operator && !node.filter.no_invert) {
                    if (this.settings.operatorOpposites[node.operator.type]) {
                        var invert = this.settings.operatorOpposites[node.operator.type];
                        if (!node.filter.operators || node.filter.operators.indexOf(invert) != -1) {
                            node.operator = this.getOperatorByType(invert);
                        }
                    } else if (!options.silent_fail) {
                        Utils.error("InvertOperator", 'Unknown inverse of operator "{0}"', node.operator.type);
                    }
                }
            }
            if (options.trigger) {
                this.trigger("afterInvert", node, options);
                this.trigger("rulesChanged");
            }
        }
    });
    QueryBuilder.defaults({
        mongoOperators: {
            equal: function(v) {
                return v[0];
            },
            not_equal: function(v) {
                return {
                    $ne: v[0]
                };
            },
            in: function(v) {
                return {
                    $in: v
                };
            },
            not_in: function(v) {
                return {
                    $nin: v
                };
            },
            less: function(v) {
                return {
                    $lt: v[0]
                };
            },
            less_or_equal: function(v) {
                return {
                    $lte: v[0]
                };
            },
            greater: function(v) {
                return {
                    $gt: v[0]
                };
            },
            greater_or_equal: function(v) {
                return {
                    $gte: v[0]
                };
            },
            between: function(v) {
                return {
                    $gte: v[0],
                    $lte: v[1]
                };
            },
            not_between: function(v) {
                return {
                    $lt: v[0],
                    $gt: v[1]
                };
            },
            begins_with: function(v) {
                return {
                    $regex: "^" + Utils.escapeRegExp(v[0])
                };
            },
            not_begins_with: function(v) {
                return {
                    $regex: "^(?!" + Utils.escapeRegExp(v[0]) + ")"
                };
            },
            contains: function(v) {
                return {
                    $regex: Utils.escapeRegExp(v[0])
                };
            },
            not_contains: function(v) {
                return {
                    $regex: "^((?!" + Utils.escapeRegExp(v[0]) + ").)*$",
                    $options: "s"
                };
            },
            ends_with: function(v) {
                return {
                    $regex: Utils.escapeRegExp(v[0]) + "$"
                };
            },
            not_ends_with: function(v) {
                return {
                    $regex: "(?<!" + Utils.escapeRegExp(v[0]) + ")$"
                };
            },
            is_empty: function(v) {
                return "";
            },
            is_not_empty: function(v) {
                return {
                    $ne: ""
                };
            },
            is_null: function(v) {
                return null;
            },
            is_not_null: function(v) {
                return {
                    $ne: null
                };
            }
        },
        mongoRuleOperators: {
            $eq: function(v) {
                return {
                    val: v,
                    op: v === null ? "is_null" : v === "" ? "is_empty" : "equal"
                };
            },
            $ne: function(v) {
                v = v.$ne;
                return {
                    val: v,
                    op: v === null ? "is_not_null" : v === "" ? "is_not_empty" : "not_equal"
                };
            },
            $regex: function(v) {
                v = v.$regex;
                if (v.slice(0, 4) == "^(?!" && v.slice(-1) == ")") {
                    return {
                        val: v.slice(4, -1),
                        op: "not_begins_with"
                    };
                } else if (v.slice(0, 5) == "^((?!" && v.slice(-5) == ").)*$") {
                    return {
                        val: v.slice(5, -5),
                        op: "not_contains"
                    };
                } else if (v.slice(0, 4) == "(?<!" && v.slice(-2) == ")$") {
                    return {
                        val: v.slice(4, -2),
                        op: "not_ends_with"
                    };
                } else if (v.slice(-1) == "$") {
                    return {
                        val: v.slice(0, -1),
                        op: "ends_with"
                    };
                } else if (v.slice(0, 1) == "^") {
                    return {
                        val: v.slice(1),
                        op: "begins_with"
                    };
                } else {
                    return {
                        val: v,
                        op: "contains"
                    };
                }
            },
            between: function(v) {
                return {
                    val: [ v.$gte, v.$lte ],
                    op: "between"
                };
            },
            not_between: function(v) {
                return {
                    val: [ v.$lt, v.$gt ],
                    op: "not_between"
                };
            },
            $in: function(v) {
                return {
                    val: v.$in,
                    op: "in"
                };
            },
            $nin: function(v) {
                return {
                    val: v.$nin,
                    op: "not_in"
                };
            },
            $lt: function(v) {
                return {
                    val: v.$lt,
                    op: "less"
                };
            },
            $lte: function(v) {
                return {
                    val: v.$lte,
                    op: "less_or_equal"
                };
            },
            $gt: function(v) {
                return {
                    val: v.$gt,
                    op: "greater"
                };
            },
            $gte: function(v) {
                return {
                    val: v.$gte,
                    op: "greater_or_equal"
                };
            }
        }
    });
    QueryBuilder.extend({
        getMongo: function(data) {
            data = data === undefined ? this.getRules() : data;
            if (!data) {
                return null;
            }
            var self = this;
            return function parse(group) {
                if (!group.condition) {
                    group.condition = self.settings.default_condition;
                }
                if ([ "AND", "OR" ].indexOf(group.condition.toUpperCase()) === -1) {
                    Utils.error("UndefinedMongoCondition", 'Unable to build MongoDB query with condition "{0}"', group.condition);
                }
                if (!group.rules) {
                    return {};
                }
                var parts = [];
                group.rules.forEach(function(rule) {
                    if (rule.rules && rule.rules.length > 0) {
                        parts.push(parse(rule));
                    } else {
                        var mdb = self.settings.mongoOperators[rule.operator];
                        var ope = self.getOperatorByType(rule.operator);
                        if (mdb === undefined) {
                            Utils.error("UndefinedMongoOperator", 'Unknown MongoDB operation for operator "{0}"', rule.operator);
                        }
                        if (ope.nb_inputs !== 0) {
                            if (!(rule.value instanceof Array)) {
                                rule.value = [ rule.value ];
                            }
                        }
                        var field = self.change("getMongoDBField", rule.field, rule);
                        var ruleExpression = {};
                        ruleExpression[field] = mdb.call(self, rule.value);
                        parts.push(self.change("ruleToMongo", ruleExpression, rule, rule.value, mdb));
                    }
                });
                var groupExpression = {};
                groupExpression["$" + group.condition.toLowerCase()] = parts;
                return self.change("groupToMongo", groupExpression, group);
            }(data);
        },
        getRulesFromMongo: function(query) {
            if (query === undefined || query === null) {
                return null;
            }
            var self = this;
            query = self.change("parseMongoNode", query);
            if ("rules" in query && "condition" in query) {
                return query;
            }
            if ("id" in query && "operator" in query && "value" in query) {
                return {
                    condition: this.settings.default_condition,
                    rules: [ query ]
                };
            }
            var key = self.getMongoCondition(query);
            if (!key) {
                Utils.error("MongoParse", "Invalid MongoDB query format");
            }
            return function parse(data, topKey) {
                var rules = data[topKey];
                var parts = [];
                rules.forEach(function(data) {
                    data = self.change("parseMongoNode", data);
                    if ("rules" in data && "condition" in data) {
                        parts.push(data);
                        return;
                    }
                    if ("id" in data && "operator" in data && "value" in data) {
                        parts.push(data);
                        return;
                    }
                    var key = self.getMongoCondition(data);
                    if (key) {
                        parts.push(parse(data, key));
                    } else {
                        var field = Object.keys(data)[0];
                        var value = data[field];
                        var operator = self.getMongoOperator(value);
                        if (operator === undefined) {
                            Utils.error("MongoParse", "Invalid MongoDB query format");
                        }
                        var mdbrl = self.settings.mongoRuleOperators[operator];
                        if (mdbrl === undefined) {
                            Utils.error("UndefinedMongoOperator", 'JSON Rule operation unknown for operator "{0}"', operator);
                        }
                        var opVal = mdbrl.call(self, value);
                        var id = self.getMongoDBFieldID(field, value);
                        var rule = self.change("mongoToRule", {
                            id: id,
                            field: field,
                            operator: opVal.op,
                            value: opVal.val
                        }, data);
                        parts.push(rule);
                    }
                });
                return self.change("mongoToGroup", {
                    condition: topKey.replace("$", "").toUpperCase(),
                    rules: parts
                }, data);
            }(query, key);
        },
        setRulesFromMongo: function(query) {
            this.setRules(this.getRulesFromMongo(query));
        },
        getMongoDBFieldID: function(field, value) {
            var matchingFilters = this.filters.filter(function(filter) {
                return filter.field === field;
            });
            var id;
            if (matchingFilters.length === 1) {
                id = matchingFilters[0].id;
            } else {
                id = this.change("getMongoDBFieldID", field, value);
            }
            return id;
        },
        getMongoOperator: function(data) {
            if (data !== null && typeof data === "object") {
                if (data.$gte !== undefined && data.$lte !== undefined) {
                    return "between";
                }
                if (data.$lt !== undefined && data.$gt !== undefined) {
                    return "not_between";
                }
                var knownKeys = Object.keys(data).filter(function(key) {
                    return !!this.settings.mongoRuleOperators[key];
                }.bind(this));
                if (knownKeys.length === 1) {
                    return knownKeys[0];
                }
            } else {
                return "$eq";
            }
        },
        getMongoCondition: function(data) {
            var keys = Object.keys(data);
            for (var i = 0, l = keys.length; i < l; i++) {
                if (keys[i].toLowerCase() === "$or" || keys[i].toLowerCase() === "$and") {
                    return keys[i];
                }
            }
        }
    });
    QueryBuilder.define("not-group", function(options) {
        var self = this;
        this.on("afterInit", function() {
            self.$el.on("click.queryBuilder", "[data-not=group]", function() {
                var $group = $(this).closest(QueryBuilder.selectors.group_container);
                var group = self.getModel($group);
                group.not = !group.not;
            });
            self.model.on("update", function(e, node, field) {
                if (node instanceof Group && field === "not") {
                    self.updateGroupNot(node);
                }
            });
        });
        this.on("afterAddGroup", function(e, group) {
            group.__.not = false;
        });
        if (!options.disable_template) {
            this.on("getGroupTemplate.filter", function(h) {
                var $h = $(h.value);
                $h.find(QueryBuilder.selectors.condition_container).prepend('<button type="button" class="btn btn-xs btn-default" data-not="group">' + '<i class="' + options.icon_unchecked + '"></i> ' + self.translate("NOT") + "</button>");
                h.value = $h.prop("outerHTML");
            });
        }
        this.on("groupToJson.filter", function(e, group) {
            e.value.not = group.not;
        });
        this.on("jsonToGroup.filter", function(e, json) {
            e.value.not = !!json.not;
        });
        this.on("groupToSQL.filter", function(e, group) {
            if (group.not) {
                e.value = "NOT ( " + e.value + " )";
            }
        });
        this.on("parseSQLNode.filter", function(e) {
            if (e.value.name && e.value.name.toUpperCase() == "NOT") {
                e.value = e.value.arguments.value[0];
                if ([ "AND", "OR" ].indexOf(e.value.operation.toUpperCase()) === -1) {
                    e.value = new SQLParser.nodes.Op(self.settings.default_condition, e.value, null);
                }
                e.value.not = true;
            }
        });
        this.on("sqlGroupsDistinct.filter", function(e, group, data, i) {
            if (data.not && i > 0) {
                e.value = true;
            }
        });
        this.on("sqlToGroup.filter", function(e, data) {
            e.value.not = !!data.not;
        });
        this.on("groupToMongo.filter", function(e, group) {
            var key = "$" + group.condition.toLowerCase();
            if (group.not && e.value[key]) {
                e.value = {
                    $nor: [ e.value ]
                };
            }
        });
        this.on("parseMongoNode.filter", function(e) {
            var keys = Object.keys(e.value);
            if (keys[0] == "$nor") {
                e.value = e.value[keys[0]][0];
                e.value.not = true;
            }
        });
        this.on("mongoToGroup.filter", function(e, data) {
            e.value.not = !!data.not;
        });
    }, {
        icon_unchecked: "glyphicon glyphicon-unchecked",
        icon_checked: "glyphicon glyphicon-check",
        disable_template: false
    });
    Utils.defineModelProperties(Group, [ "not" ]);
    QueryBuilder.selectors.group_not = QueryBuilder.selectors.group_header + " [data-not=group]";
    QueryBuilder.extend({
        updateGroupNot: function(group) {
            var options = this.plugins["not-group"];
            group.$el.find(">" + QueryBuilder.selectors.group_not).toggleClass("active", group.not).find("i").attr("class", group.not ? options.icon_checked : options.icon_unchecked);
            this.trigger("afterUpdateGroupNot", group);
            this.trigger("rulesChanged");
        }
    });
    QueryBuilder.define("sortable", function(options) {
        if (!("interact" in window)) {
            Utils.error("MissingLibrary", 'interact.js is required to use "sortable" plugin. Get it here: http://interactjs.io');
        }
        if (options.default_no_sortable !== undefined) {
            Utils.error(false, "Config", 'Sortable plugin : "default_no_sortable" options is deprecated, use standard "default_rule_flags" and "default_group_flags" instead');
            this.settings.default_rule_flags.no_sortable = this.settings.default_group_flags.no_sortable = options.default_no_sortable;
        }
        interact.dynamicDrop(true);
        interact.pointerMoveTolerance(10);
        var placeholder;
        var ghost;
        var src;
        var moved;
        this.on("afterAddRule afterAddGroup", function(e, node) {
            if (node == placeholder) {
                return;
            }
            var self = e.builder;
            if (options.inherit_no_sortable && node.parent && node.parent.flags.no_sortable) {
                node.flags.no_sortable = true;
            }
            if (options.inherit_no_drop && node.parent && node.parent.flags.no_drop) {
                node.flags.no_drop = true;
            }
            if (!node.flags.no_sortable) {
                interact(node.$el[0]).draggable({
                    allowFrom: QueryBuilder.selectors.drag_handle,
                    onstart: function(event) {
                        moved = false;
                        src = self.getModel(event.target);
                        ghost = src.$el.clone().appendTo(src.$el.parent()).width(src.$el.outerWidth()).addClass("dragging");
                        var ph = $('<div class="rule-placeholder">&nbsp;</div>').height(src.$el.outerHeight());
                        placeholder = src.parent.addRule(ph, src.getPos());
                        src.$el.hide();
                    },
                    onmove: function(event) {
                        ghost[0].style.top = event.clientY - 15 + "px";
                        ghost[0].style.left = event.clientX - 15 + "px";
                    },
                    onend: function(event) {
                        if (event.dropzone) {
                            moveSortableToTarget(src, $(event.relatedTarget), self);
                            moved = true;
                        }
                        ghost.remove();
                        ghost = undefined;
                        placeholder.drop();
                        placeholder = undefined;
                        src.$el.css("display", "");
                        self.trigger("afterMove", src);
                        self.trigger("rulesChanged");
                    }
                });
            }
            if (!node.flags.no_drop) {
                interact(node.$el[0]).dropzone({
                    accept: QueryBuilder.selectors.rule_and_group_containers,
                    ondragenter: function(event) {
                        moveSortableToTarget(placeholder, $(event.target), self);
                    },
                    ondrop: function(event) {
                        if (!moved) {
                            moveSortableToTarget(src, $(event.target), self);
                        }
                    }
                });
                if (node instanceof Group) {
                    interact(node.$el.find(QueryBuilder.selectors.group_header)[0]).dropzone({
                        accept: QueryBuilder.selectors.rule_and_group_containers,
                        ondragenter: function(event) {
                            moveSortableToTarget(placeholder, $(event.target), self);
                        },
                        ondrop: function(event) {
                            if (!moved) {
                                moveSortableToTarget(src, $(event.target), self);
                            }
                        }
                    });
                }
            }
        });
        this.on("beforeDeleteRule beforeDeleteGroup", function(e, node) {
            if (!e.isDefaultPrevented()) {
                interact(node.$el[0]).unset();
                if (node instanceof Group) {
                    interact(node.$el.find(QueryBuilder.selectors.group_header)[0]).unset();
                }
            }
        });
        this.on("afterApplyRuleFlags afterApplyGroupFlags", function(e, node) {
            if (node.flags.no_sortable) {
                node.$el.find(".drag-handle").remove();
            }
        });
        if (!options.disable_template) {
            this.on("getGroupTemplate.filter", function(h, level) {
                if (level > 1) {
                    var $h = $(h.value);
                    $h.find(QueryBuilder.selectors.condition_container).after('<div class="drag-handle"><i class="' + options.icon + '"></i></div>');
                    h.value = $h.prop("outerHTML");
                }
            });
            this.on("getRuleTemplate.filter", function(h) {
                var $h = $(h.value);
                $h.find(QueryBuilder.selectors.rule_header).after('<div class="drag-handle"><i class="' + options.icon + '"></i></div>');
                h.value = $h.prop("outerHTML");
            });
        }
    }, {
        inherit_no_sortable: true,
        inherit_no_drop: true,
        icon: "glyphicon glyphicon-sort",
        disable_template: false
    });
    QueryBuilder.selectors.rule_and_group_containers = QueryBuilder.selectors.rule_container + ", " + QueryBuilder.selectors.group_container;
    QueryBuilder.selectors.drag_handle = ".drag-handle";
    QueryBuilder.defaults({
        default_rule_flags: {
            no_sortable: false,
            no_drop: false
        },
        default_group_flags: {
            no_sortable: false,
            no_drop: false
        }
    });
    function moveSortableToTarget(node, target, builder) {
        var parent, method;
        var Selectors = QueryBuilder.selectors;
        parent = target.closest(Selectors.rule_container);
        if (parent.length) {
            method = "moveAfter";
        }
        if (!method) {
            parent = target.closest(Selectors.group_header);
            if (parent.length) {
                parent = target.closest(Selectors.group_container);
                method = "moveAtBegin";
            }
        }
        if (!method) {
            parent = target.closest(Selectors.group_container);
            if (parent.length) {
                method = "moveAtEnd";
            }
        }
        if (method) {
            node[method](builder.getModel(parent));
            if (builder && node instanceof Rule) {
                builder.setRuleInputValue(node, node.value);
            }
        }
    }
    QueryBuilder.define("sql-support", function(options) {}, {
        boolean_as_integer: true
    });
    QueryBuilder.defaults({
        sqlOperators: {
            equal: {
                op: "= ?"
            },
            not_equal: {
                op: "!= ?"
            },
            in: {
                op: "IN(?)",
                sep: ", "
            },
            not_in: {
                op: "NOT IN(?)",
                sep: ", "
            },
            less: {
                op: "< ?"
            },
            less_or_equal: {
                op: "<= ?"
            },
            greater: {
                op: "> ?"
            },
            greater_or_equal: {
                op: ">= ?"
            },
            between: {
                op: "BETWEEN ?",
                sep: " AND "
            },
            not_between: {
                op: "NOT BETWEEN ?",
                sep: " AND "
            },
            begins_with: {
                op: "LIKE(?)",
                mod: "{0}%"
            },
            not_begins_with: {
                op: "NOT LIKE(?)",
                mod: "{0}%"
            },
            contains: {
                op: "LIKE(?)",
                mod: "%{0}%"
            },
            not_contains: {
                op: "NOT LIKE(?)",
                mod: "%{0}%"
            },
            ends_with: {
                op: "LIKE(?)",
                mod: "%{0}"
            },
            not_ends_with: {
                op: "NOT LIKE(?)",
                mod: "%{0}"
            },
            is_empty: {
                op: "= ''"
            },
            is_not_empty: {
                op: "!= ''"
            },
            is_null: {
                op: "IS NULL"
            },
            is_not_null: {
                op: "IS NOT NULL"
            }
        },
        sqlRuleOperator: {
            "=": function(v) {
                return {
                    val: v,
                    op: v === "" ? "is_empty" : "equal"
                };
            },
            "!=": function(v) {
                return {
                    val: v,
                    op: v === "" ? "is_not_empty" : "not_equal"
                };
            },
            LIKE: function(v) {
                if (v.slice(0, 1) == "%" && v.slice(-1) == "%") {
                    return {
                        val: v.slice(1, -1),
                        op: "contains"
                    };
                } else if (v.slice(0, 1) == "%") {
                    return {
                        val: v.slice(1),
                        op: "ends_with"
                    };
                } else if (v.slice(-1) == "%") {
                    return {
                        val: v.slice(0, -1),
                        op: "begins_with"
                    };
                } else {
                    Utils.error("SQLParse", 'Invalid value for LIKE operator "{0}"', v);
                }
            },
            "NOT LIKE": function(v) {
                if (v.slice(0, 1) == "%" && v.slice(-1) == "%") {
                    return {
                        val: v.slice(1, -1),
                        op: "not_contains"
                    };
                } else if (v.slice(0, 1) == "%") {
                    return {
                        val: v.slice(1),
                        op: "not_ends_with"
                    };
                } else if (v.slice(-1) == "%") {
                    return {
                        val: v.slice(0, -1),
                        op: "not_begins_with"
                    };
                } else {
                    Utils.error("SQLParse", 'Invalid value for NOT LIKE operator "{0}"', v);
                }
            },
            IN: function(v) {
                return {
                    val: v,
                    op: "in"
                };
            },
            "NOT IN": function(v) {
                return {
                    val: v,
                    op: "not_in"
                };
            },
            "<": function(v) {
                return {
                    val: v,
                    op: "less"
                };
            },
            "<=": function(v) {
                return {
                    val: v,
                    op: "less_or_equal"
                };
            },
            ">": function(v) {
                return {
                    val: v,
                    op: "greater"
                };
            },
            ">=": function(v) {
                return {
                    val: v,
                    op: "greater_or_equal"
                };
            },
            BETWEEN: function(v) {
                return {
                    val: v,
                    op: "between"
                };
            },
            "NOT BETWEEN": function(v) {
                return {
                    val: v,
                    op: "not_between"
                };
            },
            IS: function(v) {
                if (v !== null) {
                    Utils.error("SQLParse", "Invalid value for IS operator");
                }
                return {
                    val: null,
                    op: "is_null"
                };
            },
            "IS NOT": function(v) {
                if (v !== null) {
                    Utils.error("SQLParse", "Invalid value for IS operator");
                }
                return {
                    val: null,
                    op: "is_not_null"
                };
            }
        },
        sqlStatements: {
            question_mark: function() {
                var params = [];
                return {
                    add: function(rule, value) {
                        params.push(value);
                        return "?";
                    },
                    run: function() {
                        return params;
                    }
                };
            },
            numbered: function(char) {
                if (!char || char.length > 1) char = "$";
                var index = 0;
                var params = [];
                return {
                    add: function(rule, value) {
                        params.push(value);
                        index++;
                        return char + index;
                    },
                    run: function() {
                        return params;
                    }
                };
            },
            named: function(char) {
                if (!char || char.length > 1) char = ":";
                var indexes = {};
                var params = {};
                return {
                    add: function(rule, value) {
                        if (!indexes[rule.field]) indexes[rule.field] = 1;
                        var key = rule.field + "_" + indexes[rule.field]++;
                        params[key] = value;
                        return char + key;
                    },
                    run: function() {
                        return params;
                    }
                };
            }
        },
        sqlRuleStatement: {
            question_mark: function(values) {
                var index = 0;
                return {
                    parse: function(v) {
                        return v == "?" ? values[index++] : v;
                    },
                    esc: function(sql) {
                        return sql.replace(/\?/g, "'?'");
                    }
                };
            },
            numbered: function(values, char) {
                if (!char || char.length > 1) char = "$";
                var regex1 = new RegExp("^\\" + char + "[0-9]+$");
                var regex2 = new RegExp("\\" + char + "([0-9]+)", "g");
                return {
                    parse: function(v) {
                        return regex1.test(v) ? values[v.slice(1) - 1] : v;
                    },
                    esc: function(sql) {
                        return sql.replace(regex2, "'" + (char == "$" ? "$$" : char) + "$1'");
                    }
                };
            },
            named: function(values, char) {
                if (!char || char.length > 1) char = ":";
                var regex1 = new RegExp("^\\" + char);
                var regex2 = new RegExp("\\" + char + "(" + Object.keys(values).join("|") + ")", "g");
                return {
                    parse: function(v) {
                        return regex1.test(v) ? values[v.slice(1)] : v;
                    },
                    esc: function(sql) {
                        return sql.replace(regex2, "'" + (char == "$" ? "$$" : char) + "$1'");
                    }
                };
            }
        }
    });
    QueryBuilder.extend({
        getSQL: function(stmt, nl, data) {
            data = data === undefined ? this.getRules() : data;
            if (!data) {
                return null;
            }
            nl = !!nl ? "\n" : " ";
            var boolean_as_integer = this.getPluginOptions("sql-support", "boolean_as_integer");
            if (stmt === true) {
                stmt = "question_mark";
            }
            if (typeof stmt == "string") {
                var config = getStmtConfig(stmt);
                stmt = this.settings.sqlStatements[config[1]](config[2]);
            }
            var self = this;
            var sql = function parse(group) {
                if (!group.condition) {
                    group.condition = self.settings.default_condition;
                }
                if ([ "AND", "OR" ].indexOf(group.condition.toUpperCase()) === -1) {
                    Utils.error("UndefinedSQLCondition", 'Unable to build SQL query with condition "{0}"', group.condition);
                }
                if (!group.rules) {
                    return "";
                }
                var parts = [];
                group.rules.forEach(function(rule) {
                    if (rule.rules && rule.rules.length > 0) {
                        parts.push("(" + nl + parse(rule) + nl + ")" + nl);
                    } else {
                        var sql = self.settings.sqlOperators[rule.operator];
                        var ope = self.getOperatorByType(rule.operator);
                        var value = "";
                        if (sql === undefined) {
                            Utils.error("UndefinedSQLOperator", 'Unknown SQL operation for operator "{0}"', rule.operator);
                        }
                        if (ope.nb_inputs !== 0) {
                            if (!(rule.value instanceof Array)) {
                                rule.value = [ rule.value ];
                            }
                            rule.value.forEach(function(v, i) {
                                if (i > 0) {
                                    value += sql.sep;
                                }
                                if (rule.type == "boolean" && boolean_as_integer) {
                                    v = v ? 1 : 0;
                                } else if (!stmt && rule.type !== "integer" && rule.type !== "double" && rule.type !== "boolean") {
                                    v = Utils.escapeString(v);
                                }
                                if (sql.mod) {
                                    v = Utils.fmt(sql.mod, v);
                                }
                                if (stmt) {
                                    value += stmt.add(rule, v);
                                } else {
                                    if (typeof v == "string") {
                                        v = "'" + v + "'";
                                    }
                                    value += v;
                                }
                            });
                        }
                        var sqlFn = function(v) {
                            return sql.op.replace("?", function() {
                                return v;
                            });
                        };
                        var field = self.change("getSQLField", rule.field, rule);
                        var ruleExpression = field + " " + sqlFn(value);
                        parts.push(self.change("ruleToSQL", ruleExpression, rule, value, sqlFn));
                    }
                });
                var groupExpression = parts.join(" " + group.condition + nl);
                return self.change("groupToSQL", groupExpression, group);
            }(data);
            if (stmt) {
                return {
                    sql: sql,
                    params: stmt.run()
                };
            } else {
                return {
                    sql: sql
                };
            }
        },
        getRulesFromSQL: function(query, stmt) {
            if (!("SQLParser" in window)) {
                Utils.error("MissingLibrary", "SQLParser is required to parse SQL queries. Get it here https://github.com/mistic100/sql-parser");
            }
            var self = this;
            if (typeof query == "string") {
                query = {
                    sql: query
                };
            }
            if (stmt === true) stmt = "question_mark";
            if (typeof stmt == "string") {
                var config = getStmtConfig(stmt);
                stmt = this.settings.sqlRuleStatement[config[1]](query.params, config[2]);
            }
            if (stmt) {
                query.sql = stmt.esc(query.sql);
            }
            if (query.sql.toUpperCase().indexOf("SELECT") !== 0) {
                query.sql = "SELECT * FROM table WHERE " + query.sql;
            }
            var parsed = SQLParser.parse(query.sql);
            if (!parsed.where) {
                Utils.error("SQLParse", "No WHERE clause found");
            }
            var data = self.change("parseSQLNode", parsed.where.conditions);
            if ("rules" in data && "condition" in data) {
                return data;
            }
            if ("id" in data && "operator" in data && "value" in data) {
                return {
                    condition: this.settings.default_condition,
                    rules: [ data ]
                };
            }
            var out = self.change("sqlToGroup", {
                condition: this.settings.default_condition,
                rules: []
            }, data);
            var curr = out;
            (function flatten(data, i) {
                if (data === null) {
                    return;
                }
                data = self.change("parseSQLNode", data);
                if ("rules" in data && "condition" in data) {
                    curr.rules.push(data);
                    return;
                }
                if ("id" in data && "operator" in data && "value" in data) {
                    curr.rules.push(data);
                    return;
                }
                if (!("left" in data) || !("right" in data) || !("operation" in data)) {
                    Utils.error("SQLParse", "Unable to parse WHERE clause");
                }
                if ([ "AND", "OR" ].indexOf(data.operation.toUpperCase()) !== -1) {
                    var createGroup = self.change("sqlGroupsDistinct", i > 0 && curr.condition != data.operation.toUpperCase(), curr, data, i);
                    if (createGroup) {
                        var group = self.change("sqlToGroup", {
                            condition: self.settings.default_condition,
                            rules: []
                        }, data);
                        curr.rules.push(group);
                        curr = group;
                    }
                    curr.condition = data.operation.toUpperCase();
                    i++;
                    var next = curr;
                    flatten(data.left, i);
                    curr = next;
                    flatten(data.right, i);
                } else {
                    if ($.isPlainObject(data.right.value)) {
                        Utils.error("SQLParse", "Value format not supported for {0}.", data.left.value);
                    }
                    var value;
                    if ($.isArray(data.right.value)) {
                        value = data.right.value.map(function(v) {
                            return v.value;
                        });
                    } else {
                        value = data.right.value;
                    }
                    if (stmt) {
                        if ($.isArray(value)) {
                            value = value.map(stmt.parse);
                        } else {
                            value = stmt.parse(value);
                        }
                    }
                    var operator = data.operation.toUpperCase();
                    if (operator == "<>") {
                        operator = "!=";
                    }
                    var sqlrl = self.settings.sqlRuleOperator[operator];
                    if (sqlrl === undefined) {
                        Utils.error("UndefinedSQLOperator", 'Invalid SQL operation "{0}".', data.operation);
                    }
                    var opVal = sqlrl.call(this, value, data.operation);
                    var field;
                    if ("values" in data.left) {
                        field = data.left.values.join(".");
                    } else if ("value" in data.left) {
                        field = data.left.value;
                    } else {
                        Utils.error("SQLParse", "Cannot find field name in {0}", JSON.stringify(data.left));
                    }
                    var id = self.getSQLFieldID(field, value);
                    var rule = self.change("sqlToRule", {
                        id: id,
                        field: field,
                        operator: opVal.op,
                        value: opVal.val
                    }, data);
                    curr.rules.push(rule);
                }
            })(data, 0);
            return out;
        },
        setRulesFromSQL: function(query, stmt) {
            this.setRules(this.getRulesFromSQL(query, stmt));
        },
        getSQLFieldID: function(field, value) {
            var matchingFilters = this.filters.filter(function(filter) {
                return filter.field.toLowerCase() === field.toLowerCase();
            });
            var id;
            if (matchingFilters.length === 1) {
                id = matchingFilters[0].id;
            } else {
                id = this.change("getSQLFieldID", field, value);
            }
            return id;
        }
    });
    function getStmtConfig(stmt) {
        var config = stmt.match(/(question_mark|numbered|named)(?:\((.)\))?/);
        if (!config) config = [ null, "question_mark", undefined ];
        return config;
    }
    QueryBuilder.define("unique-filter", function() {
        this.status.used_filters = {};
        this.on("afterUpdateRuleFilter", this.updateDisabledFilters);
        this.on("afterDeleteRule", this.updateDisabledFilters);
        this.on("afterCreateRuleFilters", this.applyDisabledFilters);
        this.on("afterReset", this.clearDisabledFilters);
        this.on("afterClear", this.clearDisabledFilters);
        this.on("getDefaultFilter.filter", function(e, model) {
            var self = e.builder;
            self.updateDisabledFilters();
            if (e.value.id in self.status.used_filters) {
                var found = self.filters.some(function(filter) {
                    if (!(filter.id in self.status.used_filters) || self.status.used_filters[filter.id].length > 0 && self.status.used_filters[filter.id].indexOf(model.parent) === -1) {
                        e.value = filter;
                        return true;
                    }
                });
                if (!found) {
                    Utils.error(false, "UniqueFilter", "No more non-unique filters available");
                    e.value = undefined;
                }
            }
        });
    });
    QueryBuilder.extend({
        updateDisabledFilters: function(e) {
            var self = e ? e.builder : this;
            self.status.used_filters = {};
            if (!self.model) {
                return;
            }
            (function walk(group) {
                group.each(function(rule) {
                    if (rule.filter && rule.filter.unique) {
                        if (!self.status.used_filters[rule.filter.id]) {
                            self.status.used_filters[rule.filter.id] = [];
                        }
                        if (rule.filter.unique == "group") {
                            self.status.used_filters[rule.filter.id].push(rule.parent);
                        }
                    }
                }, function(group) {
                    walk(group);
                });
            })(self.model.root);
            self.applyDisabledFilters(e);
        },
        clearDisabledFilters: function(e) {
            var self = e ? e.builder : this;
            self.status.used_filters = {};
            self.applyDisabledFilters(e);
        },
        applyDisabledFilters: function(e) {
            var self = e ? e.builder : this;
            self.$el.find(QueryBuilder.selectors.filter_container + " option").prop("disabled", false);
            $.each(self.status.used_filters, function(filterId, groups) {
                if (groups.length === 0) {
                    self.$el.find(QueryBuilder.selectors.filter_container + ' option[value="' + filterId + '"]:not(:selected)').prop("disabled", true);
                } else {
                    groups.forEach(function(group) {
                        group.each(function(rule) {
                            rule.$el.find(QueryBuilder.selectors.filter_container + ' option[value="' + filterId + '"]:not(:selected)').prop("disabled", true);
                        });
                    });
                }
            });
            if (self.settings.plugins && self.settings.plugins["bt-selectpicker"]) {
                self.$el.find(QueryBuilder.selectors.rule_filter).selectpicker("render");
            }
        }
    });
    QueryBuilder.regional["en"] = {
        __locale: "English (en)",
        __author: 'Damien "Mistic" Sorel, http://www.strangeplanet.fr',
        add_rule: t("querybuilder.common.add_rule"),
        add_group: t("querybuilder.common.add_group"),
        delete_rule: t("querybuilder.common.delete_rule"),
        delete_group: t("querybuilder.common.delete_group"),
        conditions: {
            AND: t("querybuilder.conditions.AND"),
            OR: t("querybuilder.conditions.OR")
        },
        operators: {
            equal: t("querybuilder.operators.equal"),
            not_equal: t("querybuilder.operators.not_equal"),
            in: t("querybuilder.operators.in"),
            not_in: t("querybuilder.operators.not_in"),
            less: t("querybuilder.operators.less"),
            less_or_equal: t("querybuilder.operators.less_or_equal"),
            greater: t("querybuilder.operators.greater"),
            greater_or_equal: t("querybuilder.operators.greater_or_equal"),
            between: t("querybuilder.operators.between"),
            not_between: t("querybuilder.operators.not_between"),
            begins_with: t("querybuilder.operators.begins_with"),
            not_begins_with: t("querybuilder.operators.not_begins_with"),
            contains: t("querybuilder.operators.contains"),
            not_contains: t("querybuilder.operators.not_contains"),
            ends_with: t("querybuilder.operators.ends_with"),
            not_ends_with: t("querybuilder.operators.not_ends_with"),
            is_empty: t("querybuilder.operators.is_empty"),
            is_not_empty: t("querybuilder.operators.is_not_empty"),
            is_null: t("querybuilder.operators.is_null"),
            is_not_null: t("querybuilder.operators.is_not_null"),
            before: t("querybuilder.operators.before"),
            after: t("querybuilder.operators.after"),
            like: "Like",
            not_like: "Not like"
        },
        errors: {
            no_filter: t("querybuilder.errors.no_filter"),
            empty_group: t("querybuilder.errors.empty_group"),
            radio_empty: t("querybuilder.errors.radio_empty"),
            checkbox_empty: t("querybuilder.errors.checkbox_empty"),
            select_empty: t("querybuilder.errors.select_empty"),
            string_empty: t("querybuilder.errors.string_empty"),
            string_exceed_min_length: t("querybuilder.errors.string_exceed_min_length"),
            string_exceed_max_length: t("querybuilder.errors.string_exceed_max_length"),
            string_invalid_format: t("querybuilder.errors.string_invalid_format"),
            number_nan: t("querybuilder.errors.number_nan"),
            number_not_integer: t("querybuilder.errors.number_not_integer"),
            number_not_double: t("querybuilder.errors.number_not_double"),
            number_exceed_min: t("querybuilder.errors.number_exceed_min"),
            number_exceed_max: t("querybuilder.errors.number_exceed_max"),
            number_wrong_step: t("querybuilder.errors.number_wrong_step"),
            number_between_invalid: "Invalid values, {0} is greater than {1}",
            datetime_empty: t("querybuilder.errors.datetime_empty"),
            datetime_invalid: t("querybuilder.errors.datetime_invalid"),
            datetime_exceed_min: t("querybuilder.errors.datetime_exceed_min"),
            datetime_exceed_max: t("querybuilder.errors.datetime_exceed_max"),
            datetime_between_invalid: "Invalid values, {0} is greater than {1}",
            boolean_not_valid: t("querybuilder.errors.boolean_not_valid"),
            operator_not_multiple: t("querybuilder.errors.operator_not_multiple")
        },
        invert: t("querybuilder.common.invert"),
        NOT: "NOT"
    };
    QueryBuilder.defaults({
        lang_code: "en"
    });
    return QueryBuilder;
});

(function() {
    var Action;
    Action = function(events, action, $scope) {
        var self = this;
        action = _.bind(action, this);
        if ($scope && $scope.exists()) {
            $scope = $scope.first();
        } else {
            $scope = $(document);
        }
        _.each(events, function(selector, trigger) {
            $scope.on(trigger, selector, function(e, data) {
                self.event = e;
                self.trigger = trigger;
                self.el = $(this);
                self.data = data;
                action();
                var $target = $(self.event.target);
                if ($target.is("a") || $target.parent("a").length === 1) {
                    self.event.preventDefault();
                }
            });
        });
    };
    Action.new = function(events, action, $scope) {
        new Action(events, action, $scope);
    };
    Action.translate = function(events) {
        var cevents = {};
        _.each(events, function(triggers, e) {
            triggers = triggers.split(/,\s?/);
            triggers = _.map(triggers, function(t) {
                return '[data-action="' + t + '"]';
            }).join(", ");
            cevents[e] = triggers;
        });
        return cevents;
    };
    AGN.Lib.Action = Action;
})();

(function() {
    function checkPossibleRestoration(scopeId, check, restore) {
        var bundle = AGN.Lib.Storage.get("autosave#" + scopeId);
        if (bundle) {
            var result = check ? check(bundle.values, bundle.timestamp) : bundle.values;
            if (result) {
                var dialog = AGN.Lib.Template.text("autosave-restore", {
                    modalClass: "",
                    title: t("autosave.confirm.title"),
                    content: t("autosave.confirm.question", new Date(bundle.timestamp).toLocaleString(window.adminLocale, {
                        year: "numeric",
                        month: "2-digit",
                        day: "2-digit",
                        hour: "2-digit",
                        minute: "2-digit",
                        second: "2-digit"
                    })),
                    negative: t("autosave.discard"),
                    positive: t("autosave.restore")
                });
                var deferred = AGN.Lib.Confirm.create(dialog).done(function() {
                    restore(result === true ? bundle.values : result, bundle.timestamp);
                    AGN.Lib.Messages(t("autosave.success.title"), t("autosave.success.message"), "success");
                }).always(function() {
                    AGN.Lib.Storage.delete("autosave#" + scopeId);
                });
                return deferred.promise();
            } else {
                AGN.Lib.Storage.delete("autosave#" + scopeId);
            }
        }
        return $.Deferred().reject().promise();
    }
    function scheduleAutoSave(scopeId, save, period) {
        var doSave = function() {
            var values = save();
            if (values) {
                AGN.Lib.Storage.set("autosave#" + scopeId, {
                    timestamp: new Date().getTime(),
                    values: values
                });
            }
            return values !== false;
        };
        if (period > 0) {
            var timerHandle = setInterval(function() {
                doSave() || clearInterval(timerHandle);
            }, period * 1e3);
        }
        var doSaveOnUnauthorized = function() {
            doSave() || $(document).unbind("ajax:unauthorized", doSaveOnUnauthorized);
        };
        $(document).on("ajax:unauthorized", doSaveOnUnauthorized);
    }
    AGN.Lib.AutoSave = {
        initialize: function(scopeId, save, check, restore, period) {
            var promise = checkPossibleRestoration(scopeId, check, restore);
            scheduleAutoSave(scopeId, save, period);
            return promise;
        }
    };
})();

(function() {
    AGN.Lib.Breadcrumbs = {
        truncate: function($scope) {
            $.each($scope.find(".breadcrumbs.js-ellipsis"), function(index, e) {
                var $breadcrumb = $(e);
                var $items = $breadcrumb.children("li");
                $breadcrumb.find("*").removeClass("breadcrumb-element-small");
                $items.removeClass("abbreviated");
                $items.css({
                    "min-width": "",
                    "max-width": ""
                });
                $items.show();
                if (checkListItemsWidth($breadcrumb)) {
                    return;
                }
                $breadcrumb.find("*").addClass("breadcrumb-element-small");
                if (checkListItemsWidth($breadcrumb)) {
                    return;
                }
                var itemsSizes = [];
                var freeSpace = $breadcrumb.parent().width();
                $.each($items, function(index, e) {
                    var $currentItem = $(e);
                    if ($currentItem.hasClass("js-ellipsis")) {
                        var content = $currentItem.html();
                        $currentItem.html("&hellip;");
                        var widthWithThreeDots = $currentItem.outerWidth(true);
                        $currentItem.html(content);
                        var widthWithContent = $currentItem.outerWidth(true);
                        var minimumWidth = widthWithThreeDots < widthWithContent ? widthWithThreeDots : widthWithContent;
                        $currentItem.addClass("abbreviated");
                        var widthWithContentAbbreviated = $currentItem.outerWidth(true);
                        $currentItem.removeClass("abbreviated");
                        itemsSizes.unshift({
                            $item: $currentItem,
                            width: widthWithContent,
                            minimumWidth: minimumWidth + 1,
                            minimumWidthAbbreviated: minimumWidth + (widthWithContentAbbreviated - widthWithContent) + 1
                        });
                    } else {
                        freeSpace -= $currentItem.outerWidth(true);
                    }
                });
                var lastItemIndex = itemsSizes.length - 1;
                for (var i = 0; i <= lastItemIndex; i++) {
                    var itemSize = itemsSizes[i];
                    var $item = itemSize.$item;
                    itemSize.width = $item.outerWidth(true);
                    if (itemSize.width > freeSpace) {
                        var minimumWidth;
                        if (i == lastItemIndex) {
                            minimumWidth = itemSize.minimumWidth;
                        } else {
                            $item.addClass("abbreviated");
                            minimumWidth = itemSize.minimumWidthAbbreviated;
                            for (var k = i + 1; k <= lastItemIndex; k++) {
                                itemsSizes[k].$item.hide();
                            }
                        }
                        if (minimumWidth > freeSpace && i > 0) {
                            $item.hide();
                            var previousItemSize = itemsSizes[i - 1];
                            var $previousItem = previousItemSize.$item;
                            $previousItem.addClass("abbreviated");
                            if ($previousItem.outerWidth(true) - previousItemSize.width > freeSpace) {
                                $previousItem.css("max-width", previousItemSize.width + freeSpace);
                            }
                        } else {
                            $item.css("max-width", freeSpace);
                        }
                        break;
                    } else {
                        freeSpace -= itemSize.width;
                    }
                }
            });
        }
    };
    function checkListItemsWidth($container) {
        var maximumWidth = $container.parent().width();
        var listItemsWidth = 0;
        $container.children("li").each(function() {
            listItemsWidth += $(this).outerWidth(true);
        });
        return Math.floor(listItemsWidth) <= Math.floor(maximumWidth);
    }
})();

(function() {
    function setViaClipboardApi(value, callback) {
        try {
            navigator.clipboard.writeText(value).then(function() {
                callback(true);
            }, function() {
                callback(false);
            });
        } catch (e) {
            console.warn(e);
            callback(false);
        }
    }
    function setViaTempInput(value, callback) {
        var success = true;
        try {
            var $input = $("<input>");
            $("body").append($input);
            $input.val(value);
            $input.select();
            document.execCommand("copy");
            $input.remove();
        } catch (e) {
            console.warn(e);
            success = false;
        }
        if (callback) {
            callback(success);
        }
    }
    AGN.Lib.Clipboard = {
        set: function(value, callback) {
            setViaClipboardApi(value, function(success1) {
                if (success1) {
                    if (callback) {
                        callback(value, true);
                    }
                } else {
                    setViaTempInput(value, function(success2) {
                        if (callback) {
                            callback(value, success2);
                        }
                    });
                }
            });
        }
    };
})();

(function() {
    var Confirm;
    Confirm = function($modal, deferred) {
        this.$modal = $modal;
        this.deferred = deferred || $.Deferred();
    };
    Confirm.get = function($needle) {
        var $confirm = Confirm.getWrapper($needle);
        return $confirm.data("_confirm");
    };
    Confirm.create = function(html, deferred) {
        var confirm, modal = AGN.Lib.Modal.create(html);
        confirm = new Confirm(modal, deferred);
        modal.data("_confirm", confirm);
        return confirm.promise();
    };
    Confirm.createFromTemplate = function(conf, template, deferred) {
        var confirm, modal = AGN.Lib.Modal.createFromTemplate(conf, template);
        confirm = new Confirm(modal, deferred);
        modal.data("_confirm", confirm);
        return confirm.promise();
    };
    Confirm.request = function(source) {
        var deferred = $.Deferred();
        var jqxhr;
        if (_.isString(source)) {
            jqxhr = $.get(source);
        } else {
            jqxhr = source;
        }
        jqxhr.done(function(resp) {
            var $resp = $(resp), $modal = $resp.all(".modal");
            if ($modal.length === 1) {
                var confirm = new Confirm($modal, deferred);
                $modal.data("_confirm", confirm);
                AGN.Lib.Modal.create($modal);
            } else {
                AGN.Lib.Page.render(resp);
                deferred.reject();
            }
        }).fail(function() {
            deferred.reject();
        });
        return deferred.promise();
    };
    Confirm.getWrapper = function($needle) {
        var $confirm;
        $confirm = $($needle.data("confirm-target"));
        if ($confirm.length == 0) {
            $confirm = $needle.closest(".modal");
        }
        return $confirm;
    };
    Confirm.prototype.promise = function() {
        return this.deferred.promise();
    };
    Confirm.prototype.positive = function(resp) {
        this.deferred.resolve(resp);
        this.$modal.modal("hide");
        this.$modal.remove();
    };
    Confirm.prototype.negative = function(resp) {
        this.deferred.reject(resp);
        this.$modal.modal("hide");
        this.$modal.remove();
    };
    AGN.Lib.Confirm = Confirm;
})();

(function() {
    AGN.Lib.ContextMenu = {
        create: function(params) {
            $.each(params, function(selector, config) {
                $.contextMenu({
                    selector: selector,
                    build: function($element, event) {
                        return build(config, $element, event);
                    }
                });
            });
        }
    };
    function build(config, $element, event) {
        if (config.shown === false || _.isFunction(config.shown) && config.shown($element, event) === false) {
            return false;
        }
        var definitions = config.items;
        if (_.isFunction(definitions)) {
            definitions = definitions($element, event);
        }
        var items = {};
        var count = 0;
        $.each(definitions, function(key, options) {
            if (!_.isFunction(options.shown) || options.shown($element, event) !== false) {
                var item = items[key] = {
                    name: options.name,
                    icon: options.icon
                };
                if (_.isFunction(options.disabled)) {
                    item.disabled = options.disabled($element, event) === true;
                } else if (options.disabled === true) {
                    item.disabled = true;
                }
                if (_.isFunction(options.clicked)) {
                    item.callback = function(k, opts) {
                        options.clicked($element, k, opts);
                    };
                }
                count++;
            }
        });
        return count ? {
            items: items
        } : false;
    }
})();

(function() {
    var Controller;
    Controller = function(func) {
        func = _.bind(func, this);
        func();
    };
    Controller.prototype.addAction = function(events, action) {
        AGN.Lib.Action.new(AGN.Lib.Action.translate(events), action);
    };
    Controller.prototype.addInitializer = function(name, initializer) {
        AGN.Lib.CoreInitializer.new(name, initializer);
    };
    Controller.prototype.addDomInitializer = function(name, initializer) {
        AGN.Lib.DomInitializer.new(name, initializer);
    };
    Controller.prototype.runInitializer = function(name) {
        AGN.Lib.CoreInitializer.run(name);
    };
    Controller.new = function(name, func) {
        AGN.Opt.Controllers[name] = func;
    };
    Controller.init = function($scope) {
        if (!$scope) {
            $scope = $(document);
        }
        $scope.all("[data-controller]").each(function() {
            var $controller = $(this), init = AGN.Opt.Controllers[$controller.data("controller")];
            if (init) {
                new AGN.Lib.Controller(init);
                AGN.Opt.Controllers[$controller.data("controller")] = undefined;
            }
        });
    };
    AGN.Lib.Controller = Controller;
})();

(function() {
    var map = {};
    function register(name) {
        var dependencies = null;
        var handler;
        if (arguments.length > 2) {
            dependencies = arguments[1];
            handler = arguments[2];
        } else {
            handler = arguments[1];
        }
        if (_.isFunction(handler)) {
            map["key#" + name] = {
                name: name,
                handler: handler,
                dependencies: dependencies
            };
        } else {
            console.error("Handler must be a function");
        }
    }
    function execute($scope, initializer, executed, pending) {
        var key = "key#" + initializer.name;
        if (executed[key]) {
            return;
        }
        if (Array.isArray(initializer.dependencies) && initializer.dependencies.length) {
            pending.push(initializer.name);
            initializer.dependencies.forEach(function(dependencyName) {
                var dependency = map["key#" + dependencyName];
                if (dependency) {
                    if (pending.includes(dependencyName)) {
                        var description = pending.map(function(value) {
                            return "`" + value + "`";
                        }).join(" => ");
                        console.error("Cyclic initializer dependency detected (" + description + " => `" + dependencyName + "`)");
                        return;
                    }
                    execute($scope, dependency, executed, pending);
                } else {
                    console.error("Unknown initializer dependency: `" + name + "`");
                }
            });
            pending.pop();
        }
        try {
            initializer.handler.call(initializer.handler, $scope);
        } catch (e) {
            console.error(e);
        }
        executed[key] = true;
    }
    function autorun($scope) {
        var executed = {};
        var pending = [];
        $.each(map, function(k, initializer) {
            execute($scope, initializer, executed, pending);
        });
    }
    function run(name, $scope) {
        if (Array.isArray(name)) {
            name.forEach(function(nm) {
                run(nm, $scope);
            });
        } else {
            var initializer = map["key#" + name];
            if (initializer) {
                initializer.handler.call(initializer.handler, $scope);
                return true;
            } else {
                console.error("Unknown initializer: `" + name + "`");
                return false;
            }
        }
    }
    AGN.Lib.CoreInitializer = {
        autorun: autorun,
        run: run,
        new: register
    };
})();

(function() {
    function readActualToken() {
        if (isProtectionEnabled()) {
            return AGN.Lib.Storage.readCookie(window.csrfCookieName);
        }
        return "";
    }
    function getParameterName() {
        return window.csrfParameterName;
    }
    function isProtectionEnabled() {
        return window.csrfHeaderName && getParameterName() && window.csrfCookieName;
    }
    function setTokenToReqHeader(jqxhr, reqType) {
        if (isProtectionEnabled() && reqType !== "GET") {
            const csrfToken = readActualToken();
            jqxhr.setRequestHeader(window.csrfHeaderName, csrfToken);
        }
    }
    function updateTokenInDOM($scope, needsHtmlInResult) {
        if (!isProtectionEnabled()) {
            return $scope;
        }
        if (!$scope) {
            $scope = $(document);
        } else if (!($scope instanceof $)) {
            $scope = $("<div>").append($scope);
        }
        const csrfToken = readActualToken();
        const $tokenInputs = $scope.find('input[name="' + window.csrfParameterName + '"]');
        _.each($tokenInputs, function(input) {
            $(input).val(csrfToken);
        });
        if (needsHtmlInResult) {
            return $scope.html();
        }
    }
    AGN.Lib.CSRF = {
        readActualToken: readActualToken,
        isProtectionEnabled: isProtectionEnabled,
        setTokenToReqHeader: setTokenToReqHeader,
        getParameterName: getParameterName,
        updateTokenInDOM: updateTokenInDOM
    };
})();

(function() {
    var DataProvider = {};
    DataProvider.get = function($element) {
        var type = $element.data("provider"), src = $element.data("provider-src"), provider;
        switch (type) {
          case "opt":
            provider = DataProvider.opt(src);
            break;

          case "remote":
            provider = DataProvider.remote(src);
            break;

          default:
            break;
        }
        return provider;
    };
    DataProvider.opt = function(src) {
        var deferred = $.Deferred();
        if (AGN.Opt[src]) {
            setTimeout(function() {
                deferred.resolve(AGN.Opt[src]);
            }, 100);
        } else {
            setTimeout(function() {
                deferred.reject();
            }, 100);
        }
        return deferred;
    };
    DataProvider.remote = function(src) {
        return $.get(src);
    };
    AGN.Lib.DataProvider = DataProvider;
})();

(function() {
    var DateFormat;
    DateFormat = {
        MONTH_NAMES: [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ],
        DAY_NAMES: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ],
        LZ: function(x) {
            return (x < 0 || x > 9 ? "" : "0") + x;
        },
        compareDates: function(date1, dateformat1, date2, dateformat2) {
            var d1 = DateFormat.parseFormat(date1, dateformat1);
            var d2 = DateFormat.parseFormat(date2, dateformat2);
            if (d1 == 0 || d2 == 0) return -1; else if (d1 > d2) return 1;
            return 0;
        },
        format: function(date, format) {
            format = format + "";
            var result = "";
            var i_format = 0;
            var c = "";
            var token = "";
            var y = date.getYear() + "";
            var M = date.getMonth() + 1;
            var d = date.getDate();
            var E = date.getDay();
            var H = date.getHours();
            var m = date.getMinutes();
            var s = date.getSeconds();
            var yyyy, yy, MMM, MM, dd, hh, h, mm, ss, ampm, HH, H, KK, K, kk, k;
            var value = new Object();
            if (y.length < 4) {
                y = "" + (y - 0 + 1900);
            }
            value["y"] = "" + y;
            value["yyyy"] = y;
            value["yy"] = y.substring(2, 4);
            value["M"] = M;
            value["MM"] = DateFormat.LZ(M);
            value["MMM"] = DateFormat.MONTH_NAMES[M - 1];
            value["NNN"] = DateFormat.MONTH_NAMES[M + 11];
            value["d"] = d;
            value["dd"] = DateFormat.LZ(d);
            value["E"] = DateFormat.DAY_NAMES[E + 7];
            value["EE"] = DateFormat.DAY_NAMES[E];
            value["H"] = H;
            value["HH"] = DateFormat.LZ(H);
            if (H == 0) {
                value["h"] = 12;
            } else if (H > 12) {
                value["h"] = H - 12;
            } else {
                value["h"] = H;
            }
            value["hh"] = DateFormat.LZ(value["h"]);
            if (H > 11) {
                value["K"] = H - 12;
            } else {
                value["K"] = H;
            }
            value["k"] = H + 1;
            value["KK"] = DateFormat.LZ(value["K"]);
            value["kk"] = DateFormat.LZ(value["k"]);
            if (H > 11) {
                value["a"] = "PM";
            } else {
                value["a"] = "AM";
            }
            value["m"] = m;
            value["mm"] = DateFormat.LZ(m);
            value["s"] = s;
            value["ss"] = DateFormat.LZ(s);
            while (i_format < format.length) {
                c = format.charAt(i_format);
                token = "";
                while (format.charAt(i_format) == c && i_format < format.length) token += format.charAt(i_format++);
                if (value[token] != null) result += value[token]; else result += token;
            }
            return result;
        },
        _isInteger: function(val) {
            var digits = "1234567890";
            for (var i = 0; i < val.length; i++) if (digits.indexOf(val.charAt(i)) == -1) return false;
            return true;
        },
        _getInt: function(str, i, minlength, maxlength) {
            for (var x = maxlength; x >= minlength; x--) {
                var token = str.substring(i, i + x);
                if (token.length < minlength) return null;
                if (DateFormat._isInteger(token)) return token;
            }
            return null;
        },
        parseFormat: function(val, format) {
            val = val + "";
            format = format + "";
            var i_val = 0;
            var i_format = 0;
            var c = "";
            var token = "";
            var token2 = "";
            var x, y;
            var now = new Date();
            var year = now.getYear();
            var month = now.getMonth() + 1;
            var date = 1;
            var hh = now.getHours();
            var mm = now.getMinutes();
            var ss = now.getSeconds();
            var ampm = "";
            while (i_format < format.length) {
                c = format.charAt(i_format);
                token = "";
                while (format.charAt(i_format) == c && i_format < format.length) token += format.charAt(i_format++);
                if (token == "yyyy" || token == "yy" || token == "y") {
                    if (token == "yyyy") x = 4;
                    y = 4;
                    if (token == "yy") x = 2;
                    y = 2;
                    if (token == "y") x = 2;
                    y = 4;
                    year = DateFormat._getInt(val, i_val, x, y);
                    if (year == null) return 0;
                    i_val += year.length;
                    if (year.length == 2) {
                        if (year > 70) year = 1900 + (year - 0); else year = 2e3 + (year - 0);
                    }
                } else if (token == "MMM" || token == "NNN") {
                    month = 0;
                    for (var i = 0; i < DateFormat.MONTH_NAMES.length; i++) {
                        var month_name = DateFormat.MONTH_NAMES[i];
                        if (val.substring(i_val, i_val + month_name.length).toLowerCase() == month_name.toLowerCase()) {
                            if (token == "MMM" || token == "NNN" && i > 11) {
                                month = i + 1;
                                if (month > 12) month -= 12;
                                i_val += month_name.length;
                                break;
                            }
                        }
                    }
                    if (month < 1 || month > 12) return 0;
                } else if (token == "EE" || token == "E") {
                    for (var i = 0; i < DateFormat.DAY_NAMES.length; i++) {
                        var day_name = DateFormat.DAY_NAMES[i];
                        if (val.substring(i_val, i_val + day_name.length).toLowerCase() == day_name.toLowerCase()) {
                            i_val += day_name.length;
                            break;
                        }
                    }
                } else if (token == "MM" || token == "M") {
                    month = DateFormat._getInt(val, i_val, token.length, 2);
                    if (month == null || month < 1 || month > 12) return 0;
                    i_val += month.length;
                } else if (token == "dd" || token == "d") {
                    date = DateFormat._getInt(val, i_val, token.length, 2);
                    if (date == null || date < 1 || date > 31) return 0;
                    i_val += date.length;
                } else if (token == "hh" || token == "h") {
                    hh = DateFormat._getInt(val, i_val, token.length, 2);
                    if (hh == null || hh < 1 || hh > 12) return 0;
                    i_val += hh.length;
                } else if (token == "HH" || token == "H") {
                    hh = DateFormat._getInt(val, i_val, token.length, 2);
                    if (hh == null || hh < 0 || hh > 23) return 0;
                    i_val += hh.length;
                } else if (token == "KK" || token == "K") {
                    hh = DateFormat._getInt(val, i_val, token.length, 2);
                    if (hh == null || hh < 0 || hh > 11) return 0;
                    i_val += hh.length;
                } else if (token == "kk" || token == "k") {
                    hh = DateFormat._getInt(val, i_val, token.length, 2);
                    if (hh == null || hh < 1 || hh > 24) return 0;
                    i_val += hh.length;
                    hh--;
                } else if (token == "mm" || token == "m") {
                    mm = DateFormat._getInt(val, i_val, token.length, 2);
                    if (mm == null || mm < 0 || mm > 59) return 0;
                    i_val += mm.length;
                } else if (token == "ss" || token == "s") {
                    ss = DateFormat._getInt(val, i_val, token.length, 2);
                    if (ss == null || ss < 0 || ss > 59) return 0;
                    i_val += ss.length;
                } else if (token == "a") {
                    if (val.substring(i_val, i_val + 2).toLowerCase() == "am") ampm = "AM"; else if (val.substring(i_val, i_val + 2).toLowerCase() == "pm") ampm = "PM"; else return 0;
                    i_val += 2;
                } else {
                    if (val.substring(i_val, i_val + token.length) != token) return 0; else i_val += token.length;
                }
            }
            if (i_val != val.length) return 0;
            if (month == 2) {
                if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
                    if (date > 29) return 0;
                } else if (date > 28) {
                    return 0;
                }
            }
            if (month == 4 || month == 6 || month == 9 || month == 11) if (date > 30) return 0;
            if (hh < 12 && ampm == "PM") hh = hh - 0 + 12; else if (hh > 11 && ampm == "AM") hh -= 12;
            var newdate = new Date(year, month - 1, date, hh, mm, ss);
            return newdate;
        },
        parse: function(val, format) {
            if (format) {
                return DateFormat.parseFormat(val, format);
            } else {
                var preferEuro = arguments.length == 2 ? arguments[1] : false;
                var generalFormats = new Array("y-M-d", "MMM d, y", "MMM d,y", "y-MMM-d", "d-MMM-y", "MMM d");
                var monthFirst = new Array("M/d/y", "M-d-y", "M.d.y", "MMM-d", "M/d", "M-d");
                var dateFirst = new Array("d/M/y", "d-M-y", "d.M.y", "d-MMM", "d/M", "d-M");
                var checkList = [ generalFormats, preferEuro ? dateFirst : monthFirst, preferEuro ? monthFirst : dateFirst ];
                var d = null;
                for (var i = 0; i < checkList.length; i++) {
                    var l = checkList[i];
                    for (var j = 0; j < l.length; j++) {
                        d = DateFormat.parseFormat(val, l[j]);
                        if (d != 0) return new Date(d);
                    }
                }
                return null;
            }
        },
        toArray: function(date, stub) {
            if (date && date.getMonth) {
                return [ date.getFullYear(), date.getMonth(), date.getDate() ];
            } else {
                return stub;
            }
        }
    };
    AGN.Lib.DateFormat = DateFormat;
})();

(function() {
    var SCRIPT_JSON_SELECTOR = 'script[type="application/json"]';
    var CONFIG_PREFIX = "config:";
    var map = {};
    function Context($e, name) {
        this.el = $e;
        if ($e.is(SCRIPT_JSON_SELECTOR)) {
            this.config = $e.json();
        } else {
            var $config = $e.find("script#" + CSS.escape(CONFIG_PREFIX + name));
            if ($config.exists()) {
                var type = $config.attr("type");
                if (!type || type === "application/json") {
                    this.config = $config.json();
                } else {
                    console.error("Unexpected config script type: `" + type + "`");
                }
            }
        }
    }
    Context.prototype.addAction = function(events, action) {
        AGN.Lib.Action.new(AGN.Lib.Action.translate(events), action, this.el);
    };
    function autorun($scope) {
        var $root = $scope;
        if (!$root) {
            $root = $(document);
        }
        $root.all("[data-initializer]").each(function() {
            var $elem = $(this);
            run($elem.data("initializer"), $elem, $scope);
        });
    }
    function run(name, $elem, $scope) {
        var handler = map["key#" + name];
        if (handler) {
            var result = handler.call(new Context($elem, name), $elem, $scope);
            if (result === false) {
                map["key#" + name] = undefined;
            }
            return true;
        } else {
            return false;
        }
    }
    function tryRun(name, $scope) {
        if (map["key#" + name]) {
            var $root = $scope;
            if (!$root) {
                $root = $(document);
            }
            $root.all('[data-initializer="' + CSS.escape(name) + '"]').each(function() {
                run(name, $(this), $scope);
            });
        }
    }
    function register(name, handler) {
        if (_.isFunction(handler)) {
            map["key#" + name] = handler;
        } else {
            console.error("Handler must be a function");
        }
    }
    AGN.Lib.DomInitializer = {
        autorun: autorun,
        run: run,
        try: tryRun,
        new: register
    };
})();

(function() {
    var Editor, EditorHtml, EditorText, EditorEql, EditorCss;
    Editor = function(textArea) {
        var self = this, target, $containerEditor, id, readOnly;
        this.el = $(textArea);
        readOnly = !!this.el.attr("readonly");
        this.isFullHeight = !!this.el.data("full-height-editor");
        this.height = parseInt(this.el.attr("rows") || 15) * 15;
        target = this.el.attr("id") + "Editor";
        $containerEditor = $("#" + target);
        if ($containerEditor.length === 1) {
            id = target;
            var isFullHeightEditor = $containerEditor.data("full-height-editor");
            $containerEditor.css("height", isFullHeightEditor ? "100%" : this.height + "px");
        } else {
            id = _.uniqueId("Editor");
            $containerEditor = $('<div id="' + id + '" class="form-control"></div>');
            $containerEditor.css("height", this.isFullHeight ? "100%" : this.height + "px");
            $containerEditor.insertAfter($(this.el));
        }
        this.el.hide();
        this.editor = ace.edit(id);
        this.editor.setReadOnly(readOnly);
        this.editor.getSession().setValue(this.el.val());
        this.editor.getSession().on("change", function(e) {
            self.el.val(self.editor.getSession().getValue());
            self.el.trigger("editor:change");
        });
        this.langTools = ace.require("ace/ext/language_tools");
        this.decorate();
        if (this.el.hasClass("js-editor-validate")) {
            this.editor.getSession().setUseWorker(true);
        }
        if (this.el.hasClass("js-editor-wrap")) {
            this.editor.getSession().setUseWrapMode(true);
        }
        self.el.trigger("editor:create");
    };
    Editor.get = function($textArea) {
        var editor = $textArea.data("_editor");
        if (editor) {
            return editor;
        }
        if ($textArea.hasClass("js-editor")) {
            editor = new EditorHtml($textArea);
        } else if ($textArea.hasClass("js-editor-text")) {
            editor = new EditorText($textArea);
        } else if ($textArea.hasClass("js-editor-eql")) {
            editor = new EditorEql($textArea);
        } else if ($textArea.hasClass("js-editor-css")) {
            editor = new EditorCss($textArea);
        }
        $textArea.data("_editor", editor);
        return editor;
    };
    Editor.all = function() {
        return _.map($(".js-editor, .js-editor-text, .js-editor-eql, .js-editor-css"), function(editor) {
            return Editor.get($(editor));
        });
    };
    Editor.prototype.decorate = function() {
        if ($("body").hasClass("dark-theme")) {
            this.editor.setTheme("ace/theme/idle_fingers");
        } else {
            this.editor.setTheme("ace/theme/chrome");
        }
        this.editor.session.setUseWrapMode(true);
        this.editor.session.setWrapLimitRange(null, null);
        this.editor.setBehavioursEnabled(true);
        this.editor.setShowPrintMargin(false);
        this.editor.session.setUseSoftTabs(true);
        this.editor.getSession().setUseWorker(false);
        this.editor.setOptions({
            enableBasicAutocompletion: true,
            enableSnippets: true,
            enableLiveAutocompletion: true,
            minLines: 20
        });
    };
    Editor.prototype.resize = function() {
        this.editor.resize();
    };
    Editor.prototype.val = function(val) {
        if (typeof val !== "undefined") {
            this.editor.getSession().setValue(val);
        } else {
            return this.editor.getSession().getValue();
        }
    };
    EditorHtml = function($textArea) {
        Editor.apply(this, $textArea);
    };
    EditorHtml.prototype = Object.create(Editor.prototype);
    EditorHtml.prototype.constructor = EditorHtml;
    EditorHtml.prototype.decorate = function() {
        Editor.prototype.decorate.call(this);
        this.editor.getSession().setMode("ace/mode/html");
    };
    EditorText = function($textArea) {
        Editor.apply(this, $textArea);
    };
    EditorText.prototype = Object.create(Editor.prototype);
    EditorText.prototype.constructor = EditorText;
    EditorText.prototype.decorate = function() {
        if ($("body").hasClass("dark-theme")) {
            this.editor.setTheme("ace/theme/idle_fingers");
        } else {
            this.editor.setTheme("ace/theme/chrome");
        }
        this.editor.session.setUseWrapMode(false);
        this.editor.session.setWrapLimitRange(null, null);
        this.editor.setBehavioursEnabled(true);
        this.editor.setShowPrintMargin(false);
        this.editor.session.setUseSoftTabs(true);
        this.editor.getSession().setUseWorker(false);
        this.editor.setOptions({
            enableBasicAutocompletion: false,
            enableSnippets: false,
            enableLiveAutocompletion: false,
            minLines: 20
        });
        this.editor.getSession().setMode("ace/mode/text");
    };
    EditorEql = function($textArea) {
        Editor.apply(this, $textArea);
    };
    EditorEql.prototype = Object.create(Editor.prototype);
    EditorEql.prototype.constructor = EditorEql;
    EditorEql.prototype.decorate = function() {
        if ($("body").hasClass("dark-theme")) {
            this.editor.setTheme("ace/theme/idle_fingers");
        } else {
            this.editor.setTheme("ace/theme/chrome");
        }
        this.editor.session.setUseWrapMode(false);
        this.editor.session.setWrapLimitRange(null, null);
        this.editor.setBehavioursEnabled(true);
        this.editor.setShowPrintMargin(false);
        this.editor.session.setUseSoftTabs(true);
        this.editor.getSession().setUseWorker(false);
        this.langTools.setCompleters([ this.langTools.keyWordCompleter, this.langTools.snippetCompleter ]);
        this.editor.setOptions({
            enableBasicAutocompletion: true,
            enableSnippets: false,
            enableLiveAutocompletion: true,
            minLines: 20
        });
        ace.config.loadModule("ace/ext/eql_constructions_tokens");
        ace.config.loadModule("ace/ext/eql_constructions_basic");
        ace.config.loadModule("ace/ext/eql_constructions_extended");
        this.editor.getSession().setMode("ace/mode/eql");
    };
    EditorCss = function($textArea) {
        Editor.apply(this, $textArea);
    };
    EditorCss.prototype = Object.create(Editor.prototype);
    EditorCss.prototype.constructor = EditorCss;
    EditorCss.prototype.decorate = function() {
        Editor.prototype.decorate.call(this);
        this.editor.getSession().setMode("ace/mode/css");
    };
    AGN.Lib.Editor = Editor;
    AGN.Lib.EditorHtml = EditorHtml;
    AGN.Lib.EditorText = EditorText;
    AGN.Lib.EditorEql = EditorEql;
    AGN.Lib.EditorCss = EditorCss;
})();

(function() {
    var Equalizer;
    Equalizer = function(el) {
        var $el = $(el), $els = $el.find("[data-equalizer-watch]:visible"), type = $el.data("equalizer"), min = parseInt($el.data("equalizer-min")) || 0, max = parseInt($el.data("equalizer-max")) || 1e4, heights, height;
        if ($els.length == 0) {
            return;
        }
        if ($els.length == 1 && type == "min") {
            max = min;
        }
        $els.css({
            height: "",
            overflow: "",
            "overflow-y": ""
        });
        heights = _.map($els, function(e) {
            return $(e).outerHeight(false);
        });
        if (type == "min") {
            height = Math.min.apply(null, heights);
        } else {
            height = Math.max.apply(null, heights);
        }
        if (height < min) {
            height = min;
        }
        if (height > max) {
            height = max;
        }
        $els.css({
            height: height,
            overflow: "hidden",
            "overflow-y": "auto"
        });
    };
    AGN.Lib.Equalizer = Equalizer;
})();

(function() {
    function TimeSchedule() {}
    TimeSchedule.defaults = function() {
        return [ {
            active: false,
            time: ""
        } ];
    };
    TimeSchedule.create = function(scheduleElement, extended) {
        scheduleElement = $.extend(TimeSchedule.defaults()[0], scheduleElement);
        if (extended) {
            return AGN.Lib.Template.dom("schedule-extended-time-wrapper", {
                scheduleElement: scheduleElement
            });
        } else {
            return AGN.Lib.Template.dom("schedule-time-wrapper", {
                scheduleElement: scheduleElement
            });
        }
    };
    TimeSchedule.get = function($needle) {
        return $needle.closest(".schedule-time-wrapper");
    };
    function DayRow($row) {
        var self = this;
        if (!$row.exists()) {
            $row = DayRow.create({});
        }
        self.$rowWrapper = $row;
    }
    DayRow.prototype.toJson = function() {
        var self = this;
        var weekDay = self.$rowWrapper.find("select[name=dayOfTheWeek]").val();
        var scheduledTime = _.map(self.$rowWrapper.find(".schedule-time-wrapper"), function(scheduleTime) {
            var $timeCheckbox = $(scheduleTime).find(".time-checkbox");
            var active = !$timeCheckbox.is(":disabled") && $timeCheckbox.is(":checked"), time = $(scheduleTime).find(".time-input").val();
            return {
                active: active,
                time: time
            };
        });
        var $hourCheckbox = self.$rowWrapper.find(".hour-checkbox");
        var scheduledInterval = {
            active: $hourCheckbox.is(":checked") && !$hourCheckbox.is(":disabled"),
            interval: self.$rowWrapper.find("select.hour-select").val()
        };
        return $.extend(DayRow.defaults(), {
            weekDay: weekDay,
            scheduledTime: scheduledTime,
            scheduledInterval: scheduledInterval
        });
    };
    DayRow.prototype.addSchedule = function(scheduleElement) {
        var self = this, wrapper = self.$rowWrapper;
        var $timeWrapper = TimeSchedule.create(scheduleElement, true);
        wrapper.find(".schedule-settings-wrapper").append($timeWrapper);
        AGN.runAll($timeWrapper);
        wrapper.trigger("row:add-schedule");
    };
    DayRow.prototype.removeSchedule = function($needle) {
        TimeSchedule.get($needle).remove();
        this.$rowWrapper.trigger("row:remove-schedule");
    };
    DayRow.prototype.hourCheckboxToggle = function(el) {
        var toDisable = el.attr("disables"), checked = el.is(":checked");
        this.$rowWrapper.find(toDisable).prop("disabled", checked);
    };
    DayRow.prototype.timeCheckboxToggle = function(el) {
        var toDisable = el.attr("disables"), checked = el.is(":checked"), $timeCheckboxes = this.$rowWrapper.find(".time-checkbox"), $hourCheckbox = this.$rowWrapper.find(".hour-checkbox"), hasChecked;
        for (var i = 0; i < $timeCheckboxes.length; i++) {
            var plainCheckbox = $timeCheckboxes[i];
            if (el[0] !== plainCheckbox && $(plainCheckbox).is(":checked")) {
                hasChecked = true;
                break;
            }
        }
        if (!$hourCheckbox.is(":disabled") || !hasChecked) {
            this.$rowWrapper.find(toDisable).prop("disabled", checked);
        }
    };
    DayRow.prototype.getAllScheduleTimes = function() {
        var rowJson = this.toJson();
        var times = [];
        rowJson.scheduledTime.forEach(function(time) {
            if (time.active) {
                times.push(parseInt(time.time.replace(":", "")));
            }
        });
        return times;
    };
    DayRow.prototype.isValidTimeIntervals = function() {
        var validator = new ScheduleValidation();
        var times = this.getAllScheduleTimes();
        return validator.valid(times);
    };
    DayRow.prototype.showTimeScheduleErrors = function(errorMsg) {
        var timeWrappers = this.$rowWrapper.find(".schedule-time-wrapper");
        var $errorBlock = $('<div class="form-control-feedback-message js-form-error-msg">' + errorMsg + "</div>");
        _.each(timeWrappers, function(time) {
            var $time = $(time);
            if (!$time.find(".js-form-error-msg").exists()) {
                $time.find(".time-input").after($errorBlock.clone());
                $time.addClass("has-alert has-feedback js-form-error");
            }
        });
    };
    DayRow.prototype.hideTimeScheduleErrors = function() {
        var timeWrapper = this.$rowWrapper.find(".schedule-time-wrapper");
        timeWrapper.find(".js-form-error-msg").remove();
        timeWrapper.removeClass("has-alert has-feedback js-form-error");
    };
    DayRow.defaults = function() {
        return {
            weekDay: "",
            scheduledInterval: {
                active: false,
                interval: ""
            },
            scheduledTime: [ {
                active: false,
                time: ""
            } ]
        };
    };
    DayRow.get = function($needle) {
        var $row;
        if ($needle.hasClass("tr.l-time-schedule-row")) {
            $row = $needle;
        } else {
            $row = $needle.closest("tr.l-time-schedule-row");
        }
        return new DayRow($row);
    };
    DayRow.create = function(entry) {
        entry = $.extend(DayRow.defaults(), entry);
        var $row = AGN.Lib.Template.dom("schedule-day-row", {
            entry: entry
        });
        var dayRow = new DayRow($row);
        $row.on("row:add-schedule", function() {
            var timeLines = $row.find(".schedule-time-wrapper");
            var multipleLines = timeLines.length > 1;
            $row.find('[data-action="remove-schedule"]').closest(".input-group-addon").toggleClass("hidden", !multipleLines);
            $row.find(".interval-reminder").toggleClass("hidden", !multipleLines);
            var $hourCheckbox = $row.find(".hour-checkbox");
            dayRow.hourCheckboxToggle($hourCheckbox);
            var $timeCheckbox = $row.find(".time-checkbox");
            dayRow.timeCheckboxToggle($timeCheckbox);
        });
        $row.on("row:remove-schedule", function() {
            var timeLines = $row.find(".schedule-time-wrapper");
            var multipleLines = timeLines.length > 1;
            $row.find('[data-action="remove-schedule"]').closest(".input-group-addon").toggleClass("hidden", !multipleLines);
            $row.find(".interval-reminder").toggleClass("hidden", !multipleLines);
            if (timeLines.length === 0) {
                dayRow.addSchedule();
            }
        });
        return $row;
    };
    DayRow.deserialize = function(data) {
        return DayRow.create(data);
    };
    function PeriodRow($row) {
        var self = this;
        if (!$row.exists()) {
            $row = PeriodRow.create({});
        }
        self.$rowWrapper = $row;
    }
    PeriodRow.prototype.toJson = function() {
        var self = this;
        var type = self.$rowWrapper.find("input[name=type]:checked").val();
        var weekDay = undefined;
        var monthDay = undefined;
        if (type == "TYPE_MONTHLY") {
            monthDay = self.$rowWrapper.find("select[name=dayOfTheMonth]").val();
        } else {
            weekDay = self.$rowWrapper.find("select[name=dayOfTheWeek]").val();
        }
        var scheduledTime = _.map(self.$rowWrapper.find(".schedule-time-wrapper"), function(scheduleTime) {
            var $timeCheckbox = $(scheduleTime).find(".time-checkbox");
            var active = true;
            if ($timeCheckbox.exists()) {
                active = !$timeCheckbox.is(":disabled") && $timeCheckbox.is(":checked");
            }
            var time = $(scheduleTime).find(".time-input").val();
            return {
                active: active,
                time: time
            };
        });
        return $.extend(PeriodRow.defaults(), {
            type: type,
            weekDay: weekDay,
            monthDay: monthDay,
            scheduledTime: scheduledTime
        });
    };
    PeriodRow.prototype.addSchedule = function(scheduleElement) {
        var self = this, wrapper = self.$rowWrapper;
        var $timeWrapper = TimeSchedule.create(scheduleElement);
        wrapper.find(".schedule-settings-wrapper").append($timeWrapper);
        AGN.runAll($timeWrapper);
        wrapper.trigger("row:add-schedule");
    };
    PeriodRow.prototype.removeSchedule = function($needle) {
        TimeSchedule.get($needle).remove();
        this.$rowWrapper.trigger("row:remove-schedule");
    };
    PeriodRow.defaults = function() {
        return {
            type: "1",
            weekDay: "",
            monthDay: "",
            scheduledTime: [ {
                active: false,
                time: ""
            } ]
        };
    };
    PeriodRow.deserialize = function(object, type) {
        var data = $.extend(PeriodRow.defaults(), object);
        data.type = convertTypeToInt(object.type);
        data.monthDay = convertMonthToInt(object.monthDay);
        return PeriodRow.create(data);
    };
    function convertTypeToInt(typeEnumName) {
        switch (typeEnumName) {
          case "TYPE_MONTHLY":
            return 2;

          case "TYPE_WEEKLY":
          default:
            return 1;
        }
    }
    function convertMonthToInt(monthEnumName) {
        switch (monthEnumName) {
          case "TYPE_MONTHLY_FIRST":
            return 1;

          case "TYPE_MONTHLY_15TH":
            return 15;

          case "TYPE_MONTHLY_LAST":
            return 99;

          default:
            return 1;
        }
    }
    PeriodRow.get = function($needle) {
        var $row;
        if ($needle.hasClass("tr.l-time-schedule-row")) {
            $row = $needle;
        } else {
            $row = $needle.closest("tr.l-time-schedule-row");
        }
        return new PeriodRow($row);
    };
    PeriodRow.create = function(entry) {
        entry = $.extend(PeriodRow.defaults(), entry);
        var $row = AGN.Lib.Template.dom("schedule-period-row", {
            entry: entry
        });
        var dayRow = new PeriodRow($row);
        $row.on("row:add-schedule", function() {
            var timeLines = $row.find(".schedule-time-wrapper");
            if (timeLines.length > 1) {
                $row.find('[data-action="remove-schedule"]').closest(".input-group-addon").removeClass("hidden");
            }
        });
        $row.on("row:remove-schedule", function() {
            var timeLines = $row.find(".schedule-time-wrapper");
            if (timeLines.length < 2) {
                $row.find('[data-action="remove-schedule"]').closest(".input-group-addon").addClass("hidden");
            }
            if (timeLines.length === 0) {
                dayRow.addSchedule();
            }
        });
        return $row;
    };
    function ScheduleTimeTable($needle) {
        var self = this;
        self.$container = $needle.find("table tbody");
        self.$container.on("scheduler:add-day", function() {
            var dayLines = self.$container.find(".l-time-schedule-row");
            if (dayLines.length > 1) {
                self.$container.find('[data-action="remove-day"]').removeClass("hidden");
            }
        });
        self.$container.on("scheduler:remove-day", function() {
            var dayLines = self.$container.find(".l-time-schedule-row");
            if (dayLines.length <= 1) {
                dayLines.find('[data-action="remove-day"]').addClass("hidden");
            }
        });
    }
    ScheduleTimeTable.prototype.clean = function() {
        this.$container.find("tr.l-time-schedule-row").remove();
    };
    ScheduleTimeTable.prototype.deleteRow = function(row) {
        this.deleteRowByNeedle(row.$rowWrapper);
    };
    ScheduleTimeTable.prototype.deleteRowByNeedle = function($row) {
        this.$container.find($row).remove();
        this.$container.trigger("scheduler:remove-day");
    };
    ScheduleTimeTable.prototype.addRow = function($row) {
        if ($row) {
            this.$container.append($row);
            AGN.runAll($row);
            this.$container.trigger("scheduler:add-day", $row);
            $row.trigger("row:add-schedule", $row);
        }
    };
    ScheduleTimeTable.prototype.addEmptyDayRow = function() {
        this.addRow(DayRow.create());
    };
    ScheduleTimeTable.prototype.addEmptyPeriodRow = function() {
        this.addRow(PeriodRow.create());
    };
    ScheduleTimeTable.prototype.getAllDayRows = function() {
        var daysElements = this.$container.find("tr.l-time-schedule-row");
        return _.map(daysElements, function(elem) {
            return DayRow.get($(elem));
        });
    };
    ScheduleTimeTable.prototype.getAllPeriodRows = function() {
        var daysElements = this.$container.find("tr.l-time-schedule-row");
        return _.map(daysElements, function(elem) {
            return PeriodRow.get($(elem));
        });
    };
    ScheduleTimeTable.prototype.getSubmissionJson = function(type) {
        var scheduleJson = {};
        if (type == "day") {
            scheduleJson = _.map(this.getAllDayRows(), function(row) {
                return row.toJson();
            });
        } else if (type == "period") {
            scheduleJson = _.map(this.getAllPeriodRows(), function(row) {
                return row.toJson();
            });
        }
        return JSON.stringify(scheduleJson);
    };
    function ScheduleValidation(minutes) {
        var min = 100;
        if (minutes) {
            min = Number(minutes);
        }
        this.intervalPad = min;
    }
    ScheduleValidation.prototype.valid = function(times) {
        var interval = this.intervalPad;
        return times.every(ScheduleValidation.hasCorrectInterval, interval);
    };
    ScheduleValidation.hasCorrectInterval = function(time, index, times) {
        var interval = this;
        var isCorrect = true;
        times.splice(index, 1);
        times.forEach(function(element) {
            if (Math.abs(element - time) < interval) {
                isCorrect = false;
            }
        });
        return isCorrect;
    };
    AGN.Lib.ScheduleTimeTable = ScheduleTimeTable;
    AGN.Lib.ScheduleTimeTable.DayRow = DayRow, AGN.Lib.ScheduleTimeTable.PeriodRow = PeriodRow;
})();

(function() {
    var Field, CustomField, DoubleSelectField, ToggleVisField, PasswordField, ValueSplitField, FilterField, DateFilterField, DateSplitField, RequiredField, DateTimeField;
    Field = function($field) {
        this.el = $field;
    };
    Field.create = function($field) {
        var type, fieldType = $field.data("field");
        type = AGN.Opt.Fields[fieldType] || Field;
        return new type($field);
    };
    Field.prototype.valid = function() {
        return true;
    };
    Field.prototype.errors = function() {
        return [];
    };
    AGN.Lib.Field = Field;
    CustomField = function($field) {
        Field.apply(this, [ $field ]);
        var $target = this.el.find("[data-field-validator]");
        this.$target = $target;
        this.validatorName = $target.data("field-validator");
        var options = $target.data("validator-options");
        this.options = options ? AGN.Lib.Helpers.objFromString(options) || {} : {};
    };
    CustomField.prototype = Object.create(Field.prototype);
    CustomField.prototype.constructor = CustomField;
    CustomField.prototype.valid = function() {
        var validator = AGN.Lib.Validator.get(this.validatorName);
        if (validator && this.$target.exists()) {
            return validator.valid(this.$target, this.options);
        } else {
            console.debug("Validator `" + this.validatorName + "` doesn't exist");
            return true;
        }
    };
    CustomField.prototype.errors = function() {
        var validator = AGN.Lib.Validator.get(this.validatorName);
        if (validator && this.$target.exists()) {
            return validator.errors(this.$target, this.options);
        } else {
            console.debug("Validator `" + this.validatorName + "` doesn't exist");
            return [];
        }
    };
    AGN.Lib.CustomField = CustomField;
    AGN.Opt.Fields["validator"] = CustomField;
    DoubleSelectField = function($field) {
        Field.apply(this, [ $field ]);
        var self = this;
        this.$source = this.el.find(".js-double-select-trigger");
        this.$target = this.el.find(".js-double-select-target");
        this.$source.on("change", function() {
            self.$target.val([]);
            self.update();
        });
        AGN.Lib.DataProvider.get($field).done(function(options) {
            self.options = options;
            self.update();
        });
    };
    DoubleSelectField.prototype = Object.create(Field.prototype);
    DoubleSelectField.prototype.constructor = DoubleSelectField;
    DoubleSelectField.prototype.update = function() {
        var valueSource = this.$source.find("option:selected").val(), valueTarget = this.$target.find("option:selected").val(), template = '{{ _.forEach(opts, function(name, value) { }}<option value="{{- value }}" {{- ( value == valueSelected ) ? "selected" : "" }}>{{- name }}</option>{{ }); }}';
        template = _.template(template)({
            opts: this.options[valueSource],
            valueSelected: valueTarget
        });
        this.$target.html(template);
        AGN.runAll(this.el);
    };
    AGN.Lib.DoubleSelectField = DoubleSelectField;
    AGN.Opt.Fields["double-select"] = DoubleSelectField;
    ToggleVisField = function($field) {
        Field.apply(this, [ $field ]);
        var self = this;
        this.$source = this.el.find("[data-field-vis]");
        this.$source.on("change", function() {
            self.update();
        });
        self.update();
    };
    ToggleVisField.prototype = Object.create(Field.prototype);
    ToggleVisField.prototype.constructor = ToggleVisField;
    ToggleVisField.prototype._updateSelects = function() {
        var self = this;
        _.each(this.$source.filter("select"), function(el) {
            self._toggleFields($(el).find(":selected"));
        });
    };
    ToggleVisField.prototype._updateDefaults = function() {
        var self = this;
        _.each(this.el.find("[data-field-vis-default]"), function(el) {
            self._toggleFields($(el));
        });
    };
    ToggleVisField.prototype._updateCheckboxes = function() {
        var self = this;
        _.each(this.$source.filter(":checked"), function(el) {
            self._toggleFields($(el));
        });
    };
    ToggleVisField.prototype._toggleFields = function($el) {
        var fieldsToHide, fieldsToShow;
        if ($el.is(":disabled") && !$el.is("[data-field-vis-nondisabled]")) {
            return;
        }
        fieldsToHide = $el.data("field-vis-hide");
        fieldsToShow = $el.data("field-vis-show");
        _.each(this.el.find(fieldsToHide), function(el) {
            $el = $(el);
            $el.all(":input").each(function() {
                var $input = $(this);
                if (!$input.prop("disabled")) {
                    $input.data("field-disabled", true);
                    $input.prop("disabled", true);
                }
            });
            $el.hide();
            if ($el.data("select2")) {
                $el.select2("container").hide();
                $el.select2("enable", false);
            }
            if ($el.is("option")) {
                $el.prop("disabled", true);
                AGN.Lib.CoreInitializer.run("select", $el.parents("select"));
            }
        });
        _.each(this.el.find(fieldsToShow), function(el) {
            $el = $(el);
            $el.all(":input").each(function() {
                var $input = $(this);
                if ($input.data("field-disabled")) {
                    $input.prop("disabled", false);
                    $input.removeData("field-disabled");
                }
            });
            $el.show();
            if ($el.data("select2")) {
                $el.select2("container").show();
                $el.select2("enable", true);
            }
            if ($el.is("option")) {
                $el.prop("disabled", false);
                AGN.Lib.CoreInitializer.run("select", $el.parents("select"));
            }
        });
    };
    ToggleVisField.prototype.update = function() {
        this._updateDefaults();
        this._updateSelects();
        this._updateCheckboxes();
    };
    AGN.Lib.ToggleVisField = ToggleVisField;
    AGN.Opt.Fields["toggle-vis"] = ToggleVisField;
    RequiredField = function($field) {
        Field.apply(this, [ $field ]);
        this.$target = this.el.find("[data-field-required]");
    };
    RequiredField.prototype = Object.create(Field.prototype);
    RequiredField.prototype.constructor = RequiredField;
    RequiredField.prototype.valid = function() {
        if (this.$target.exists()) {
            return $.trim(this.$target.val());
        } else {
            return true;
        }
    };
    RequiredField.prototype.errors = function() {
        var errors = [];
        if (this.valid()) return errors;
        errors.push({
            field: this.$target,
            msg: t("fields.required.errors.missing")
        });
        return errors;
    };
    AGN.Lib.RequiredField = RequiredField;
    AGN.Opt.Fields["required"] = RequiredField;
    PasswordField = function($field) {
        Field.apply(this, [ $field ]);
        var self = this;
        this.$strength = this.el.find(".js-password-strength");
        this.$strengthIndicator = this.el.find(".js-password-strength-indicator");
        this.$match = this.el.find(".js-password-match");
        this.$matchIndicator = this.el.find(".js-password-match-indicator");
        this.$strength.on("keyup", function() {
            self.updateStrength();
            self.updateMatch();
        });
        this.$match.on("keyup", function() {
            self.updateMatch();
        });
    };
    PasswordField.prototype = Object.create(Field.prototype);
    PasswordField.prototype.constructor = PasswordField;
    PasswordField.prototype.match = function() {
        return this.$strength.val() == this.$match.val();
    };
    PasswordField.prototype.safe = function() {
        return this._getSecurityIssues().length === 0;
    };
    PasswordField.prototype._getSecurityIssues = function() {
        var errors = [];
        var self = this, pass = this.$strength.val();
        if (pass.length == 0) return errors;
        var ruleName = this.$strength.attr("data-rule");
        var policy = AGN.Lib.PasswordPolicies.find_password_policy(ruleName);
        var errorKeys = policy(pass);
        if (errorKeys != null && errorKeys.length > 0) {
            errors.push(t("fields.password.errors.unsafe"));
            for (var i = 0; i < errorKeys.length; i++) {
                errors.push(t(errorKeys[i]));
            }
        }
        return errors;
    };
    PasswordField._getRule = function(ruleName) {
        var minLength = 8;
        var checks = [ "[a-z]", "[A-Z]", "[0-9]", "[^a-zA-Z0-9]" ];
        switch (ruleName) {
          case "LENGTH_8_MIXED":
            minLength = 8;
            checks = [ "[a-z]", "[A-Z]", "[0-9]", "[^a-zA-Z0-9]" ];
            break;

          case "LENGTH_12_SIMPLE":
            minLength = 12;
            checks = [ "." ];
            break;

          case "WEBSERVICE":
            minLength = 32;
            checks = [ "." ];
            break;

          default:
            console.log("Don't know password policy '" + name + "'");
            return false;
        }
        return {
            minLength: minLength,
            checks: checks
        };
    };
    PasswordField.prototype.passesCheck = function(pass, check) {
        if (pass.match(check)) {
            return true;
        }
        return false;
    };
    PasswordField.prototype.valid = function() {
        if (this.$match.length == 0) return true;
        return this.match() && this.safe();
    };
    PasswordField.prototype.errors = function() {
        var self = this, errors = [];
        if (this.valid()) return errors;
        if (!this.match()) {
            errors.push({
                field: this.$match,
                msg: t("fields.password.errors.notMatching")
            });
        }
        var securityErrors = this._getSecurityIssues();
        if (securityErrors.length > 0) {
            securityErrors.forEach(function(el) {
                errors.push({
                    field: self.$strength,
                    msg: el
                });
            });
        }
        return errors;
    };
    PasswordField.prototype.resetStrength = function() {
        var form = AGN.Lib.Form.get(this.el);
        form.cleanErrors(this.$strengthIndicator.parents(".form-group"));
        this.$strengthIndicator.addClass("hidden");
        this.$strengthIndicator.removeClass("state-alert");
        this.$strengthIndicator.removeClass("state-success");
        this.$strengthIndicator.html("");
    };
    PasswordField.prototype.resetMatch = function() {
        var form = AGN.Lib.Form.get(this.el);
        form.cleanErrors(this.$matchIndicator.parents(".form-group"));
        this.$matchIndicator.addClass("hidden");
        this.$matchIndicator.removeClass("state-success");
        this.$matchIndicator.removeClass("state-alert");
        this.$matchIndicator.html("");
    };
    PasswordField.prototype.updateStrength = function() {
        this.resetStrength();
        if (this.$strength.val().length == 0) {
            return;
        }
        this.$strengthIndicator.removeClass("hidden");
        if (this.safe()) {
            this.$strengthIndicator.addClass("state-success");
            this.$strengthIndicator.html(t("fields.password.successHtml", t("fields.password.safe")));
        } else {
            this.$strengthIndicator.addClass("state-alert");
            this.$strengthIndicator.html(t("fields.password.unsuccessHtml", t("fields.password.unsafe")));
        }
    };
    PasswordField.prototype.updateMatch = function() {
        this.resetMatch();
        if (this.$match.val().length == 0) {
            return;
        }
        this.$matchIndicator.removeClass("hidden");
        if (this.match()) {
            this.$matchIndicator.addClass("state-success");
            this.$matchIndicator.html(t("fields.password.successHtml", t("fields.password.matches")));
        } else {
            this.$matchIndicator.addClass("state-alert");
            this.$matchIndicator.html(t("fields.password.unsuccessHtml", t("fields.password.matchesNot")));
        }
    };
    AGN.Lib.PasswordField = PasswordField;
    AGN.Opt.Fields["password"] = PasswordField;
    ValueSplitField = function($field) {
        Field.apply(this, [ $field ]);
        this.$source = this.el.find("[data-field-split]");
        this.targets = this.$source.data("field-split").split(/,\s?/);
        this.rule = new RegExp(this.$source.data("field-split-rule"));
    };
    ValueSplitField.prototype = Object.create(Field.prototype);
    ValueSplitField.prototype.constructor = ValueSplitField;
    ValueSplitField.prototype.valid = function() {
        var values, form = AGN.Lib.Form.get(this.el);
        values = this.$source.val().split(this.rule);
        _.each(this.targets, function(target, index) {
            form.setValueOnce(target, values[index]);
        });
        return true;
    };
    AGN.Lib.ValueSplitField = ValueSplitField;
    AGN.Opt.Fields["split"] = ValueSplitField;
    FilterField = function($field) {
        var self = this;
        Field.apply(this, [ $field ]);
        this.$filters = this.el.find("[data-field-filter]");
        this.$filters.on("change", function() {
            self.update();
        });
        self.position();
        self.update();
    };
    FilterField.prototype = Object.create(Field.prototype);
    FilterField.prototype.constructor = FilterField;
    FilterField.prototype.position = function() {
        var $target;
        $target = $(this.el.data("filter-target"));
        this.el.detach();
        this.el.appendTo($target);
        $target.parents("table").hide();
        $target.parents("table").show();
    };
    FilterField.prototype.isEnabled = function() {
        return this.$filters.get().some(function(e) {
            var $e = $(e);
            if ($e.is("input")) {
                var type = $e.attr("type");
                if (type == "text" || type == "number" || type == "password") {
                    return !!$e.val();
                }
            }
            return !!$e.serialize();
        });
    };
    FilterField.prototype.isDisabled = function() {
        return !this.isEnabled();
    };
    FilterField.prototype.update = function() {
        if (this.isEnabled()) {
            this.el.addClass("filter-active");
        } else {
            this.el.removeClass("filter-active");
        }
    };
    AGN.Lib.FilterField = FilterField;
    AGN.Opt.Fields["filter"] = FilterField;
    DateFilterField = function($field) {
        var self = this;
        Field.apply(this, [ $field ]);
        this.$filterMin = this.el.find("[data-filter-date-min]");
        this.$filterMax = this.el.find("[data-filter-date-max]");
        this.$filters = this.el.find("[data-filter-date-min],[data-filter-date-max]");
        this.$filterMin.on("change", function() {
            var apiMax = self.$filterMax.data("pickadate");
            apiMax.set("min", self.$filterMin.val());
        });
        this.$filterMax.on("change", function() {
            var apiMin = self.$filterMin.data("pickadate");
            apiMin.set("max", self.$filterMax.val());
        });
        this.$filters.on("change", function() {
            self.update();
        });
        self.position();
        self.update();
    };
    DateFilterField.prototype = Object.create(FilterField.prototype);
    DateFilterField.prototype.constructor = DateFilterField;
    DateFilterField.prototype.isEnabled = function() {
        return _.some(this.$filters, function(filter) {
            return $(filter).val() != "";
        });
    };
    AGN.Lib.DateFilterField = DateFilterField;
    AGN.Opt.Fields["date-filter"] = DateFilterField;
    DateSplitField = function($field) {
        var self = this;
        Field.apply(this, [ $field ]);
        this.$source = this.el.find("[data-field-date-split]");
        this.$source.on("change", function() {
            self.update();
        });
    };
    DateSplitField.prototype = Object.create(Field.prototype);
    DateSplitField.prototype.constructor = DateSplitField;
    DateSplitField.prototype.update = function() {
        var date = null;
        var timestamp = this.$source.val();
        if (timestamp) {
            date = new Date(parseInt(timestamp));
        }
        var $targets = this.el.find("[data-date-split-target]");
        $targets.each(function() {
            var $target = $(this);
            var param = $target.attr("data-date-split-target");
            if (date && param) {
                switch (param.toUpperCase()) {
                  case "MILLISECONDS":
                    $target.val(date.getMilliseconds());
                    break;

                  case "SECONDS":
                    $target.val(date.getSeconds());
                    break;

                  case "MINUTES":
                    $target.val(date.getMinutes());
                    break;

                  case "HOURS":
                    $target.val(date.getHours());
                    break;

                  case "DAY":
                    $target.val(date.getDate());
                    break;

                  case "MONTH":
                    $target.val(date.getMonth() + 1);
                    break;

                  case "YEAR":
                    $target.val(date.getFullYear());
                    break;

                  default:
                    $target.val(date.toJSON());
                }
            } else {
                $target.val("");
            }
        });
    };
    AGN.Lib.DateSplitField = DateSplitField;
    AGN.Opt.Fields["date-split"] = DateSplitField;
    DateTimeField = function($field) {
        Field.apply(this, [ $field ]);
        var $el = $(this.el);
        var propertyName = $el.data("property");
        var options = _.extend({}, AGN.Lib.Helpers.objFromString($el.data("field-options")));
        var value = options.value || options.defaultValue || "";
        var dateFormat = options.dateFormat || "dd.mm.yyyy";
        prepareDatetimeInput($el, propertyName, value, dateFormat);
        $el.on("change", function() {
            setDateTimeFieldValue(propertyName, dateFormat);
        });
    };
    DateTimeField.prototype = Object.create(Field.prototype);
    DateTimeField.prototype.constructor = DateTimeField;
    AGN.Lib.DateTimeField = DateTimeField;
    AGN.Opt.Fields["datetime"] = DateTimeField;
    function setDateTimeFieldValue(property, dateFormat) {
        var escapedProperty = property.replace(/([:.\[\],=@])/g, "\\$1");
        var $date = $("#" + escapedProperty + "_date");
        var $time = $("#" + escapedProperty + "_time");
        $('[name="' + property + '"]').val(prepareDateTimeValue($date, $time, dateFormat));
    }
    function prepareDateTimeValue($date, $time, dateFormat) {
        var time = $time ? $time.val() : "";
        time = time ? time.replaceAll("_", "0") : "00:00";
        return $date.val() ? formatDateTime($date.pickadate("picker"), time, dateFormat) : "";
    }
    function formatDateTime(date, time, dateFormat) {
        return date.get("select", dateFormat) + (isValidTimeField(time) ? " " + time : "");
    }
    function isValidTimeField(time) {
        return /^(\d{2}):(\d{2})$/.test(time);
    }
    function getDateFromFieldValue(value) {
        if (value) {
            return value.split(" ")[0];
        }
        return "";
    }
    function getTimeFromFieldValue(value) {
        if (value) {
            var datetime = value.split(" ");
            if (datetime.length == 2) {
                return datetime[1];
            }
        }
        return "";
    }
    function prepareDatetimeInput($el, propertyName, value, dateFormat) {
        var input = document.createElement("input");
        input.type = "hidden";
        input.name = propertyName;
        input.value = value;
        $el.append(_.template(AGN.Opt.Templates["datetime-picker"])({
            date: getDateFromFieldValue(value),
            time: getTimeFromFieldValue(value),
            property: propertyName,
            dateFormat: dateFormat
        }));
        $el.append(input);
        AGN.runAll($el);
    }
})();

(function() {
    var defaultRowTemplate = _.template('<div class="form-group email-list-manager-row" data-action="change-trigger">' + '        <div class="col-sm-12">' + '            <div class="input-group">' + '                <div class="input-group-controls">' + '                    <input type="text" value="{{= value}}" class="form-control" size="42" maxlength="99"/>' + "                </div>" + '                <div class="input-group-btn">' + '                    <button type="button" class="btn btn-regular btn-primary email-list-manager-add-btn" data-action="create-email">' + '                        <i class="icon icon-plus"></i>' + "                    </button>" + "                </div>" + "            </div>" + "        </div>" + "    </div>");
    var deleteBtnTemplate = _.template('<button type="button" class="btn btn-regular btn-alert email-list-manager-delete-btn" data-action="delete-email">' + '        <i class="icon icon-trash-o"></i>' + "    </button>");
    function EmailsListManager(scope, data, options) {
        this.scope = scope;
        this.data = data;
        this.options = $.extend({
            rowTemplate: defaultRowTemplate,
            rowSelector: ".email-list-manager-row",
            addBtnSelector: ".email-list-manager-add-btn",
            deleteBtnSelector: ".email-list-manager-delete-btn",
            rowDataMapper: function(data) {
                return {
                    value: data
                };
            }
        }, options);
        var self = this;
        _.each(self.data, function(rowData) {
            addFieldRow(self.scope, rowData, null, self.options);
        });
    }
    EmailsListManager.initialize = function(scope, data, options) {
        return new EmailsListManager(scope, data, options);
    };
    EmailsListManager.prototype.createRowAfter = function(target) {
        var self = this;
        addFieldRow(self.scope, "", $(target), self.options);
    };
    EmailsListManager.prototype.deleteRow = function(target) {
        $(target).closest(this.options.rowSelector).remove();
        updateRemoveButtons(this.scope, this.options);
    };
    EmailsListManager.prototype.getJsonData = function() {
        var values = [];
        _.each(this.scope.find(this.options.rowSelector + " input"), function(rowInput) {
            var value = rowInput.value;
            if (value.trim() !== "") {
                values.push(value);
            }
        });
        return values;
    };
    function updateRemoveButtons(scope, options) {
        var $rows = scope.find(options.rowSelector);
        if ($rows.length === 1) {
            var $deleteButtons = $rows.find(options.deleteBtnSelector);
            $deleteButtons.remove();
        } else {
            _.each($rows, function(row) {
                var $row = $(row);
                var $deleteBtn = $row.find(options.deleteBtnSelector);
                if (!$deleteBtn.exists()) {
                    $row.find(".input-group-btn").append(deleteBtnTemplate({}));
                }
            });
        }
    }
    function addFieldRow(scope, rowData, $target, options) {
        var content = options.rowTemplate(options.rowDataMapper(rowData));
        if ($target && $target.exists()) {
            $target.closest(options.rowSelector).after(content);
        } else {
            scope.append(content);
        }
        updateRemoveButtons(scope, options);
    }
    AGN.Lib.EmailsListManager = EmailsListManager;
})();

(function() {
    var Form, Field = AGN.Lib.Field, CSRF = AGN.Lib.CSRF, ControlsToDisable;
    ControlsToDisable = function(group) {
        this.group = group;
        this.$controls = $();
    };
    ControlsToDisable.prototype._collect = function(group) {
        var $all = $("[data-controls-group]");
        if (group === "*") {
            return $all;
        }
        if (group) {
            return $all.filter(function() {
                return group === $(this).attr("data-controls-group");
            });
        } else {
            return $();
        }
    };
    ControlsToDisable.prototype.collect = function() {
        if (this.group) {
            this.$controls = this._collect(this.group).filter(function() {
                var $e = $(this);
                return !$e.prop("disabled") && !$e.hasClass("disabled");
            });
        }
    };
    ControlsToDisable.prototype.setDisabled = function(isDisabled) {
        if (isDisabled === false) {
            this.$controls.removeClass("disabled");
            this.$controls.prop("disabled", false);
        } else {
            this.$controls.addClass("disabled");
            this.$controls.prop("disabled", true);
        }
    };
    Form = function($form) {
        this.$form = $form;
        this.form = $form[0];
        this._abort = null;
        this._data = {};
        this._dataNextRequest = {};
        this.fields = [];
        this.validatorName = null;
        this.validatorOptions = null;
        this.dirtyChecking = $form.is("[data-form-dirty-checking]");
        this.editable = !$form.is("[data-editable]") || !!$form.data("editable");
        this.url = $form.attr("action");
        this.urlNextRequest = null;
        this.method = $form.attr("method");
        this.isMultipart = "multipart/form-data" == ($form.attr("enctype") || "").toLowerCase();
        this.isCustomLoader = $form.is("[data-custom-loader]");
        this.controlsToDisable = new ControlsToDisable($form.attr("data-disable-controls"));
        if ($form.is("[data-custom-loader]")) {
            this.isCustomLoader = $form.attr("data-custom-loader") !== "false";
        } else {
            this.isCustomLoader = false;
        }
        this.initFields();
        this.initValidator();
        this.handleMessages($("body"), true);
        if (this.dirtyChecking) {
            enableDirtyChecking($form);
        }
        if (!this.editable) {
            $form.find(":input, button").prop("disabled", true);
        }
    };
    function enableDirtyChecking($form) {
        $form.dirty({
            preventLeaving: true,
            leavingMessage: t("grid.layout.leaveQuestion")
        });
        window.onbeforeunload = function() {
            if (!$form.dirty("isDirty") === true) {
                AGN.Lib.Loader.show();
            }
        };
    }
    Form.get = function($needle) {
        var $form, type, formType, formObj;
        $form = Form.getWrapper($needle);
        formObj = $form.data("_form");
        if (!formObj) {
            formType = $form.data("form");
            type = AGN.Opt.Forms[formType] || AGN.Lib.Form;
            formObj = new type($form);
            $form.data("_form", formObj);
        }
        return formObj;
    };
    Form.getWrapper = function($needle) {
        var $form;
        $form = $($needle.data("form-target"));
        if ($form.length == 0) {
            $form = $needle.closest("form");
        }
        return $form;
    };
    Form.prototype.valid = function(options) {
        var validationEvent = $.Event("validation");
        options = _.merge({}, this.validatorOptions, options);
        this.$form.trigger(validationEvent, options);
        if (validationEvent.isDefaultPrevented()) {
            return false;
        }
        var fieldsValid = _.every(this.fields, function(field) {
            return field.valid();
        });
        if (this.validatorName) {
            var validator = AGN.Lib.Validator.get(this.validatorName);
            if (validator) {
                return validator.valid(this, options, fieldsValid);
            }
        }
        return fieldsValid;
    };
    Form.prototype.validate = function(options) {
        if (this.valid(options)) {
            return true;
        } else {
            this.handleErrors();
            return false;
        }
    };
    Form.prototype.get$ = function() {
        return this.$form;
    };
    Form.prototype.getAction = function() {
        if (this.urlNextRequest) {
            var value = this.urlNextRequest;
            this.urlNextRequest = null;
            return value;
        }
        return this.url;
    };
    Form.prototype.setActionOnce = function(url) {
        this.urlNextRequest = url;
    };
    Form.prototype.errors = function() {
        var errors = [];
        _.each(this.fields, function(field) {
            errors = errors.concat(field.errors());
        });
        if (this.validatorName) {
            var validator = AGN.Lib.Validator.get(this.validatorName);
            if (validator) {
                errors = errors.concat(validator.errors(this, this.validatorOptions));
            }
        }
        return errors;
    };
    Form.prototype.setValue = function(field, value) {
        var node = this.form[field];
        if (typeof node === "object") {
            $(node).val([ value ]);
            $(node).trigger("change");
        } else {
            if (typeof value === "undefined") {
                delete this._data[field];
            } else {
                this._data[field] = value;
            }
        }
    };
    Form.prototype.setValueOnce = function(field, value) {
        if (typeof value === "undefined") {
            delete this._dataNextRequest[field];
        } else {
            this._dataNextRequest[field] = value;
        }
    };
    Form.prototype.getValue = function(field) {
        var node = this.form[field];
        if (typeof node === "object") {
            return node.value;
        } else {
            return this._data[field];
        }
    };
    Form.prototype.data = function() {
        if (this.isMultipart) {
            var formData = new FormData();
            var data = this.$form.serializeFormDataObject();
            $.each(this._data, function(k, v) {
                if (!data.hasOwnProperty(k)) {
                    data[k] = v;
                }
            });
            $.each(this._dataNextRequest, function(k, v) {
                data[k] = v;
            });
            $.each(data, function(k, v) {
                if ($.isArray(v)) {
                    $.each(v, function(index, value) {
                        formData.append(k, value);
                    });
                } else {
                    formData.append(k, v);
                }
            });
            return formData;
        } else {
            return _.merge({}, this._data, this.$form.serializeObject(), this._dataNextRequest);
        }
    };
    Form.prototype.params = function() {
        return $.param(this.data(), true);
    };
    Form.prototype.jqxhr = function() {
        var self = this, xhr = $.ajaxSettings.xhr(), jqxhr, deferred = $.Deferred();
        this.$form.trigger("form:submit");
        var parameters = {
            url: this.getAction(),
            method: this.method,
            loader: this.loader(),
            xhr: function() {
                return xhr;
            }
        };
        if (this.isMultipart) {
            parameters.data = this.data();
            parameters.enctype = "multipart/form-data";
            parameters.processData = false;
            parameters.contentType = false;
        } else {
            parameters.data = this.params();
        }
        if (this.isCustomLoader) {
            var onProgress = function(e) {
                var progress = true;
                if (e.lengthComputable) {
                    progress = (e.loaded / e.total * 100).toFixed(1);
                }
                self.$form.trigger("form:progress", {
                    loaded: e.loaded,
                    total: e.total,
                    progress: progress
                });
            };
            if ("upload" in xhr) {
                parameters.xhr = function() {
                    xhr.upload.onprogress = onProgress;
                    return xhr;
                };
            } else {
                parameters.xhrFields = {
                    onprogress: onProgress
                };
            }
        }
        if (typeof xhr.abort === "function") {
            this._abort = function() {
                xhr.abort();
            };
        }
        jqxhr = $.ajax(parameters);
        this._dataNextRequest = {};
        this.setLoaderShown(true);
        deferred.always(function() {
            self.setLoaderShown(false);
        });
        jqxhr.done(function(resp) {
            var $resp = $(resp), $pollingForm, pollingFormObj, pollingFormJqxhr;
            $pollingForm = $resp.filter('[data-form="polling"]').add($resp.find('[data-form="polling"]'));
            if ($pollingForm.length == 1) {
                pollingFormObj = Form.get($pollingForm);
                pollingFormJqxhr = pollingFormObj.jqhxr();
                pollingFormJqxhr.done(function() {
                    deferred.resolve.apply(this, arguments);
                    var $body = $("body");
                    var $resp = $("<div></div>");
                    $resp.html(resp);
                    $resp.find('script[data-message][type="text/html"]').appendTo($body);
                    $resp.find('script[data-message][type="text/javascript"]').each(function() {
                        try {
                            eval.call(window, $(this).html());
                        } catch (e) {}
                    });
                    $resp.remove();
                });
                pollingFormJqxhr.fail(function() {
                    deferred.reject.apply(this, arguments);
                });
            } else {
                deferred.resolve(resp);
            }
        });
        jqxhr.fail(function() {
            deferred.reject.apply(this, arguments);
        });
        return deferred.promise();
    };
    Form.prototype._submit = function() {
        var jqxhr, self = this;
        this.setLoaderShown(true);
        jqxhr = this.jqxhr();
        jqxhr.done(function(resp) {
            self.setLoaderShown(false);
            self.updateHtml(resp);
            self.$form.trigger("submitted", resp);
            if (self.dirtyChecking) {
                changeDirtyState(self.$form);
            }
        });
        return jqxhr;
    };
    function changeDirtyState($form) {
        const formRewritten = $("body").has($form).length === 0;
        if (formRewritten) {
            $form.dirty("destroy");
        } else {
            $form.dirty("setAsClean");
        }
    }
    Form.prototype._submitStatic = function() {
        var data = this.data(), $staticForm;
        if (CSRF.isProtectionEnabled()) {
            data[CSRF.getParameterName()] = CSRF.readActualToken();
        }
        $staticForm = $('<form method="' + this.method + '" action="' + this.getAction() + '"></form>');
        _.each(data, function(value, param) {
            if (_.isArray(value)) {
                var $select = $('<select multiple name="' + param + '"></select>');
                _.each(value, function(option) {
                    var $option = $('<option selected="selected"></option>');
                    $option.val(option);
                    $option.appendTo($select);
                });
                $select.appendTo($staticForm);
            } else {
                var $input = $('<input type="hidden" name="' + param + '"/>');
                $input.val(value);
                $input.appendTo($staticForm);
            }
        });
        $staticForm.appendTo($("body"));
        $staticForm.submit();
        $staticForm.remove();
        this._dataNextRequest = {};
    };
    Form.prototype._submitAction = function(actionId) {
        this.setValue("previousAction", this.getValue("actionList"));
        this.setValueOnce("action", actionId);
        return this.submit();
    };
    Form.prototype._submitEvent = function() {
        var submissionEvent = $.Event("submission");
        this.$form.trigger(submissionEvent);
        if (!submissionEvent.isDefaultPrevented()) {
            this.$form.trigger("submitted");
            this._dataNextRequest = {};
        }
    };
    Form.prototype._submitConfirm = function(actionId) {
        this.setValue("previousAction", this.getValue("actionList"));
        this.setValueOnce("action", actionId);
        var jqxhr = this.jqxhr();
        var self = this;
        jqxhr.done(function(resp) {
            self.$form.trigger("submitted", resp);
        });
        return jqxhr;
    };
    Form.prototype.submit = function(type) {
        var actionId = 0;
        var validationOptions = {};
        if ((type == "confirm" || type == "action") && (typeof arguments[1] === "number" || typeof arguments[1] === "string")) {
            actionId = arguments[1];
            validationOptions = arguments[2];
        } else {
            validationOptions = arguments[1];
        }
        if (this.valid(validationOptions)) {
            this.cleanErrors();
        } else {
            this.handleErrors();
            return false;
        }
        switch (type) {
          case "static":
            return this._submitStatic();

          case "confirm":
            return this._submitConfirm(actionId);

          case "action":
            return this._submitAction(actionId);

          case "event":
            return this._submitEvent();

          default:
            return this._submit();
        }
    };
    Form.prototype.revertAction = function() {};
    Form.prototype.reset = function() {
        this.$form.trigger("reset");
    };
    Form.prototype.abort = function() {
        this.$form.trigger("form:abort");
        if (this._abort) {
            this._abort();
            this._abort = null;
        }
    };
    Form.prototype.bulkUpdate = function(group, value) {
        if (group) {
            this.$form.find('[name^="' + group + '"]').prop("checked", value);
        } else {
            this.$form.find(".js-bulk-ids").prop("checked", value);
        }
    };
    Form.prototype.handleMessages = function($resp, formFieldsOnly) {
        const self = this;
        if (!($resp instanceof $)) {
            $resp = $($resp);
        }
        $resp.all('script[data-message][type="text/html"]').each(function() {
            const $this = $(this);
            const message = $this.text();
            const fieldName = $this.data("message");
            if (message && fieldName) {
                self.showFieldError(fieldName, message, false);
            }
        });
        if (formFieldsOnly === true) {
            return;
        }
        const $messages = $resp.filter("script[data-message]").add($resp.find("script[data-message]"));
        _.each($messages, function(msg) {
            $("body").append(msg);
        });
    };
    Form.prototype.initFields = function($scope) {
        var self = this;
        if (!$scope) {
            $scope = this.$form;
        }
        self.fields.length = 0;
        _.each($scope.find("[data-field]"), function(field) {
            self.fields.push(Field.create($(field)));
        });
    };
    Form.prototype.initValidator = function() {
        this.validatorName = this.$form.data("validator");
        var options = this.$form.data("validator-options");
        this.validatorOptions = options ? AGN.Lib.Helpers.objFromString(options) : null;
    };
    Form.prototype.updateHtml = function(resp) {
        var $newForm, $resp = $(resp);
        if (this.$form.attr("id")) {
            $newForm = $(resp).filter("#" + this.$form.attr("id")).add($resp.find("#" + this.$form.attr("id")));
        } else if (this.$form.attr("name")) {
            $newForm = $(resp).filter('[name="' + this.$form.attr("name") + '"]').add($resp.find('[name="' + this.$form.attr("name") + '"]'));
        } else {
            $newForm = $(resp).filter("form").add($resp.find("form"));
        }
        this.$form.html($newForm.html());
        this.handleMessages(resp);
        this.initFields();
        this.initValidator();
        AGN.Lib.Controller.init(this.$form);
        AGN.runAll(this.$form);
    };
    Form.prototype.loader = function() {
        var self = this;
        return {
            show: function() {
                self.controlsToDisable.collect();
                self.controlsToDisable.setDisabled(true);
                self.setLoaderShown(true);
            },
            hide: function() {
                self.controlsToDisable.setDisabled(false);
                self.setLoaderShown(false);
            }
        };
    };
    Form.prototype.setLoaderShown = function(shown) {
        if (this.isCustomLoader) {
            if (shown) {
                this.$form.trigger("form:loadershow");
            } else {
                this.$form.trigger("form:loaderhide");
            }
        } else {
            if (shown) {
                AGN.Lib.Loader.show();
            } else {
                AGN.Lib.Loader.hide();
            }
        }
    };
    Form.prototype.cleanErrors = function($group) {
        if (!$group) {
            $group = this.$form.find(".js-form-error");
        }
        _.each($group, function(group) {
            var $group = $(group);
            $group.removeClass("has-alert has-feedback js-form-error");
            $group.find(".js-form-error-ind").remove();
            $group.find(".js-form-error-msg").remove();
        });
    };
    function appendFeedbackMessage($field, message) {
        var anchor = $field;
        var editor = $field.data("_editor");
        var emojioneArea = $field.data("emojioneArea");
        var showIcon = true;
        if (editor) {
            editor = editor.editor;
            if (editor.container) {
                showIcon = false;
                anchor = $(editor.container);
            }
        } else if (emojioneArea) {
            if (emojioneArea.editor) {
                showIcon = false;
                anchor = emojioneArea.editor.parent();
            }
        } else {
            if (anchor.is("select")) {
                showIcon = false;
                if (anchor.is(".input-group .input-group-controls .js-select")) {
                    anchor = anchor.closest(".input-group");
                }
            }
        }
        if (showIcon) {
            const $existingIcon = anchor.next("span[class*='icon-state-']");
            if ($existingIcon) {
                $existingIcon.hide();
            }
            anchor.after('<span class="icon icon-state-alert form-control-feedback js-form-error-ind"></span>');
        }
        anchor.parent().append('<div class="form-control-feedback-message js-form-error-msg">' + message + "</div>");
    }
    Form.prototype.handleErrors = function() {
        var errorPos = [];
        this.cleanErrors();
        var errors = this.errors().filter(function(error) {
            return error.field && error.field.length > 0;
        });
        _.each(errors, function(error) {
            var $field = error.field;
            markFieldInRed($field);
            appendFeedbackMessage($field, error.msg);
        });
        _.each(this.errors(), function(error) {
            var $field = error.field;
            if ($field.data("select2")) {
                errorPos.push($field.parent().find(".select2-container").offset().top);
            } else if ($field.data("_editor") && $field.data("_editor").editor) {
                var editor = $field.data("_editor").editor;
                errorPos.push($(editor.container).offset().top);
            } else {
                errorPos.push($field.offset().top);
            }
        });
        var containerScroll = false;
        var $view = this.$form.closest(".modal");
        if (!$view.exists()) {
            $view = $('.tile-content[data-sizing="scroll"]');
            if ($view.exists()) {
                containerScroll = true;
            }
        }
        if (!$view.exists()) {
            $view = $(document);
        }
        if ($view.find(".popover.support-popover").exists()) {
            return;
        }
        var formPosition = this.$form.offset().top;
        var scrollTopPos;
        if (containerScroll) {
            scrollTopPos = _.sortBy(errorPos)[0] + $view.scrollTop() - $view.offset().top - 25;
        } else {
            scrollTopPos = _.sortBy(errorPos)[0] - formPosition - 25;
        }
        $view.scrollTop(scrollTopPos);
    };
    Form.prototype.cleanFieldError = function(field) {
        if (this.form[field]) {
            this.cleanFieldError$($(this.form[field]));
        }
    };
    Form.prototype.cleanFieldError$ = function($field) {
        var $group = $field.closest(".js-form-error");
        $group.removeClass("has-alert has-feedback js-form-error");
        $group.find(".js-form-error-ind").remove();
        $group.find(".js-form-error-msg").remove();
    };
    Form.prototype.showFieldError = function(field, message, disableScrolling) {
        if (this.form[field]) {
            this.showFieldError$($(this.form[field]), message, disableScrolling);
        }
    };
    Form.prototype.showFieldError$ = function($field, message, disableScrolling) {
        var $group = $field.parents(".form-group");
        $group.addClass("has-alert has-feedback js-form-error");
        $group.find(".js-form-error-ind").remove();
        $group.find(".js-form-error-msg").remove();
        appendFeedbackMessage($field, message);
        if (disableScrolling !== true) {
            var $view = this.$form.closest("[data-sizing=scroll], .modal").first();
            if ($view.exists()) {
                var $target = $(".has-alert").first();
                $view.animate({
                    scrollTop: $target.offset().top - $view.offset().top + $view.scrollTop()
                });
            } else {
                $view = $(document);
                $view.scrollTop($field.offset().top - 125);
            }
        }
    };
    AGN.Lib.Form = Form;
    function markFieldInRed($field) {
        var $td = $field.closest("td");
        if ($td.length && $td.parents(".table-form").length) {
            $td.addClass("has-alert js-form-error");
        } else {
            $field.parents(".form-group").addClass("has-alert has-feedback js-form-error");
        }
    }
})();

(function() {
    var GridView;
    GridView = function($target) {
        this.$el = $target;
    };
    GridView.prototype.update = function(config) {
        this.config = config;
        this.draw();
    };
    GridView.prototype.template = function() {
        var config = this.config;
        return _.template('<div class="grid-stage center-block" style="width: {{= viewWidth}} px; height: {{= viewHeight }}px;">' + '<svg class="grid-view center-block" viewBox="0 0 {{= viewWidth }} {{= viewHeight }}" style="width: {{= viewWidth }}px; height: {{= viewHeight }}px">' + '<g class="grid-columns"></g>' + "</svg>" + "</div>")({
            viewWidth: config.templateWidth,
            viewHeight: 100
        });
    };
    GridView.prototype.data = function() {
        var d3data = [], config = this.config;
        _.times(config.columnNum, function(col) {
            d3data.push({
                type: "gutter",
                width: config.gutter / 2,
                offset: _.reduce(d3data, function(result, col) {
                    return result + col.width;
                }, 0)
            });
            d3data.push({
                type: "col",
                width: config.columnWidth,
                offset: _.reduce(d3data, function(result, col) {
                    return result + col.width;
                }, 0)
            });
            d3data.push({
                type: "gutter",
                width: config.gutter / 2,
                offset: _.reduce(d3data, function(result, col) {
                    return result + col.width;
                }, 0)
            });
        });
        return d3data;
    };
    GridView.prototype.draw = function() {
        var col;
        this.$el.html(this.template());
        col = d3.select(this.$el.find(".grid-columns")[0]).selectAll("g").data(this.data()).enter().append("g").attr("transform", function(d, i) {
            return "translate(" + d.offset + ",0)";
        });
        col.append("rect").attr("class", function(d) {
            return "grid-view-" + d.type;
        }).attr("width", function(d) {
            return d.width;
        }).attr("height", 100);
    };
    AGN.Lib.GridView = GridView;
})();

(function() {
    var GridColumnView;
    GridColumnView = function($target) {
        this.$el = $target;
    };
    GridColumnView.prototype.update = function(config) {
        this.config = config;
        this.draw();
    };
    GridColumnView.prototype.template = function() {
        var config = this.config;
        return _.template('<div class="grid-stage center-block" style="width: {{= viewWidth }}"px"; height: {{= viewHeight }}px;">' + '<svg class="column-view center-block" viewBox="0 0 {{= viewWidth }} {{= viewHeight }}" style="width: {{= viewWidth }}px; height: {{= viewHeight }}px">' + '<g class="grid-columns"></g>' + "</svg>" + "</div>")({
            viewWidth: config.templateWidth,
            viewHeight: config.columnNum * 35 - 5
        });
    };
    GridColumnView.prototype.data = function() {
        var config = this.config, d3data = [];
        _.times(config.columnNum, function(row) {
            var colData = [];
            colData.push({
                type: "gutter",
                width: config.gutter / 2,
                offset: 0
            });
            colData.push({
                type: "col",
                width: (row + 1) * config.columnWidth + row * config.gutter,
                offset: _.reduce(colData, function(result, col) {
                    return result + col.width;
                }, 0)
            });
            colData.push({
                type: "gutter",
                width: config.gutter / 2,
                offset: _.reduce(colData, function(result, col) {
                    return result + col.width;
                }, 0)
            });
            _.times(config.columnNum - (row + 1), function(col) {
                colData.push({
                    type: "gutter",
                    width: config.gutter / 2,
                    offset: _.reduce(colData, function(result, col) {
                        return result + col.width;
                    }, 0)
                });
                colData.push({
                    type: "empty-col",
                    width: config.columnWidth,
                    offset: _.reduce(colData, function(result, col) {
                        return result + col.width;
                    }, 0)
                });
                colData.push({
                    type: "gutter",
                    width: config.gutter / 2,
                    offset: _.reduce(colData, function(result, col) {
                        return result + col.width;
                    }, 0)
                });
            });
            d3data.push(colData);
        });
        return d3data;
    };
    GridColumnView.prototype.draw = function() {
        var config = this.config, col, row;
        this.$el.html(this.template());
        row = d3.select(this.$el.find(".grid-columns")[0]).selectAll(".row").data(this.data()).enter().append("g").attr("class", "row").attr("transform", function(d, i) {
            return "translate(0," + i * 35 + ")";
        });
        col = row.selectAll(".col").data(function(d) {
            return d;
        }).enter().append("g").attr("class", "col").attr("transform", function(d) {
            return "translate(" + d.offset + ",0)";
        });
        col.append("rect").attr("class", function(d) {
            return "column-view-" + d.type;
        }).attr("width", function(d) {
            return d.width;
        }).attr("height", 30);
        row.append("text").attr("class", "column-view-text").attr("x", config.gutter / 2 + 10).attr("y", 20).text(function(d, i) {
            return _.template("{{= width }}px / {{= perc }}%")({
                width: d[1].width,
                perc: Math.floor(100 * (i + 1) / config.columnNum)
            });
        });
    };
    AGN.Lib.GridColumnView = GridColumnView;
})();

(function() {
    var Help;
    var helpPopoverTemplate = '<div class="popover" role="tooltip">' + '<div class="arrow"></div>' + '<h3 class="popover-title"></h3>' + '<div class="popover-content popover-scrollable"></div>' + "</div>";
    Help = function($element) {
        var url = AGN.url($element.data("help")), self = this, jqhxr;
        this.el = $element;
        jqhxr = $.get(url);
        jqhxr.done(function(xml) {
            self.config = $(xml);
            self.popoverInteractive();
            self.show();
        });
    };
    Help.show = function($element) {
        var helpObj;
        helpObj = $element.data("_help");
        if (helpObj) {
            helpObj.show();
            return;
        }
        helpObj = new Help($element);
        $element.data("_help", helpObj);
    };
    Help.prototype.show = function() {
        this.el.popover("show");
    };
    Help.prototype.getConfig = function(key) {
        var val = this.config.find(key).text();
        return val.replace("<![CDATA[", "").replace("]]>", "");
    };
    Help.prototype.popover = function() {
        if (!this.config) {
            return;
        }
        this.el.popover("destroy");
        AGN.Lib.Popover.new(this.el, {
            template: helpPopoverTemplate,
            title: this.getConfig("title"),
            content: this.getConfig("content"),
            html: true,
            trigger: this.el.data("trigger") || "focus"
        });
    };
    Help.prototype.popoverInteractive = function() {
        if (!this.config) {
            return;
        }
        this.el.popover("destroy");
        var popover = AGN.Lib.Popover.new(this.el, {
            template: helpPopoverTemplate,
            title: this.getConfig("title"),
            content: this.getConfig("content"),
            html: true,
            trigger: "manual"
        });
        var elem = this.el;
        var tip = popover.tip();
        tip.attr("tabindex", 0);
        tip.css("outline", "none");
        var timeout = null;
        var onFocusLosing = function() {
            timeout = setTimeout(function() {
                popover.hide();
            }, 100);
        };
        var onFocusObtaining = function() {
            clearTimeout(timeout);
        };
        tip.focusout(onFocusLosing);
        elem.focusout(onFocusLosing);
        tip.focusin(onFocusObtaining);
        elem.focusin(onFocusObtaining);
        elem.on("shown.bs.popover", function() {
            var $content = tip.children(".popover-content");
            var minWidthOld = $content.css("min-width");
            var oldWidth = $content.outerWidth();
            $content.css("min-width", "100%");
            $content.css("min-width", $content.outerWidth());
            if (oldWidth > $content.outerWidth()) {
                $content.css("min-width", minWidthOld || "0px");
            }
        });
    };
    AGN.Lib.Help = Help;
})();

(function() {
    AGN.Lib.Helpers = {
        paramsFromUrl: function(url) {
            var result = {};
            var searchIndex;
            if (url) {
                searchIndex = url.indexOf("?");
            } else {
                return result;
            }
            if (searchIndex == -1) return result;
            var sPageURL = url.substring(searchIndex + 1);
            var sURLVariables = sPageURL.split("&");
            for (var i = 0; i < sURLVariables.length; i++) {
                var sParameterName = sURLVariables[i].split("=");
                result[sParameterName[0]] = sParameterName[1];
            }
            return result;
        },
        objFromString: function(optsAsString) {
            var optsArray, optsSplitRegex = /,\s*(?=(?:[^'\\]*(?:\\.|'(?:[^'\\]*\\.)*[^'\\]*'))*[^']*$)/m, tupleSplitRegex = /:\s*(?=(?:[^'\\]*(?:\\.|'(?:[^'\\]*\\.)*[^'\\]*'))*[^']*$)/m, floatRegex = /^\s*-?(\d*\.?\d+|\d+\.?\d*)(e[-+]?\d+)?\s*$/i, arrayRegex = /^\s?\[.*?\]$/i;
            opts = {};
            if (optsAsString === "" || optsAsString === undefined) {
                return opts;
            }
            optsArray = optsAsString.split(optsSplitRegex);
            _.forEach(optsArray, function(opt) {
                var tup = opt.split(tupleSplitRegex), name, value;
                tup = _.filter(tup);
                name = tup[0].replace(/^'([^]*?)'$/m, "$1");
                name = name.replace(/\\/, "");
                value = tup[1];
                if (typeof value === "undefined") {
                    value = "";
                }
                if (value == "true") {
                    value = true;
                } else if (value == "false") {
                    value = false;
                } else if (floatRegex.test(value)) {
                    value = parseFloat(value);
                } else if (arrayRegex.test(value)) {
                    value = value.replace(/\[|\]/g, "");
                    value = value.split(/\s+/);
                    value = _.map(value, function(v) {
                        if (/^\'(.*?)\'$/.test(v)) {
                            return v.replace(/^\'(.*?)\'$/g, "$1");
                        } else {
                            return eval(v);
                        }
                    });
                } else {
                    value = value.replace(/^'(.*?)'$/m, "$1");
                    value = value.replace(/\\/, "");
                }
                opts[name] = value;
            });
            return opts;
        },
        disableCSSAnimations: function() {
            var script = $('<style class="disable-animation">* { -webkit-transition: none !important; -o-transition: none !important; transition: none !important; }</style>');
            $("body").append(script);
        },
        enableCSSAnimations: function() {
            window.setTimeout(function() {
                $(".disable-animation").remove();
            }, 10);
        },
        clearFormField: function($element) {
            var $form = $("<form></form>");
            var $div = $("<div></div>");
            $div.insertAfter($element);
            $form.append($element);
            $form.get(0).reset();
            $element.insertBefore($div);
            $div.remove();
        },
        renameFile: function(file, name) {
            Object.defineProperty(file, "name", {
                writable: true,
                value: name
            });
        },
        formatBytes: function(bytes, units) {
            if (bytes == 0) return "0 Bytes";
            if (bytes == 1) return "1 Byte";
            if (bytes == -1) return "-1 Byte";
            var bytes = Math.abs(bytes);
            if (units && units.toLowerCase() && units.toLowerCase() == "iec") {
                var orderOfMagnitude = Math.pow(2, 10);
                var abbreviations = [ "Bytes", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB" ];
            } else {
                var orderOfMagnitude = Math.pow(10, 3);
                var abbreviations = [ "Bytes", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" ];
            }
            var i = Math.floor(Math.log(bytes) / Math.log(orderOfMagnitude));
            var result = bytes / Math.pow(orderOfMagnitude, i);
            if (bytes < 0) {
                result *= -1;
            }
            if (result >= 99.995 || i == 0) {
                return result.toFixed(0) + " " + abbreviations[i];
            } else {
                return result.toFixed(2) + " " + abbreviations[i];
            }
        },
        pad: function(value, count, char) {
            char = char || "0";
            var s = value + "";
            if (s.length < count) {
                return new Array(count - s.length + 1).join(char) + s;
            } else {
                return s;
            }
        },
        caching: function(func, thisArg) {
            var calculated = false;
            var value;
            if (arguments.length > 1) {
                func = _.bind.apply(null, Array.prototype.slice.call(arguments));
            }
            return function() {
                if (!calculated) {
                    calculated = true;
                    value = func();
                }
                return value;
            };
        },
        replaceAgnTags: function(html, replacementFn) {
            try {
                return html.replace(/\[(agn[A-Z0-9]+)(?:[^'"\]]|'.*?'|".*?")+]/g, function(whole, tagName) {
                    var tag = $("<" + whole.substring(1, whole.length - 1) + ">")[0];
                    if (tag instanceof HTMLElement) {
                        var tagAttributes = tag.attributes;
                        var attributes = {};
                        for (var i = 0; i < tagAttributes.length; i++) {
                            var tagAttribute = tagAttributes[i];
                            attributes[tagAttribute.nodeName] = tagAttribute.nodeValue;
                        }
                        return replacementFn({
                            name: tagName,
                            attributes: attributes
                        }, whole);
                    }
                    return whole;
                });
            } catch (e) {}
            return html;
        },
        escapeAgnTags: function(html) {
            try {
                if (html) {
                    return html.replace(/\[agn[A-Z0-9]+(?:[^'"\]]|'.*?'|".*?")+]/g, function(whole) {
                        if (whole.includes("'") || whole.includes('"')) {
                            return _.escape(whole);
                        } else {
                            return whole;
                        }
                    });
                }
            } catch (e) {}
            return html;
        },
        unescapeAgnTags: function(html) {
            try {
                if (html) {
                    return html.replace(/\[agn[A-Z0-9]+(?:(?!&#39;|&quot;)[^'"\]]|=\s*&#39;.*?&#39;|=\s*&quot;.*?&quot;)*]/g, function(whole) {
                        return _.unescape(whole);
                    });
                }
            } catch (e) {}
            return html;
        },
        isValidEmail: function(email) {
            var re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
            return re.test(String(email).toLowerCase());
        }
    };
})();

(function() {
    var Load;
    Load = function($element) {
        var callback, self = this;
        self.el = $element;
        self.url = $element.data("load");
        self.interval = parseInt($element.data("load-interval"));
        self.target = $element.data("load-target");
        if (self.interval) {
            callback = function() {
                self.load();
            };
            self._interval = window.setInterval(callback, self.interval);
        }
        self.el.removeAttr("data-load");
    };
    Load.load = function($element, isAlwaysLoad) {
        var loadObj;
        loadObj = $element.data("_load");
        if (loadObj) {
            loadObj.load();
            return;
        }
        if ($element.is(":hidden") && isAlwaysLoad !== true) {
            return;
        }
        loadObj = new Load($element);
        loadObj.load();
        $element.data("_load", loadObj);
    };
    Load.get = function($el) {
        return $el.data("_load");
    };
    Load.prototype.stop = function() {
        window.clearInterval(this._interval);
    };
    Load.prototype.load = function() {
        var jqxhr, self = this;
        if (self.loading) {
            return;
        }
        self.loading = true;
        jqxhr = $.get(self.url);
        jqxhr.always(function() {
            if (self.interval) {
                self.loading = false;
            }
        });
        jqxhr.fail(function() {
            self.stop();
        });
        jqxhr.done(function(resp) {
            var $resp = $(resp), $target, $loadStop;
            $loadStop = $resp.all("[data-load-stop]");
            if ($loadStop.length != 0) {
                self.stop();
            }
            if (!self.target) {
                $target = resp;
            } else if (self.target == "body") {
                $target = /<body[^>]*>((.|[\n\r])*)<\/body>/im.exec(resp)[1];
            } else {
                $target = $resp.all(self.target);
            }
            self.el.html($target);
            AGN.Lib.Controller.init(self.el);
            AGN.runAll(self.el);
        });
    };
    AGN.Lib.Load = Load;
})();

(function() {
    var Loader = {}, hiding, requestCount = 0, prevent = false;
    Loader.show = function() {
        window.clearTimeout(hiding);
        if (!prevent) {
            requestCount += 1;
            $(".loader").show();
        } else {
            prevent = false;
        }
    };
    Loader.hide = function() {
        requestCount -= 1;
        if (requestCount <= 0) {
            hiding = window.setTimeout(function() {
                $(".loader").hide();
            }, 5);
            requestCount = 0;
        }
    };
    Loader.prevent = function() {
        prevent = true;
    };
    AGN.Lib.Loader = Loader;
})();

(function() {
    var LoadingForm, Form = AGN.Lib.Form;
    LoadingForm = function($form) {
        Form.apply(this, [ $form ]);
        AGN.Lib.Loader.show();
        this.submit();
    };
    LoadingForm.prototype = Object.create(Form.prototype);
    LoadingForm.prototype.constructor = LoadingForm;
    LoadingForm.prototype.jqxhr = function() {
        var self = this, deferred = $.Deferred();
        this.$form.trigger("form:submit");
        window.setTimeout(function() {
            var jqxhr = $.ajax({
                url: self.url,
                method: self.method,
                data: self.params(),
                loader: self.loader()
            });
            jqxhr.done(function(resp) {
                deferred.resolve.apply(this, arguments);
            });
        }, parseInt(this.$form.data("polling-interval")));
        return deferred.promise();
    };
    LoadingForm.prototype.submit = function() {
        var jqxhr, self = this;
        jqxhr = this.jqxhr();
        jqxhr.done(function(resp) {
            self.updateHtml(resp);
        });
        return jqxhr;
    };
    LoadingForm.prototype.updateHtml = function(resp) {
        var $newForm, $resp = $(resp);
        $newForm = $resp.filter('[data-form="loading"]').add($resp.find('[data-form="loading"]'));
        if ($newForm.length == 1) {
            this.$form.html($newForm.html());
            AGN.runAll(this.$form);
            this.submit();
        } else {
            AGN.Lib.Loader.hide();
            AGN.Lib.Page.render(resp);
        }
    };
    AGN.Lib.LoadingForm = LoadingForm;
    AGN.Opt.Forms["loading"] = LoadingForm;
})();

(function() {
    var Menu;
    Menu = {
        init: function() {
            var conf = AGN.Lib.Storage.get("menu_state") || "close";
            if (conf == "open") {
                this.openDirectly();
            } else {
                this.closeDirectly();
            }
            this.updateInits();
        },
        isOpen: function() {
            return $("body").hasClass("menu-is-active");
        },
        openDirectly: function() {
            AGN.Lib.Helpers.disableCSSAnimations();
            this.open();
            AGN.Lib.Helpers.enableCSSAnimations();
        },
        closeDirectly: function() {
            AGN.Lib.Helpers.disableCSSAnimations();
            this.close();
            AGN.Lib.Helpers.enableCSSAnimations();
        },
        close: function() {
            AGN.Lib.Storage.set("menu_state", "close");
            $("body").removeClass("menu-is-active");
            this.updateInits();
        },
        open: function() {
            AGN.Lib.Storage.set("menu_state", "open");
            $("body").addClass("menu-is-active");
            this.updateInits();
        },
        updateInits: function() {
            window.setTimeout(function() {
                AGN.Lib.CoreInitializer.run([ "truncate", "scrollable", "dropdown-expand" ]);
            }, 600);
        }
    };
    AGN.Lib.Menu = Menu;
})();

(function() {
    var Messages = function(messageHead, messageContent, type, onClose, newestOnTop) {
        var $message, timeout, options = {
            timeout: {
                success: 3e3,
                warning: 3e3
            }
        };
        if (!type) {
            type = "info";
        }
        if (newestOnTop === null) {
            newestOnTop = true;
        }
        timeout = options["timeout"][type || "info"] || 0;
        _.each($(".notification"), function(message) {
            var $message = $(message), displayedMessageHead, displayedMessageContent;
            displayedMessageHead = $message.data("message-head");
            displayedMessageContent = $message.data("message-content");
            if (messageHead === displayedMessageHead && messageContent === displayedMessageContent) {
                $message.remove();
            }
        });
        $message = toastr[type](messageHead, messageContent, {
            timeOut: timeout,
            extendedTimeOut: timeout,
            onCloseClick: onClose,
            newestOnTop: newestOnTop
        });
        $message.data("message-head", messageHead);
        $message.data("message-content", messageContent);
        AGN.Lib.Controller.init($message);
        AGN.runAll($message);
    };
    var displayMessages = function(title, messages, type) {
        messages.forEach(function(text) {
            Messages(title, text, type);
        });
    };
    var hideMessages = function() {
        _.each($(".notification"), function(message) {
            message.remove();
        });
    };
    var JsonMessages = function(messages, removeDisplayedMessages) {
        if (!!removeDisplayedMessages) {
            hideMessages();
        }
        if (messages) {
            if (messages.success) {
                displayMessages(t("defaults.success"), messages.success, "success");
            }
            if (messages.warning) {
                displayMessages(t("defaults.warning"), messages.warning, "warning");
            }
            if (messages.alert) {
                displayMessages(t("defaults.error"), messages.alert, "alert");
            }
        }
    };
    var RenderMessages = function($resp) {
        $resp.all('script[data-message][type="text/html"]').appendTo($(document.body));
        $resp.all('script[data-message][type="text/javascript"]').each(function() {
            try {
                eval($(this).html());
            } catch (exception) {
                console.debug(exception);
            }
        });
    };
    AGN.Lib.Messages = Messages;
    AGN.Lib.JsonMessages = JsonMessages;
    AGN.Lib.RenderMessages = RenderMessages;
})();

(function() {
    var map = {};
    function send(topic) {
        var k = "key#" + topic;
        var callbacks = map[k];
        var args = Array.prototype.slice.call(arguments, 1);
        if (callbacks) {
            map[k] = callbacks.filter(function(callback) {
                return callback.apply(this, args) !== false;
            });
        }
    }
    function subscribe(topic, callback) {
        var k = "key#" + topic;
        if ($.isFunction(callback)) {
            if (!map[k]) {
                map[k] = [];
            }
            map[k].push(callback);
        } else {
            console.error("Callback must be a function");
        }
    }
    function unsubscribe(topic, callback) {
        if (arguments.length) {
            var k = "key#" + topic;
            if (arguments.length > 1) {
                map[k] = map[k].filter(function(c) {
                    return c !== callback;
                });
            } else {
                map[k] = [];
            }
        }
    }
    AGN.Lib.Messaging = {
        send: send,
        subscribe: subscribe,
        unsubscribe: unsubscribe
    };
})();

(function() {
    var Modal;
    Modal = function() {};
    Modal.create = function(src, conf) {
        var $modal = null, $resp = null;
        if (src instanceof $) {
            $resp = src;
        } else {
            $resp = $(src);
        }
        var $modals = $resp.filter(".modal");
        var $scripts = $resp.filter("script");
        if ($modals) {
            $modal = $($modals[0]);
            $modal.data("_modal", conf);
            $scripts.each(function() {
                $(this).appendTo($modal);
            });
            $modal = $modal.modal();
            AGN.Lib.Controller.init($modal);
            AGN.runAll($modal);
        }
        return $modal;
    };
    Modal.createFromTemplate = function(conf, template) {
        template = AGN.Opt.Templates[template] || AGN.Opt.Templates["modal"];
        return Modal.create(_.template(template)(conf), conf);
    };
    Modal.get = function($needle) {
        var $modal = Modal.getWrapper($needle);
        return $modal.data("_modal");
    };
    Modal.getWrapper = function($needle) {
        return $needle.closest(".modal");
    };
    AGN.Lib.Modal = Modal;
})();

(function() {
    var Confirm = AGN.Lib.Confirm, Page = {};
    function getValidMethod(method) {
        if (method) {
            method = method.toUpperCase();
            switch (method) {
              case "CONNECT":
              case "DELETE":
              case "GET":
              case "HEAD":
              case "OPTIONS":
              case "POST":
              case "PUT":
                return method;
            }
        }
        return "GET";
    }
    Page.render = function(resp, address) {
        if (/<\s*\/\s*body\s*>/i.test(resp)) {
            var parser = new DOMParser();
            var doc = parser.parseFromString(resp, "text/html");
            if (address !== false && doc.head) {
                var uri = $(doc.head).data("origin-uri");
                if (uri) {
                    address = uri;
                }
            }
            if (address) {
                window.history.pushState({}, "", address);
            }
            var posY = $(document).scrollTop();
            setTimeout(function() {
                AGN.Lib.Controller.init();
                AGN.runAll();
                $(document).scrollTop(posY);
            }, 100);
            document.body = doc.body;
            document.title = doc.title;
            var $body = $(document.body);
            $body.find("script").each(function(index, e) {
                var $e = $(e);
                if ($e.attr("src")) {
                    var $script = $("<script><\/script>");
                    $.each(e.attributes, function() {
                        if (this.specified) {
                            $script.attr(this.name, this.value);
                        }
                    });
                    try {
                        $script.appendTo($body);
                    } catch (exception) {
                        console.debug(exception);
                    }
                } else if ($e.attr("type") == "text/javascript") {
                    try {
                        eval.call(window, $e.html());
                    } catch (exception) {
                        console.debug(exception);
                    }
                }
            });
        } else {
            var $resp = $(resp);
            var $e = $resp.filter(".modal");
            if ($e.exists()) {
                var deferred = $.Deferred();
                AGN.Lib.RenderMessages($resp);
                Confirm.create($resp);
                deferred.resolve(Confirm.get($resp));
                return deferred.promise();
            } else {
                $e = $resp.all("script[data-load]");
                if ($e.exists()) {
                    return Page.reload($e.data("load"), true).done(function() {
                        AGN.Lib.RenderMessages($resp);
                    });
                } else {
                    AGN.Lib.RenderMessages($resp);
                }
            }
        }
    };
    Page.reload = function(address, ajax, method) {
        if (ajax) {
            address = address || window.location.href;
            var deferred = $.Deferred();
            $.ajax(address, {
                method: getValidMethod(method)
            }).done(function(resp) {
                var promise = Page.render(resp, address);
                if (promise) {
                    promise.done(deferred.resolve).fail(deferred.reject);
                } else {
                    deferred.resolve();
                }
            }).fail(function() {
                deferred.reject();
            });
            return deferred.promise();
        } else {
            if (address && address != window.location.href) {
                window.location.assign(address);
            } else {
                window.location.reload(true);
            }
            return null;
        }
    };
    AGN.Lib.Page = Page;
})();

(function() {
    var PasswordPolicies = {};
    var policy_LENGTH_8_MIXED = function(password) {
        var errors = [];
        if (password.length < 8) {
            errors.push("password.error.too_short_min8");
        }
        if (!password.match("[a-z]")) {
            errors.push("password.error.no_lower_case");
        }
        if (!password.match("[A-Z]")) {
            errors.push("password.error.no_upper_case");
        }
        if (!password.match("[0-9]")) {
            errors.push("password.error.no_digits");
        }
        if (!password.match("[^a-zA-Z0-9]")) {
            errors.push("password.error.no_special");
        }
        return errors;
    };
    var policy_LENGTH_12_SIMPLE = function(password) {
        if (password.length < 12) {
            return [ "password.error.too_short_min12" ];
        } else {
            return null;
        }
    };
    var policy_WEBSERVICE = function(password) {
        if (password.length < 32) {
            return [ "password.error.too_short_min32" ];
        } else {
            return null;
        }
    };
    var policy_FALLBACK = function(password) {
        return [ "password.error.generic_error" ];
    };
    var policy_map = [];
    register_policy("LENGTH_8_MIXED", policy_LENGTH_8_MIXED);
    register_policy("LENGTH_12_SIMPLE", policy_LENGTH_12_SIMPLE);
    register_policy("WEBSERVICE", policy_WEBSERVICE);
    function register_policy(name, policy_fn) {
        policy_map.push({
            name: name,
            fn: policy_fn
        });
    }
    PasswordPolicies.find_password_policy = function(name) {
        for (var i = 0; i < policy_map.length; i++) {
            if (policy_map[i].name == name) {
                return policy_map[i].fn;
            }
        }
        return policy_FALLBACK;
    };
    AGN.Lib.PasswordPolicies = PasswordPolicies;
})();

(function() {
    var PollingForm, Page = AGN.Lib.Page, Form = AGN.Lib.Form;
    PollingForm = function($form) {
        Form.apply(this, [ $form ]);
    };
    PollingForm.prototype = Object.create(Form.prototype);
    PollingForm.prototype.constructor = PollingForm;
    PollingForm.prototype.jqhxr = function() {
        var self = this, deferred = $.Deferred();
        this.$form.trigger("form:submit");
        window.setTimeout(function() {
            var jqxhr = $.ajax({
                url: self.url,
                method: self.method,
                data: self.params(),
                loader: self.loader()
            });
            jqxhr.done(function(resp) {
                var $resp = $(resp);
                var $newForm = $resp.all('[data-form="polling"]');
                if ($newForm.length == 1) {
                    self.$form.data("polling-interval", $newForm.data("polling-interval"));
                    self.jqhxr().done(function() {
                        deferred.resolve.apply(this, arguments);
                    });
                } else {
                    deferred.resolve.apply(this, arguments);
                }
            });
        }, parseInt(this.$form.data("polling-interval")));
        return deferred.promise();
    };
    PollingForm.prototype.submit = function() {
        var jqxhr, self = this;
        AGN.Lib.Loader.show();
        jqxhr = this.jqxhr();
        jqxhr.done(function(resp) {
            AGN.Lib.Loader.hide();
            self.updateHtml(resp);
        });
        return jqxhr;
    };
    PollingForm.prototype.updateHtml = function(resp) {
        var $newForm, $resp = $(resp), renderMode = this.$form.data("render");
        if (renderMode == "page") {
            Page.render(resp);
        } else {
            if (this.$form.attr("id")) {
                $newForm = $resp.all("#" + this.$form.attr("id"));
            } else if (this.$form.attr("name")) {
                $newForm = $resp.all('[name="' + this.$form.attr("name") + '"]');
            } else {
                $newForm = $resp.all("form");
            }
            setTimeout(function() {
                AGN.Lib.Controller.init();
                AGN.runAll();
            }, 100);
            this.handleMessages(resp);
            this.$form.replaceWith($newForm);
        }
    };
    AGN.Lib.PollingForm = PollingForm;
    AGN.Opt.Forms["polling"] = PollingForm;
})();

(function($) {
    var Popover = {};
    var placementFunction = function(balloon, element) {
        var $balloon = $(balloon);
        var $e = $(element);
        var windowTop = $(window).scrollTop();
        var windowHeight = $(window).outerHeight();
        var height = $e.outerHeight();
        var top = $e.offset().top - windowTop;
        var bottom = top + height;
        if ($balloon.outerHeight() <= top) {
            return "top";
        }
        return windowHeight - bottom > top ? "bottom" : "top";
    };
    Popover.new = function($e, options) {
        if ($e.length !== 1) {
            return false;
        }
        $e.popover($.extend({
            container: "body",
            placement: placementFunction
        }, options));
        var popover = $e.data("bs.popover");
        if (options && options.enableAgnRunAll) {
            $e.on("shown.bs.popover", function() {
                var $tip = popover.tip();
                AGN.Lib.Controller.init($tip);
                AGN.runAll($tip);
            });
        }
        return popover;
    };
    Popover.get = function($e) {
        if ($e.length !== 1) {
            return null;
        }
        var popover = $e.data("bs.popover");
        if (popover) {
            return popover;
        }
        return $e.closest("div.popover").data("bs.popover");
    };
    Popover.remove = function($e) {
        if ($e.length !== 1) {
            return false;
        }
        $e.popover("destroy");
        return true;
    };
    Popover.validate = function() {
        $(".popover").each(function() {
            var popover = $(this).data("bs.popover");
            if (popover && popover.$element) {
                if (!$.contains(document.body, popover.$element[0])) {
                    popover.destroy();
                }
            }
        });
    };
    AGN.Lib.Popover = Popover;
})(jQuery);

(function() {
    var ResourceForm, Form = AGN.Lib.Form, Page = AGN.Lib.Page;
    ResourceForm = function($form) {
        Form.apply(this, [ $form ]);
        this.resourceSelector = $form.data("resource-selector");
    };
    ResourceForm.prototype = Object.create(Form.prototype);
    ResourceForm.prototype.getResourceSelector = function() {
        if (this.resourceSelectorNextRequest) {
            var value = this.resourceSelectorNextRequest;
            this.resourceSelectorNextRequest = null;
            return value;
        }
        return this.resourceSelector;
    };
    ResourceForm.prototype.setResourceSelectorOnce = function(resourceSelector) {
        this.resourceSelectorNextRequest = resourceSelector;
    };
    ResourceForm.prototype.updateHtml = function(resp) {
        var selector = this.getResourceSelector();
        if (selector) {
            var $resp = $(resp);
            var $target = $(selector);
            var $source = $resp.all(selector);
            if ($target.length == 1 && $source.length == 1) {
                var isInitRequired = false;
                if ($target[0] == this.$form[0] || $.contains($target[0], this.$form[0])) {
                    isInitRequired = true;
                }
                $target.html($source.html());
                this.handleMessages($resp);
                if (isInitRequired) {
                    this.initFields();
                    this.initValidator();
                }
                AGN.Lib.Controller.init($target);
                AGN.runAll($target);
            } else {
                Page.render(resp);
                this.handleMessages(resp, true);
            }
        } else {
            Page.render(resp);
            this.handleMessages(resp, true);
        }
    };
    AGN.Lib.ResourceForm = ResourceForm;
    AGN.Opt.Forms["resource"] = ResourceForm;
})();

(function() {
    function TrackableLinks(url, cache) {
        this.src = url;
        this.promises = {};
        this.cache = $.extend({}, cache);
    }
    TrackableLinks.prototype.retrieve = function(mailingId) {
        var promises = this.promises;
        var cache = this.cache;
        var promise = promises[mailingId];
        if (promise && promise.state() == "pending") {
            return promise;
        }
        var d = $.Deferred();
        promise = d.promise();
        if (cache[mailingId]) {
            d.resolve(cache[mailingId]);
        } else if (this.src) {
            var req = $.ajax(this.src, {
                type: "POST",
                data: {
                    mailingId: mailingId
                }
            });
            promises[mailingId] = promise;
            req.always(function() {
                delete promises[mailingId];
            });
            req.done(function(data) {
                if (data && data.mailingId == mailingId) {
                    var links = data.links || [];
                    cache[mailingId] = links;
                    d.resolve(links, mailingId);
                } else {
                    d.reject(mailingId);
                }
            });
            req.fail(function() {
                d.reject(mailingId);
            });
        } else {
            d.reject(mailingId);
        }
        return promise;
    };
    var COLUMN_TYPE_DATE = "DATE", COLUMN_TYPE_DATETIME = "DATETIME", COLUMN_TYPE_INTEGER = "INTEGER", COLUMN_TYPE_DOUBLE = "DOUBLE", COLUMN_TYPE_FLOAT = "FLOAT", COLUMN_TYPE_NUMBER = "NUMBER", COLUMN_TYPE_MAILING = "MAILING", COLUMN_TYPE_MAILING_LINKS = "MAILING_LINKS", COLUMN_TYPE_INTERVAL_MAILING = "INTERVAL_MAILING";
    function isNumericType(columnType) {
        switch (columnType) {
          case COLUMN_TYPE_INTEGER:
          case COLUMN_TYPE_DOUBLE:
          case COLUMN_TYPE_FLOAT:
          case COLUMN_TYPE_NUMBER:
            return true;

          default:
            return false;
        }
    }
    function getAvailablePrimaryOperators(config, columnType) {
        switch (columnType) {
          case COLUMN_TYPE_DATE:
          case COLUMN_TYPE_DATETIME:
            return config.dateOperators;

          case COLUMN_TYPE_MAILING:
          case COLUMN_TYPE_MAILING_LINKS:
            return config.mailingOperators;

          case COLUMN_TYPE_INTERVAL_MAILING:
            return config.intervalMailingOperators;

          default:
            if (isNumericType(columnType)) {
                return config.numericOperators;
            } else {
                return config.stringOperators;
            }
        }
    }
    function changedColumn(idx, config) {
        var columnSel = getElemWithIndexedName("columnAndType", idx);
        if (columnSel) {
            var columnOpt = columnSel.options[columnSel.selectedIndex];
            var columnName = columnOpt.value.toUpperCase();
            var columnType = columnOpt.getAttribute("data-extra").toUpperCase();
            var primaryOp = getElemWithIndexedName("primaryOperator", idx);
            var primaryVal = getElemWithIndexedName("primaryValue", idx);
            if (primaryOp.value == config["OPERATOR_IS"]) {
                switchToIsOperator(config, primaryVal, idx);
            } else if (primaryOp.value == config["OPERATOR_MOD"] && isNumericType(columnType)) {
                switchToModOperator(config, primaryVal, idx);
            } else if (columnType == COLUMN_TYPE_DATE || columnType === COLUMN_TYPE_DATETIME) {
                switchToDateType(config, primaryVal, idx);
            } else if (columnType == COLUMN_TYPE_INTERVAL_MAILING) {
                switchToIntervalMailingType(config, primaryVal, idx);
            } else if (columnType == COLUMN_TYPE_MAILING) {
                switchToMailingType(config, primaryVal, idx);
            } else if (columnType == COLUMN_TYPE_MAILING_LINKS) {
                switchToMailingLinksType(config, primaryVal, idx);
            } else if (columnName == "MAILTYPE") {
                switchToMailType(config, primaryVal, idx);
            } else if (columnName == "GENDER") {
                switchToGender(config, primaryVal, idx);
            } else {
                switchToStringType(config, primaryVal, idx);
            }
            resetPrimaryOperators(config, primaryOp, columnType, idx);
        }
    }
    function resetPrimaryOperators(config, primaryOp, columnType, idx) {
        var op = primaryOp.value;
        var select = createSelectElement(getIndexedName("primaryOperator", idx), "form-control", "1", idx);
        var operators = getAvailablePrimaryOperators(config, columnType);
        $.each(extractValues(operators), function(index, operator) {
            appendOption(select, op, operator.id, operator.value);
        });
        replaceElement(primaryOp, select);
    }
    function resetMailingUrls(config, idx) {
        var primaryVal = getElemWithIndexedName("primaryValue", idx);
        var primaryValue = primaryVal.value;
        var newSelect = createSelectElement(getIndexedName("secondaryValue", idx), "form-control js-select js-option-popovers", "1", idx);
        newSelect.setAttribute("data-action", "updateMailingLinkId" + (idx == null ? "New" : ""));
        populateSelectWithLinks(config, primaryValue, newSelect, config.mailingLinksSelectionsCache[idx] && config.mailingLinksSelectionsCache[idx][primaryValue]);
        var $primaryVal = $(primaryVal);
        var existingSelect = $primaryVal.clone();
        existingSelect.val($primaryVal.val());
        existingSelect.css({
            display: "block"
        });
        replaceElements([ existingSelect, newSelect ], $(primaryVal.parentNode));
    }
    function updateMailingLinksCache(config, idx, mailingLinkId) {
        var primaryVal = getElemWithIndexedName("primaryValue", idx);
        var mailingId = primaryVal.value;
        var cache = config.mailingLinksSelectionsCache[idx];
        if (!cache) {
            cache = {};
            config.mailingLinksSelectionsCache[idx] = cache;
        }
        cache[mailingId] = mailingLinkId;
    }
    function querySelectOptions(name) {
        return $('select[name="' + name + '"] option');
    }
    function mapSelectToObjects(name) {
        return mapSelectOptionsToObjects(querySelectOptions(name));
    }
    function mapSelectOptionsToObjects($options) {
        return $.map($options.toArray(), function(option) {
            var $option = $(option);
            return {
                id: $option.val(),
                value: $option.text()
            };
        });
    }
    function configure(options) {
        var mailingLinksCache = {};
        $('select[name="all_mailings_urls_config"] optgroup').each(function() {
            var $group = $(this);
            var $options = $group.find("option");
            mailingLinksCache[$group.attr("label")] = $options.map(function() {
                var $option = $(this);
                return {
                    id: $option.val(),
                    value: $option.text()
                };
            });
        });
        return $.extend(options, {
            mailingLinks: new TrackableLinks(options && options["URL_GET_MAILING_LINKS"], mailingLinksCache),
            mailingLinksSelectionsCache: {},
            allColumns: querySelectOptions("all_columns_config"),
            intervalMailings: mapSelectToObjects("interval_mailings_config"),
            modSecondaryOperators: mapSelectToObjects("mod_secondary_operators_config"),
            allMailings: mapSelectToObjects("all_mailings_config"),
            dateOperators: mapSelectToObjects("date_operators_config"),
            mailingOperators: mapSelectToObjects("mailing_operators_config"),
            intervalMailingOperators: mapSelectToObjects("interval_mailing_operators_config"),
            numericOperators: mapSelectToObjects("numeric_operators_config"),
            stringOperators: mapSelectToObjects("string_operators_config"),
            mailTypes: mapSelectToObjects("mail_types_config"),
            genders: mapSelectToObjects("genders_config"),
            dateFormats: mapSelectToObjects("date_formats_config")
        });
    }
    function switchToIsOperator(config, primaryValElement, idx) {
        var value = primaryValElement.value == null ? "" : primaryValElement.value;
        var select = createSelectElement(getIndexedName("primaryValue", idx), "form-control", "1", null);
        appendOption(select, value, "null", "null");
        appendOption(select, value, "not null", "not null");
        replaceElements([ select ], $(primaryValElement.parentNode));
    }
    function switchToModOperator(config, primaryValElement, idx) {
        var modSecondaryOperators = config.modSecondaryOperators;
        var value = primaryValElement.value == null ? "" : primaryValElement.value;
        var secondaryOp = getElemWithIndexedName("secondaryOperator", idx);
        var op = secondaryOp == null ? "" : secondaryOp.value;
        var secondaryVal = getElemWithIndexedName("secondaryValue", idx);
        var secondaryValue = secondaryVal == null ? "" : secondaryVal.value;
        var input = createInputElement(getIndexedName("primaryValue", idx), value, "form-control");
        var select = createSelectElement(getIndexedName("secondaryOperator", idx), "form-control", "1", null);
        $.each(extractValues(modSecondaryOperators), function(index, operator) {
            appendOption(select, op, operator.id, operator.value);
        });
        var input2 = createInputElement(getIndexedName("secondaryValue", idx), secondaryValue, "form-control");
        replaceElements([ input, select, input2 ], $(primaryValElement.parentNode));
    }
    function switchToStringType(config, primaryValElement, idx) {
        var value = primaryValElement.value == null ? "" : primaryValElement.value;
        var input = createInputElement(getIndexedName("primaryValue", idx), value, "form-control");
        replaceElements([ input ], $(primaryValElement.parentNode));
    }
    function switchToMailType(config, primaryValElement, idx) {
        var mailTypes = config.mailTypes;
        var value = primaryValElement.value == null ? "" : primaryValElement.value;
        var select = createSelectElement(getIndexedName("primaryValue", idx), "form-control", "1", null);
        $.each(extractValues(mailTypes), function(index, mailType) {
            appendOption(select, value, mailType.id, mailType.value);
        });
        replaceElements([ select ], $(primaryValElement.parentNode));
    }
    function switchToGender(config, primaryValElement, idx) {
        var genders = config.genders;
        var value = primaryValElement.value == null ? "" : primaryValElement.value;
        var select = createSelectElement(getIndexedName("primaryValue", idx), "form-control", "1", null);
        $.each(extractValues(genders), function(index, gender) {
            appendOption(select, value, gender.id, gender.value);
        });
        replaceElements([ select ], $(primaryValElement.parentNode));
    }
    function switchToDateType(config, primaryValElement, idx) {
        var dateFormats = config.dateFormats;
        var value = primaryValElement.value == null ? "" : primaryValElement.value;
        var dateFormatEl = getElemWithIndexedName("dateFormat", idx);
        var dateFormat = dateFormatEl == null ? "" : dateFormatEl.value;
        var input = createInputElement(getIndexedName("primaryValue", idx), value, "form-control");
        var select = createSelectElement(getIndexedName("dateFormat", idx), "form-control", "1", null);
        $.each(extractValues(dateFormats), function(index, format) {
            appendOption(select, dateFormat, format.id, format.value);
        });
        replaceElements([ input, select ], $(primaryValElement.parentNode));
    }
    function switchToIntervalMailingType(config, primaryValElement, idx) {
        var intervalMailings = config.intervalMailings;
        var selectedValue = primaryValElement.value == null ? "" : primaryValElement.value;
        var select = createSelectElement(getIndexedName("primaryValue", idx), "form-control js-select", "1", null);
        $.each(extractValues(intervalMailings), function(index, mailing) {
            appendOption(select, selectedValue, mailing.id, mailing.value);
        });
        replaceElements([ select ], $(primaryValElement.parentNode));
    }
    function switchToMailingType(config, primaryValElement, idx) {
        var allMailings = config.allMailings;
        var value = primaryValElement.value == null ? "" : primaryValElement.value;
        var select = createSelectElement(getIndexedName("primaryValue", idx), "form-control js-select", "1", null);
        $.each(extractValues(allMailings), function(index, mailing) {
            appendOption(select, value, mailing.id, mailing.value);
        });
        replaceElements([ select ], $(primaryValElement.parentNode));
    }
    function switchToMailingLinksType(config, primaryValElement, idx) {
        var allMailings = config.allMailings;
        var value = primaryValElement.value == null ? "" : primaryValElement.value;
        var secondaryVal = getElemWithIndexedName("secondaryValue", idx);
        var secondaryValue = secondaryVal == null ? "" : secondaryVal.value;
        var select = createSelectElement(getIndexedName("primaryValue", idx), "form-control js-select", "1", idx);
        select.setAttribute("data-action", "resetMailingUrls" + (idx == null ? "New" : ""));
        $.each(extractValues(allMailings), function(index, mailing) {
            appendOption(select, value, mailing.id, mailing.value);
        });
        value = select.value;
        var select2 = createSelectElement(getIndexedName("secondaryValue", idx), "form-control js-select js-option-popovers", "1", idx);
        select2.setAttribute("data-action", "updateMailingLinkId" + (idx == null ? "New" : ""));
        populateSelectWithLinks(config, value, select2, config.mailingLinksSelectionsCache[idx] && config.mailingLinksSelectionsCache[idx][value]);
        replaceElements([ select, select2 ], $(primaryValElement.parentNode));
    }
    function getElemWithIndexedName(name, idx) {
        return document.getElementsByName(getIndexedName(name, idx))[0];
    }
    function getIndexedName(name, idx) {
        return name + (idx != null ? "[" + idx + "]" : "New");
    }
    function populateSelectWithLinks(config, mailingId, select, selectedValue) {
        config.mailingLinks.retrieve(mailingId).done(function(urls) {
            if (urls.length == 0) {
                return;
            }
            var selection = null;
            $.each(urls, function(index) {
                if (index == 0 || this.id == selectedValue) {
                    selection = this.id;
                }
            });
            var $select = $(select);
            $.each(urls, function() {
                $select.append($("<option/>", {
                    value: this.id,
                    text: this.value,
                    selected: selection == this.id
                }));
            });
            if ($select.data("select2")) {
                $select.select2("val", selection);
            }
        });
    }
    function createSelectElement(name, elClass, elSize, ruleid) {
        var select = document.createElement("select");
        select.setAttribute("name", name);
        select.setAttribute("class", elClass);
        select.setAttribute("size", elSize);
        select.setAttribute("data-action", name.replace(/\[\d+\]/, ""));
        if (ruleid != null) {
            select.setAttribute("data-ruleid", ruleid);
        }
        return select;
    }
    function replaceElement(oldOne, newOne) {
        var $newOne = $(newOne);
        $(oldOne).parent().html($newOne);
        if ($newOne.is("select")) {
            initSelect2($newOne);
        }
    }
    function replaceElements(newElements, $parentNode) {
        if (newElements.length > 0) {
            var numOfCellsInGrid = 12;
            var clsName = "col-sm-" + Math.round(numOfCellsInGrid / newElements.length);
            $parentNode = $parentNode.parent();
            $parentNode.empty();
            $.each(newElements, function() {
                var $element = $(this);
                var $divItemWrapper = $("<div>").addClass(clsName);
                $divItemWrapper.append($element);
                $parentNode.append($divItemWrapper);
                if ($element.is("select")) {
                    initSelect2($element);
                }
            });
        }
    }
    function initSelect2($select) {
        AGN.Lib.CoreInitializer.run("select", $select.parent());
    }
    function appendOption(select, selectedValue, value, text) {
        var $option = $("<option/>", {
            value: value,
            text: text,
            selected: selectedValue.localeCompare(value) == 0
        });
        $option.appendTo($(select));
        return $option;
    }
    function createInputElement(name, value, elClass) {
        var input = document.createElement("input");
        input.setAttribute("type", "text");
        input.setAttribute("name", name);
        input.setAttribute("value", value);
        input.setAttribute("class", elClass);
        return input;
    }
    function extractValues(object) {
        var values = [];
        for (var k in object) {
            if (object.hasOwnProperty(k)) {
                values.push(object[k]);
            }
        }
        return values;
    }
    AGN.Lib.RuleService = {
        changedColumn: changedColumn,
        resetPrimaryOperators: resetPrimaryOperators,
        resetMailingUrls: resetMailingUrls,
        updateMailingLinksCache: updateMailingLinksCache,
        switchTo: {
            operators: {
                mod: switchToModOperator,
                is: switchToIsOperator
            },
            types: {
                string: switchToStringType,
                mail: switchToMailType,
                gender: switchToGender,
                date: switchToDateType,
                mailing: switchToMailingType,
                mailingLinks: switchToMailingLinksType,
                intervalMailing: switchToIntervalMailingType
            }
        },
        configure: configure
    };
})();

(function() {
    var SearchForm, Form = AGN.Lib.Form;
    SearchForm = function($form) {
        Form.apply(this, [ $form ]);
    };
    SearchForm.prototype = Object.create(Form.prototype);
    SearchForm.prototype.updateHtml = function(resp) {
        var $newSearchResults = $(resp).find("[data-form-content]"), $searchResults = this.$form.find("[data-form-content]");
        $searchResults.html($newSearchResults.html());
        this.handleMessages(resp);
        this.initFields($searchResults);
        AGN.Lib.Controller.init($searchResults);
        AGN.runAll($searchResults);
        $searchResults.trigger("scrollTo", $searchResults);
    };
    AGN.Lib.SearchForm = SearchForm;
    AGN.Opt.Forms["search"] = SearchForm;
})();

(function() {
    var Select;
    Select = function($select) {
        this.$select = $select;
        this.select = $select[0];
        this.api = function() {
            args = Array.prototype.slice.call(arguments, 0);
            $select.select2.apply($select, args);
        };
    };
    Select.get = function($needle) {
        var $select, selectObj;
        $select = $needle;
        selectObj = $select.data("_select");
        if (!selectObj) {
            selectObj = new Select($select);
            $select.data("_select", selectObj);
        }
        return selectObj;
    };
    Select.prototype.map = function() {
        var self = this;
        return _.reduce(self.values(), function(obj, val) {
            obj[val] = self.$select.find("option[value='" + val + "']").html();
            return obj;
        }, {});
    };
    Select.prototype.values = function() {
        return _.map(this.$select.find("option"), function(el) {
            return $(el).val();
        });
    };
    Select.prototype.hasOption = function(value) {
        const values = this.values();
        return values.indexOf(value) !== -1;
    };
    Select.prototype.clear = function() {
        this.api("val", "");
    };
    Select.prototype.selectNext = function() {
        const values = this.values();
        const selectedValue = this.getSelectedValue();
        const nextIndex = values.indexOf(selectedValue) + 1;
        if (nextIndex < values.length) {
            this.selectValue(values[nextIndex]);
        }
    };
    Select.prototype.selectValue = function(val) {
        this.api("val", val);
    };
    Select.prototype.getFirstValue = function() {
        return this.$select.find("option:first").val();
    };
    Select.prototype.selectFirstValue = function() {
        this.api("val", this.getFirstValue());
    };
    Select.prototype.selectValueOrSelectFirst = function(values) {
        var allValuesFound = false, valuesAvailable = this.values();
        if (!_.isArray(values)) {
            values = [ values ];
        }
        allValuesFound = _.every(values, function(val) {
            return valuesAvailable.indexOf(val + "") != -1;
        });
        if (allValuesFound && values.length != 0) {
            this.selectValue(values);
        } else {
            this.selectFirstValue();
        }
    };
    Select.prototype.resetOptions = function() {
        this.$select.html("");
    };
    Select.prototype.setOptions = function(data) {
        var options;
        options = _.reduce(data, function(html, option) {
            html += '<option value="' + option.id + '">' + option.text + "</option>";
            return html;
        }, "");
        this.$select.html(options);
    };
    Select.prototype.addFormattedOption = function(option) {
        this.$select.append(option);
    };
    Select.prototype.getSelectedValue = function() {
        var value = this.$select.val();
        return value ? value : "";
    };
    AGN.Lib.Select = Select;
})();

(function() {
    var StaticForm, Form = AGN.Lib.Form;
    StaticForm = function($form) {
        Form.apply(this, [ $form ]);
    };
    StaticForm.prototype = Object.create(Form.prototype);
    StaticForm.prototype.jqxhr = function() {
        return this.form.submit();
    };
    StaticForm.prototype.submit = function() {
        var self = this, fieldsMissing = _.merge({}, this._data, this._dataNextRequest);
        if (!this.valid()) {
            this.handleErrors();
            return false;
        }
        this.$form.trigger("form:submit");
        _.each(fieldsMissing, function(value, field) {
            var $input = $('<input type="hidden" name="' + field + '"/>');
            $input.val(value);
            $input.appendTo(self.$form);
        });
        this._dataNextRequest = {};
        this.$form.submit();
        return $.Deferred().promise();
    };
    AGN.Lib.StaticForm = StaticForm;
    AGN.Opt.Forms["static"] = StaticForm;
})();

(function($) {
    var get, set, deleteByKey, saveChosenFields, restoreChosenFields, readCookie, currentStorage, Storage;
    Storage = function(type) {
        function createCookie(name, value, days) {
            var date, expires;
            if (days) {
                date = new Date();
                date.setTime(date.getTime() + days * 24 * 60 * 60 * 1e3);
                expires = "; expires=" + date.toGMTString();
            } else {
                expires = "";
            }
            document.cookie = name + "=" + value + expires + "; path=/";
        }
        function setData(data) {
            data = JSON.stringify(data);
            if (type == "session") {
                window.name = data;
            } else {
                createCookie("localStorage", data, 365);
            }
        }
        function clearData() {
            if (type == "session") {
                window.name = "";
            } else {
                createCookie("localStorage", "", 365);
            }
        }
        function getData() {
            var data = type == "session" ? window.name : readCookie("localStorage");
            try {
                return JSON.parse(data);
            } catch (e) {
                console.warn("Could not parse storage data: " + data + " cause: " + e);
            }
            return {};
        }
        var data = getData();
        return {
            length: 0,
            clear: function() {
                data = {};
                this.length = 0;
                clearData();
            },
            getItem: function(key, ignoreCache) {
                if (ignoreCache === true) {
                    var realData = getData();
                    return realData[key] === undefined ? null : realData[key];
                } else {
                    return data[key] === undefined ? null : data[key];
                }
            },
            key: function(i) {
                var ctr = 0;
                for (var k in data) {
                    if (ctr == i) return k; else ctr++;
                }
                return null;
            },
            removeItem: function(key) {
                delete data[key];
                this.length--;
                setData(data);
            },
            setItem: function(key, value) {
                data[key] = value + "";
                this.length++;
                setData(data);
            }
        };
    };
    readCookie = function(name) {
        var nameEQ = name + "=", ca = document.cookie.split(";"), i, c;
        for (i = 0; i < ca.length; i++) {
            c = ca[i];
            while (c.charAt(0) == " ") {
                c = c.substring(1, c.length);
            }
            if (c.indexOf(nameEQ) == 0) {
                return c.substring(nameEQ.length, c.length);
            }
        }
        return null;
    };
    try {
        if (!window.localStorage) {
            currentStorage = new Storage("local");
        } else {
            currentStorage = window.localStorage;
        }
    } catch (e) {
        currentStorage = new Storage("local");
    }
    get = function(key) {
        try {
            var result = currentStorage.getItem(generateKeyForAdmin(key));
            if (result) {
                return JSON.parse(result);
            }
        } catch (e) {
            console.warn("Could not get Storage key: " + key + " cause: " + e);
        }
        return undefined;
    };
    set = function(key, value) {
        try {
            value = JSON.stringify(value);
            currentStorage.setItem(generateKeyForAdmin(key), value);
        } catch (e) {
            console.warn("Could not set Storage key:value " + key + ":" + value + " cause: " + e);
        }
    };
    deleteByKey = function(key) {
        try {
            currentStorage.removeItem(generateKeyForAdmin(key));
        } catch (e) {
            console.warn("Could not remove Storage key:" + key + " cause: " + e);
        }
    };
    saveChosenFields = function(selector) {
        selector.each(function() {
            var $e = $(this);
            if ($e.is("[data-stored-field]") && ($e.is("input") || $e.is("select"))) {
                saveStoredField($e);
            } else {
                $e.find("[data-stored-field]").each(function() {
                    saveStoredField($(this));
                });
            }
        });
    };
    restoreChosenFields = function(selector) {
        var wasChanged = false;
        selector.each(function() {
            var $e = $(this);
            if ($e.is("[data-stored-field]") && ($e.is("input") || $e.is("select"))) {
                if (restoreStoredField($e)) {
                    wasChanged = true;
                }
            } else {
                $e.find("[data-stored-field]").each(function() {
                    if (restoreStoredField($(this))) {
                        wasChanged = true;
                    }
                });
            }
        });
        return wasChanged;
    };
    function saveStoredField(field) {
        var scope = field.data("stored-field") | "";
        var property = field.prop("name");
        if (property != undefined) {
            var value = undefined;
            if (field.prop("type") == "checkbox") {
                value = field.is(":checked");
            } else if (field.is("input") || field.is("select")) {
                value = field.val();
            }
            if (value != undefined) {
                set(generateStoredFieldKeyForAdmin(property, scope), value);
            }
        }
    }
    function restoreStoredField(field) {
        var scope = field.data("stored-field") | "";
        var wasChanged = false;
        var property = field.prop("name");
        if (property != undefined) {
            var type = field.prop("type") || field.prop("type");
            var value = get(generateStoredFieldKeyForAdmin(property, scope));
            if (value === undefined) {
                value = get(generateStoredFieldKey(property, scope));
                if (value === undefined) {
                    return false;
                }
                set(generateStoredFieldKeyForAdmin(property, scope), value);
            }
            if (type == "radio") {
                if (field.val() !== value && field.is(":checked")) {
                    field.prop("checked", false);
                    return true;
                } else if (field.val() == value && !field.is(":checked")) {
                    field.prop("checked", true);
                    return true;
                }
            } else if (type == "checkbox") {
                if (field.prop("checked") !== value) {
                    field.prop("checked", value);
                    wasChanged = true;
                }
            } else if (type == "select-one") {
                var exist = false;
                field.find("option").each(function() {
                    if ($(this).val() == value) {
                        exist = true;
                        return false;
                    }
                });
                if (exist && field.val() !== value) {
                    field.val(value).change();
                    wasChanged = true;
                }
            } else if (type == "select-multiple") {
                var existed = [];
                var currentValue = field.value();
                field.find("option").each(function() {
                    var optionSelector = $(this);
                    $.each(value, function(i, e) {
                        if (optionSelector.val() == e) {
                            existed.push(e);
                        }
                    });
                });
                existed.sort();
                currentValue.sort();
                var equals = true;
                if (existed.length != currentValue.length) equals = false;
                for (var i = 0; i < existed.length; ++i) {
                    if (existed[i] !== currentValue[i]) equals = false;
                }
                if (!equals) {
                    field.val(existed).change();
                    wasChanged = true;
                }
            } else if (type == "textarea" || type == "text") {
                if (field.val() !== value) {
                    field.val(value);
                    wasChanged = true;
                }
            }
        }
        return wasChanged;
    }
    function generateStoredFieldKey(property, scope) {
        var key = "stored_field_";
        if (property) {
            key = key + property;
        }
        if (scope) {
            key = key + "_" + scope;
            return key;
        }
        return undefined;
    }
    function generateStoredFieldKeyForAdmin(property, scope) {
        var key = generateStoredFieldKey(property, scope);
        if (key) {
            return generateKeyForAdmin(key);
        } else {
            return key;
        }
    }
    function generateKeyForAdmin(key) {
        if (window.adminId) {
            return window.adminId + "-" + key;
        }
        return key;
    }
    AGN.Lib.Storage = {
        get: get,
        set: set,
        delete: deleteByKey,
        readCookie: readCookie,
        saveChosenFields: saveChosenFields,
        restoreChosenFields: restoreChosenFields
    };
})(jQuery);

(function() {
    var Storage = AGN.Lib.Storage;
    var init, show, hide, getGroupId;
    init = function($trigger) {
        var target = $trigger.data("toggle-tab"), group = getGroupId($trigger, target), conf = Storage.get("toggle_tab" + group) || {}, $target = $(target);
        if (typeof $target.data("tab-show") !== "undefined") {
            conf.hidden = false;
            $target.data("tab-show", undefined);
        }
        if (typeof $target.data("tab-hide") !== "undefined") {
            conf.hidden = true;
            $target.data("tab-hide", undefined);
        }
        if (conf.hidden === false || conf.hidden !== true && $target.is(":visible")) {
            show($trigger);
        }
    };
    show = function($trigger) {
        var $siblings = $trigger.parents("ul").find("[data-toggle-tab]").not($trigger), target = $trigger.data("toggle-tab"), group = getGroupId($trigger, target), $target = $(target), $icon = $trigger.find(".tab-toggle"), $extends = $($trigger.data("extends-tab"));
        _.each($siblings, function(sibling) {
            hide($(sibling));
        });
        $trigger.parent().addClass("active");
        $icon.removeClass("icon-angle-down").addClass("icon-angle-up");
        $target.removeClass("hidden");
        $extends.removeClass("hidden");
        $target.trigger("tile:show");
        Storage.set("toggle_tab" + group, {
            hidden: false
        });
        AGN.Lib.CoreInitializer.run("load", $target);
    };
    hide = function($trigger) {
        var target = $trigger.data("toggle-tab"), group = getGroupId($trigger, target), $icon = $trigger.find(".tab-toggle");
        $trigger.parent().removeClass("active");
        $icon.removeClass("icon-angle-up").addClass("icon-angle-down");
        $(target).addClass("hidden");
        $(target).trigger("tile:hide");
        Storage.set("toggle_tab" + group, {
            hidden: true
        });
    };
    toggle = function($trigger) {
        var target = $trigger.data("toggle-tab"), $target = $(target);
        if ($target.is(":visible")) {
            hide($trigger);
        } else {
            show($trigger);
        }
    };
    getGroupId = function($trigger, defaultValue) {
        var group = $trigger.data("tab-group");
        if (group) {
            return "/" + group;
        } else {
            return defaultValue;
        }
    };
    AGN.Lib.Tab = {
        init: init,
        show: show,
        hide: hide,
        toggle: toggle
    };
})();

(function() {
    var Popover = AGN.Lib.Popover;
    var Table, template;
    template = '<div class="pagination-top"></div>' + '<div class="ag-theme-bootstrap" style="height: calc(100% - 106px); width: 100%"></div>' + '<div class="pagination-bottom"></div>';
    Table = function($el, columns, data, options) {
        var self = this;
        this.$el = $el;
        this.$el.html(template);
        this.$el.data("_table", self);
        this.$paginationTop = this.$el.find(".pagination-top");
        this.$paginationBottom = this.$el.find(".pagination-bottom");
        columns.forEach(function(column) {
            if (column.cellRenderer) {
                column.cellRenderer = AGN.Opt.TableCellRenderers[column.cellRenderer];
            }
            if (column.headerComponent) {
                column.headerComponent = AGN.Opt.TableHeaderComponents[column.headerComponent];
            }
            if (column.comparator) {
                column.comparator = AGN.Opt.Table["comparators"][column.comparator];
            }
        });
        this.gridOptions = _.merge({
            autoSizePadding: 4,
            columnDefs: columns,
            enableSorting: true,
            accentedSort: true,
            enableFilter: true,
            enableColResize: true,
            pagination: true,
            showRecordsCount: true,
            filtersDescription: {
                enabled: false,
                templateName: "",
                templateParams: {}
            },
            paginationPageSize: 100,
            rowSelection: "multiple",
            unSortIcon: true,
            onCellClicked: function(cell) {
                switch (cell.colDef.cellAction) {
                  case "select":
                    cell.node.setSelected(!cell.node.isSelected());
                    break;

                  case "goTo":
                    var url = cell.data.show;
                    if (url) {
                        if (cell.event.ctrlKey) {
                            window.open(url, "_blank");
                        } else {
                            window.location.href = url;
                        }
                    }
                    break;
                }
            },
            onCellMouseOver: function(cell) {
                if (cell.colDef.textInPopoverIfTruncated === true) {
                    var target = cell.event.target, isTruncated = target.clientWidth < target.scrollWidth;
                    if (isTruncated) {
                        getPopoverForCell(cell).show();
                    }
                }
            },
            onCellMouseOut: function(cell) {
                if (cell.colDef.textInPopoverIfTruncated === true) {
                    var popover = Popover.get($(cell.event.target));
                    if (popover) {
                        popover.hide();
                    }
                }
            },
            suppressRowClickSelection: true,
            headerHeight: 41,
            rowHeight: 34,
            suppressPaginationPanel: true,
            onPaginationChanged: function() {
                self.renderPagination();
            },
            defaultColDef: {
                headerComponentParams: {
                    template: '<div class="ag-cell-label-container" role="presentation">' + '  <span ref="eMenu" class="ag-header-icon ag-header-cell-menu-button"></span>' + '  <div ref="eLabel" class="ag-header-cell-label" role="presentation">' + '    <span ref="eSortAsc" class="ag-header-icon ag-sort-ascending-icon" ></span>' + '    <span ref="eSortDesc" class="ag-header-icon ag-sort-descending-icon" ></span>' + '    <span ref="eSortNone" class="ag-header-icon ag-sort-none-icon" ></span>' + '    <span ref="eText" class="ag-header-cell-text" role="columnheader"></span>' + '    <span ref="eFilter" class="ag-header-icon ag-filter-icon"></span>' + '    <span ref="eSortOrder" class="ag-header-icon ag-sort-order" ></span>' + "  </div>" + "</div>"
                },
                filterParams: {
                    clearButton: true
                }
            },
            columnTypes: {
                numberColumn: {
                    width: 83,
                    filter: "agNumberColumnFilter",
                    comparator: AGN.Lib.TableNumberComparator
                },
                dateColumn: {
                    filter: AGN.Lib.TableDateFilter
                },
                setColumn: {
                    filter: AGN.Lib.TableSetFilter
                },
                bulkSelectColumn: {
                    headerName: "",
                    editable: false,
                    checkboxSelection: true,
                    headerCheckboxSelection: true,
                    headerComponent: AGN.Opt.TableHeaderComponents["NoLabelHeader"],
                    suppressResize: true,
                    suppressMenu: true,
                    suppressSorting: true,
                    cellAction: "select",
                    suppressSizeToFit: true,
                    cellStyle: {
                        textAlign: "center"
                    }
                },
                deleteColumn: {
                    headerName: "",
                    editable: false,
                    suppressResize: true,
                    suppressMenu: true,
                    suppressSorting: true,
                    cellAction: null,
                    cellRenderer: AGN.Opt.TableCellRenderers["DeleteCellRenderer"],
                    suppressSizeToFit: true,
                    "button-tooltip": t("defaults.delete")
                },
                textCaseInsensitiveColumn: {
                    comparator: AGN.Lib.TableCaseInsensitiveComparator
                }
            },
            icons: {
                menu: '<i class="icon icon-filter"/>',
                filter: '<i class="icon icon-filter"/>',
                columns: '<i class="icon icon-handshake-o"/>',
                sortAscending: '<i class="icon icon-sort-asc"/>',
                sortDescending: '<i class="icon icon-sort-desc"/>',
                checkboxChecked: '<i class="icon icon-check-square-o"/>',
                checkboxUnchecked: '<i class="icon icon-square-o"/>',
                checkboxIndeterminate: '<i class="icon icon-square-o"/>',
                checkboxCheckedReadOnly: '<i class="icon icon-check-square-o"/>',
                checkboxUncheckedReadOnly: '<i class="icon icon-square-o"/>',
                checkboxIndeterminateReadOnly: '<i class="icon icon-square-o"/>',
                sortUnSort: '<i class="icon-fa5 icon-fa5-sort"/>'
            },
            localeText: window.I18n.tables
        }, options || {});
        if (!this.gridOptions.showRecordsCount && !this.gridOptions.pagination) {
            this.$el.find(".ag-theme-bootstrap").height(this.gridOptions.autoHeight ? "auto" : this.$el.parent().height());
        }
        this.grid = new agGrid.Grid(this.$el.find(".ag-theme-bootstrap").get(0), this.gridOptions);
        this.api = this.gridOptions.api;
        this.columnApi = this.gridOptions.columnApi;
        this.api.setRowData(data);
        this.redraw();
    };
    Table.prototype.renderPagination = function() {
        var api = this.api, currentPage, totalPages, pageSelects, paginationData, paginationTopTemplate = AGN.Lib.Template.prepare("table-controls-top");
        paginationBottomTemplate = AGN.Lib.Template.prepare("table-controls-bottom");
        if (!api) {
            return;
        }
        currentPage = api.paginationGetCurrentPage() + 1;
        totalPages = api.paginationGetTotalPages();
        pageSelects = [ currentPage ];
        _.times(5, function(i) {
            if (currentPage - (i + 1) > 0) {
                pageSelects.unshift(currentPage - (i + 1));
            }
            if (currentPage + (i + 1) <= totalPages) {
                pageSelects.push(currentPage + (i + 1));
            }
        });
        paginationData = {
            pagination: this.gridOptions.pagination,
            showRecordsCount: this.gridOptions.showRecordsCount,
            currentPage: currentPage,
            totalPages: totalPages,
            itemStart: api.paginationGetPageSize() * (currentPage - 1) + 1,
            itemEnd: currentPage == totalPages ? api.paginationGetRowCount() : api.paginationGetPageSize() * currentPage,
            itemTotal: api.paginationGetRowCount(),
            pageSelects: pageSelects
        };
        this.$paginationTop.html(paginationTopTemplate(paginationData));
        var filtersDescription = this.gridOptions.filtersDescription;
        if (filtersDescription.enabled && filtersDescription.templateName) {
            this.$paginationTop.find("#filtersDescription").html(AGN.Lib.Template.text(filtersDescription.templateName), filtersDescription.templateParams);
        }
        this.$paginationBottom.html(paginationBottomTemplate(paginationData));
        this.api.redrawRows();
    };
    Table.prototype.redraw = function() {
        var columnsToAutoResize = this.columnApi.getAllDisplayedColumns().filter(function(column) {
            return column.getColDef().suppressSizeToFit === true;
        }).map(function(column) {
            return column.getColId();
        });
        if (columnsToAutoResize.length) {
            this.columnApi.autoSizeColumns(columnsToAutoResize);
        }
        this.api.sizeColumnsToFit();
    };
    Table.get = function($needle) {
        var $table, tableObj;
        $table = Table.getWrapper($needle);
        tableObj = $table.data("_table");
        return tableObj;
    };
    Table.getWrapper = function($needle) {
        var $table;
        $table = $($needle.data("table-body"));
        if ($table.length == 0) {
            $table = $needle.closest(".js-data-table-body");
        }
        return $table;
    };
    AGN.Lib.Table = Table;
    function getPopoverForCell(cell) {
        var $cellTarget = $(cell.event.target), popover = Popover.get($cellTarget);
        if (!popover) {
            return Popover.new($cellTarget, {
                trigger: "manual",
                container: "body",
                content: cell.value
            });
        }
        return popover;
    }
})();

(function() {
    var TargetGroup;
    TargetGroup = function() {};
    TargetGroup.getComplexityColor = function(complexity) {
        var color;
        if (complexity < 10) {
            color = "green";
        } else if (complexity >= 10 && complexity < 17) {
            color = "yellow";
        } else {
            color = "red";
        }
        return color;
    };
    AGN.Lib.TargetGroup = TargetGroup;
})();

(function() {
    const CSRF = AGN.Lib.CSRF;
    const templates = AGN.Opt.Templates;
    function prepare(name) {
        if (name in templates) {
            const templateFunc = _.template(templates[name]);
            return createTemplateDecorator(templateFunc);
        }
        throw new Error("There's no template `" + name + "` registered");
    }
    function createTemplateDecorator(templateFunc) {
        return function() {
            const template = templateFunc.apply(this, arguments);
            return CSRF.updateTokenInDOM(template, true);
        };
    }
    function text(name, parameters) {
        return prepare(name)(parameters);
    }
    function dom(name, parameters) {
        return $(text(name, parameters));
    }
    AGN.Lib.Template = {
        prepare: prepare,
        text: text,
        dom: dom
    };
})();

(function() {
    const Storage = AGN.Lib.Storage;
    var init, toggle, trigger, show, hide;
    init = function($trigger) {
        const target = $trigger.data("toggle-tile"), conf = Storage.get("toggle_tile" + target);
        if (!conf) {
            const defaultState = $trigger.data("toggle-tile-default-state");
            if (typeof defaultState !== "undefined") {
                if (defaultState === "open") {
                    showTile($trigger, false);
                } else {
                    hideTile($trigger, false);
                }
            }
            return;
        }
        if (conf.hidden) {
            hide($trigger);
        } else {
            show($trigger);
        }
    };
    toggle = function($trigger) {
        const $target = $($trigger.data("toggle-tile"));
        if ($target.hasClass("hidden")) {
            show($trigger);
        } else {
            hide($trigger);
        }
    };
    show = function($trigger) {
        showTile($trigger, true);
    };
    function showTile($trigger, updateStorage) {
        const $icon = $trigger.find(".icon"), target = $trigger.data("toggle-tile"), $target = $(target);
        $target.removeClass("hidden");
        $icon.addClass("icon-angle-up");
        $icon.removeClass("icon-angle-down");
        if (updateStorage) {
            Storage.set("toggle_tile" + target, {
                hidden: false
            });
        }
        AGN.Lib.CoreInitializer.run("load", $target);
    }
    trigger = function($needle) {
        return $needle.closest(".tile").find("[data-toggle-tile]");
    };
    hide = function($trigger) {
        hideTile($trigger, true);
    };
    function hideTile($trigger, updateStorage) {
        const $icon = $trigger.find(".icon"), target = $trigger.data("toggle-tile");
        $(target).addClass("hidden");
        $icon.addClass("icon-angle-down");
        $icon.removeClass("icon-angle-up");
        if (updateStorage) {
            Storage.set("toggle_tile" + target, {
                hidden: true
            });
        }
    }
    AGN.Lib.Tile = {
        toggle: toggle,
        init: init,
        show: show,
        hide: hide,
        trigger: trigger
    };
})();

(function() {
    var Tooltip = {}, Template = AGN.Lib.Template, Helpers = AGN.Lib.Helpers;
    var createTitle = function() {
        var templateWithTitle = Template.prepare("tooltip-message-with-title");
        var templateJustContent = Template.prepare("tooltip-message-just-content");
        return function(title, text) {
            if (title) {
                return templateWithTitle({
                    title: title,
                    content: text
                });
            }
            return templateJustContent({
                content: text
            });
        };
    }();
    var createTemplate = function() {
        var make = Template.prepare("tooltip-template");
        return function(tooltipStyle, arrowStyle, innerStyle) {
            return make({
                tooltipStyle: tooltipStyle,
                arrowStyle: arrowStyle,
                innerStyle: innerStyle
            });
        };
    }();
    function getTooltipOptions(title, style) {
        return {
            title: title,
            container: "body",
            template: createTemplate(style)
        };
    }
    function getTooltipHelpOptions(title, text, style) {
        return {
            title: createTitle(title, text),
            container: "body",
            html: true,
            placement: "auto top",
            template: createTemplate(style, "helper-popup-arrow", "helper-popup")
        };
    }
    Tooltip.options = function($e) {
        var options = {};
        if ($e.is("[data-tooltip]")) {
            var title = $e.data("tooltip");
            var source = $e.data("tooltip-src");
            if (source) {
                title = Template.text(source, {
                    element: $e
                });
            }
            options = getTooltipOptions(title, $e.data("tooltip-style"));
        } else if ($e.is("[data-tooltip-help]")) {
            options = getTooltipHelpOptions($e.data("tooltip-help"), $e.data("tooltip-help-text"), $e.data("tooltip-style"));
        }
        return $.extend(options, Helpers.objFromString($e.data("tooltip-options")));
    };
    Tooltip.create = function($e, options) {
        Tooltip.remove($e);
        $e.bsTooltip(options);
        $e.on({
            "dragstart.tooltip": function() {
                $e.bsTooltip("hide");
                $e.bsTooltip("disable");
            },
            "dragstop.tooltip": function() {
                $e.bsTooltip("enable");
            }
        });
        $e.on("remove", function() {
            Tooltip.remove($e);
        });
    };
    Tooltip.remove = function($e) {
        $e.bsTooltip("hide");
        $e.bsTooltip("destroy");
        $e.off("dragstart.tooltip dragstop.tooltip");
    };
    Tooltip.setEnabled = function($e, isEnabled) {
        if (isEnabled || isEnabled === undefined) {
            $e.bsTooltip("enable");
        } else {
            $e.bsTooltip("hide");
            $e.bsTooltip("disable");
        }
    };
    Tooltip.setShown = function($e, isShown) {
        if (isShown || isShown === undefined) {
            $e.bsTooltip("show");
        } else {
            $e.bsTooltip("hide");
        }
    };
    Tooltip.createTip = function($e, text, style) {
        Tooltip.create($e, getTooltipOptions(text, style));
    };
    Tooltip.createHelpTip = function($e, title, text, style) {
        Tooltip.create($e, getTooltipHelpOptions(title, text, style));
    };
    AGN.Lib.Tooltip = Tooltip;
})();

(function() {
    var Action = AGN.Lib.Action;
    var TrackableLinkExtensions;
    var extensionRowTemplate;
    var $table;
    TrackableLinkExtensions = function() {};
    TrackableLinkExtensions.prototype.load = function(extensions, table) {
        $table = table;
        extensionRowTemplate = _.template(AGN.Opt.Templates["trackablelink-extension-table-row"]);
        _.each(extensions, function(extension, index) {
            insertExtension(index, extension.name, extension.value);
        });
        appendLastRow("", "");
    };
    TrackableLinkExtensions.prototype.collect = function() {
        if ($table && $table.length) {
            return _.map($table.find("[data-extension-row]"), function(row) {
                var $row = $(row);
                return {
                    name: getName($row),
                    value: getValue($row)
                };
            }).filter(function(extension) {
                return extension.name && extension.value;
            });
        }
        return [];
    };
    Action.new({
        click: "[data-extension-add]",
        enterdown: "[data-extension-row]"
    }, function() {
        this.event.preventDefault();
        if (isUniqueRow("", "")) {
            replaceNewButtonWithDeleteButton();
            appendLastRow("", "");
        }
        $table.find("[data-extension-name]:last").focus();
    });
    Action.new({
        click: "[data-extension-delete]"
    }, function() {
        var currentRow = this.el.closest("tr");
        currentRow.remove();
    });
    Action.new({
        click: "[data-add-default-extensions]"
    }, function() {
        var lastRow = $table.find("tr:last");
        if (getName(lastRow) == "" && getValue(lastRow) == "") {
            lastRow.remove();
        } else {
            replaceNewButtonWithDeleteButton();
        }
        _.each(AGN.Opt.DefaultExtensions, function(extension) {
            appendLastRow(extension.name, extension.value);
        });
        appendLastRow("", "");
    });
    function insertExtension(index, name, value) {
        if (isUniqueRow(name, value)) {
            $table.append(extensionRowTemplate({
                index: index,
                name: name,
                value: value
            }));
        }
    }
    function appendLastRow(name, value) {
        var lastIndex = $table.find("[data-extension-row]:last-child").data("extension-row") || 0;
        insertExtension(++lastIndex, name, value);
    }
    function isUniqueRow(name, value) {
        var unique = true;
        _.each($table.find("[data-extension-row]"), function(row) {
            var $row = $(row);
            if (unique) {
                if (getName($row) == name && getValue($row) == value) {
                    unique = false;
                }
            }
        });
        return unique;
    }
    function replaceNewButtonWithDeleteButton() {
        var newBtn = $table.find("#newExtensionBtn");
        newBtn.after("<a href='#' class='btn btn-regular btn-alert' data-extension-delete>" + "<i class='icon icon-trash-o'></i></a>");
        newBtn.remove();
    }
    function getName(row) {
        return row.find("[data-extension-name]").val();
    }
    function getValue(row) {
        return row.find("[data-extension-value]").val();
    }
    AGN.Lib.TrackableLinkExtensions = TrackableLinkExtensions;
})();

(function() {
    AGN.Lib.Truncate = {
        run: function($container, truncateSelector) {
            var width, spaceOccupied;
            width = $container.width();
            spaceOccupied = _.reduce($container.children().not(truncateSelector), function(total, el) {
                return total + $(el).outerWidth(true);
            }, 0);
            spaceOccupied = spaceOccupied + ($(truncateSelector).outerWidth(true) - $(truncateSelector).outerWidth());
            spaceOccupied = spaceOccupied * .05 > 5 ? 1.05 * spaceOccupied : spaceOccupied + 5;
            spaceOccupied = spaceOccupied > width ? width : spaceOccupied;
            $container.children(truncateSelector).css({
                "max-width": width - spaceOccupied + "px",
                overflow: "hidden"
            });
        }
    };
})();

(function() {
    var Validator;
    Validator = function(handlers) {
        if (handlers.init) {
            handlers.init();
            delete handlers.init;
        }
        return $.extend(this, handlers);
    };
    Validator.exists = function(name) {
        return AGN.Opt.Validators.hasOwnProperty(name);
    };
    Validator.get = function(name) {
        return Validator.exists(name) ? AGN.Opt.Validators[name] : null;
    };
    Validator.new = function(name, handlers) {
        if (Validator.exists(name)) {
            console.debug("Validator with name `" + name + "` was overridden");
        }
        var validator = new Validator(handlers);
        AGN.Opt.Validators[name] = validator;
        return validator;
    };
    Validator.prototype.valid = function() {
        return true;
    };
    Validator.prototype.errors = function() {
        return [];
    };
    AGN.Lib.Validator = Validator;
})();

(function() {
    var init, trigger, initClasses;
    init = function() {
        var $view = $("[data-view]:checked"), conf = AGN.Lib.Storage.get("view_" + $view.data("view"));
        if (conf) {
            $('[data-view][value="' + conf.view + '"]').prop("checked", true);
        } else {
            conf = {
                view: $view.val()
            };
        }
        initClasses(conf.view);
    };
    trigger = function($trigger) {
        var type = $trigger.val();
        initClasses(type);
        AGN.Lib.Storage.set("view_" + $trigger.data("view"), {
            view: type
        });
    };
    initClasses = function(type) {
        _.each($("[data-view-" + type + "]"), function(target) {
            var $target = $(target);
            $target.attr("class", $target.data("view-" + type));
        });
        $(window).trigger("resize");
        AGN.Lib.CoreInitializer.run("load");
        if ($("#preview").length) {
            controlPreviewDisplaying(type);
        }
    };
    function removePreviewInnerScroll() {
        $("#preview-contents").css("height", "");
        $(".mailing-preview-wrapper").css("overflow-y", "");
    }
    function addPreviewInnerScroll($previewContainer) {
        $previewContainer.css({
            "flex-grow": "1",
            "overflow-y": "auto"
        });
    }
    function makePreviewSticky(isEmc) {
        var anyFirstTileTop = $(".tile").first().offset().top;
        $('[data-load-target="#preview"]').parent().css({
            position: "sticky",
            top: (isEmc ? 15 : anyFirstTileTop) + "px"
        });
    }
    function previewFrameLoaded($mailingPreviewWrapper) {
        return $mailingPreviewWrapper.length && $mailingPreviewWrapper.find("iframe").length;
    }
    function controlPreviewDisplaying(type) {
        var isEmc = $("#gt-wrapper").exists();
        var $previewContainer = $(".mailing-preview-wrapper");
        if (!$previewContainer.length && isEmc) {
            $previewContainer = $("#preview").find(".tile-content-padded");
        }
        if (previewFrameLoaded($previewContainer)) {
            if (type === "block") {
                removePreviewInnerScroll($previewContainer);
            } else if (type === "split") {
                $previewContainer.css("height", "0px");
                makePreviewSticky(isEmc);
                setPreviewTileHeight($previewContainer, isEmc);
                addPreviewInnerScroll($previewContainer, isEmc);
                $previewContainer.css("height", "");
            }
        }
    }
    function setPreviewTileHeight($previewContainer, isEmc) {
        var $previewTileContent = $previewContainer.parent();
        $previewTileContent.css({
            display: "flex",
            "flex-direction": "column",
            height: "calc(100vh - " + Math.ceil($previewTileContent.offset().top - $(window).scrollTop() + (isEmc ? 45 : 10)) + "px)",
            "min-height": "200px"
        });
    }
    AGN.Lib.View = {
        init: init,
        trigger: trigger
    };
})();

(function() {
    var Storage = AGN.Lib.Storage;
    var WebStorage = {};
    WebStorage.get = function(k) {
        var key = "web-storage#" + $.trim(k);
        try {
            return Storage.get(key);
        } catch (e) {
            console.error(e);
        }
        return null;
    };
    WebStorage.set = function(k, v) {
        Storage.set("web-storage#" + $.trim(k), v);
    };
    WebStorage.extend = function(k, v) {
        var value = WebStorage.get(k);
        if (value != null) {
            value = $.extend(value, v);
        } else {
            value = v;
        }
        WebStorage.set(k, value);
        return value;
    };
    AGN.Lib.WebStorage = WebStorage;
})();

(function() {
    var ICONS_CONFIG = {
        actionbased_mailing: {
            icons: {
                inactive: "icon_actionbased_mailing_g.png",
                active: "icon_actionbased_mailing_l.png",
                dialog: "icon_actionbased_mailing_s.png"
            },
            anchors: [ [ .07, .5, -1, 0 ], [ .5, .22, 0, -1 ], [ .9, .5, 1, 0 ], [ .5, .78, 0, 1 ] ]
        },
        mailing_mediatype_sms: {
            icons: {
                inactive: "icon_sms_g.png",
                active: "icon_sms_l.png",
                dialog: "icon_sms_s.png"
            },
            anchors: [ [ .07, .5, -1, 0 ], [ .5, .22, 0, -1 ], [ .9, .5, 1, 0 ], [ .5, .78, 0, 1 ] ]
        },
        mailing_mediatype_post: {
            icons: {
                inactive: "icon_post_g.png",
                active: "icon_post_l.png",
                dialog: "icon_post_s.png"
            },
            anchors: [ [ .07, .5, -1, 0 ], [ .5, .22, 0, -1 ], [ .9, .5, 1, 0 ], [ .5, .78, 0, 1 ] ]
        },
        archive: {
            icons: {
                inactive: "icon_archive_g.png",
                active: "icon_archive_l.png",
                dialog: "icon_archive_s.png"
            },
            anchors: [ [ .1, .5, -1, 0 ], [ .5, .22, 0, -1 ], [ .9, .5, 1, 0 ], [ .5, .8, 0, 1 ] ]
        },
        datebased_mailing: {
            icons: {
                inactive: "icon_datebased_mailing_g.png",
                active: "icon_datebased_mailing_l.png",
                dialog: "icon_datebased_mailing_s.png"
            },
            anchors: [ [ .07, .5, -1, 0 ], [ .5, .22, 0, -1 ], [ .9, .5, 1, 0 ], [ .5, .78, 0, 1 ] ]
        },
        deadline: {
            icons: {
                inactive: "icon_deadline_g.png",
                active: "icon_deadline_l.png",
                dialog: "icon_deadline_s.png"
            },
            anchors: [ [ .1, .5, -1, 0 ], [ .5, .05, 0, -1 ], [ .9, .5, 1, 0 ], [ .5, .9, 0, 1 ] ]
        },
        decision: {
            icons: {
                inactive: "icon_decision_g.png",
                active: "icon_decision_l.png",
                dialog: "icon_decision_s.png"
            },
            anchors: [ [ .06, .5, -1, 0 ], [ .5, .06, 0, -1 ], [ .94, .5, 1, 0 ], [ .5, .94, 0, 1 ] ]
        },
        export: {
            icons: {
                inactive: "icon_export_g.png",
                active: "icon_export_l.png",
                dialog: "icon_export_s.png"
            },
            anchors: [ [ .1, .5, -1, 0 ], [ .5, .1, 0, -1 ], [ .9, .5, 1, 0 ], [ .5, .9, 0, 1 ] ]
        },
        followup_mailing: {
            icons: {
                inactive: "icon_followup_mailing_g.png",
                active: "icon_followup_mailing_l.png",
                dialog: "icon_followup_mailing_s.png"
            },
            anchors: [ [ .04, .5, -1, 0 ], [ .5, .2, 0, -1 ], [ .96, .5, 1, 0 ], [ .5, .8, 0, 1 ] ]
        },
        form: {
            icons: {
                inactive: "icon_form_g.png",
                active: "icon_form_l.png",
                dialog: "icon_form_s.png"
            },
            anchors: [ [ .1, .5, -1, 0 ], [ .5, .22, 0, -1 ], [ .9, .5, 1, 0 ], [ .5, .78, 0, 1 ] ]
        },
        import: {
            icons: {
                inactive: "icon_import_g.png",
                active: "icon_import_l.png",
                dialog: "icon_import_s.png"
            },
            anchors: [ [ .1, .5, -1, 0 ], [ .5, .1, 0, -1 ], [ .9, .5, 1, 0 ], [ .5, .9, 0, 1 ] ]
        },
        mailing: {
            icons: {
                inactive: "icon_mailing_g.png",
                active: "icon_mailing_l.png",
                dialog: "icon_mailing_s.png"
            },
            anchors: [ [ .1, .5, -1, 0 ], [ .5, .22, 0, -1 ], [ .9, .5, 1, 0 ], [ .5, .78, 0, 1 ] ]
        },
        ownWorkflow: {
            icons: {
                inactive: "icon_ownWorkflow_g.png",
                active: "icon_ownWorkflow_l.png",
                dialog: "icon_ownWorkflow_s.png"
            },
            anchors: [ [ .1, .5, -1, 0 ], [ .5, .22, 0, -1 ], [ .9, .5, 1, 0 ], [ .5, .78, 0, 1 ] ]
        },
        parameter: {
            icons: {
                inactive: "icon_parameter_g.png",
                active: "icon_parameter_l.png",
                dialog: "icon_parameter_s.png"
            },
            anchors: [ [ .1, .5, -1, 0 ], [ .5, .1, 0, -1 ], [ .9, .5, 1, 0 ], [ .5, .9, 0, 1 ] ]
        },
        recipient: {
            icons: {
                inactive: "icon_recipient_g.png",
                active: "icon_recipient_l.png",
                dialog: "icon_recipient_s.png"
            },
            anchors: [ [ .1, .5, -1, 0 ], [ .5, .1, 0, -1 ], [ .9, .5, 1, 0 ], [ .5, .9, 0, 1 ] ]
        },
        scABTest: {
            icons: {
                inactive: "icon_scABTest_g.png",
                active: "icon_scABTest_l.png",
                dialog: "icon_scABTest_s.png"
            },
            anchors: [ [ .1, .5, -1, 0 ], [ .5, .15, 0, -1 ], [ .9, .5, 1, 0 ], [ .5, .85, 0, 1 ] ]
        },
        scBirthday: {
            icons: {
                inactive: "icon_scBirthday_g.png",
                active: "icon_scBirthday_l.png",
                dialog: "icon_scBirthday_s.png"
            },
            anchors: [ [ .1, .5, -1, 0 ], [ .5, .1, 0, -1 ], [ .9, .5, 1, 0 ], [ .5, .85, 0, 1 ] ]
        },
        scDOI: {
            icons: {
                inactive: "icon_scDOI_g.png",
                active: "icon_scDOI_l.png",
                dialog: "icon_scDOI_s.png"
            },
            anchors: [ [ .3, .5, -1, 0 ], [ .5, .04, 0, -1 ], [ .72, .5, 1, 0 ], [ .5, .96, 0, 1 ] ]
        },
        start: {
            icons: {
                inactive: "icon_start_g.png",
                active: "icon_start_l.png",
                dialog: "icon_start_s.png"
            },
            anchors: [ [ 0, .5, -1, 0 ], [ .5, .15, 0, -1 ], [ 1, .5, 1, 0 ], [ .5, .85, 0, 1 ] ]
        },
        stop: {
            icons: {
                inactive: "icon_start_g.png",
                active: "icon_stop_l.png",
                dialog: "icon_start_s.png"
            },
            anchors: [ [ 0, .5, -1, 0 ], [ .5, .15, 0, -1 ], [ 1, .5, 1, 0 ], [ .5, .85, 0, 1 ] ]
        }
    };
    var CONNECTION_CONSTRAINTS = {
        "*": {
            deadline: function(source, target) {
                return !target.connections.incoming.some(function(connection) {
                    return connection.source.getType() === "import";
                });
            },
            mailing: function(source, target) {
                return target.connections.incoming.length === 0;
            },
            datebased_mailing: function(source, target) {
                return target.connections.incoming.length === 0;
            }
        },
        start: {
            recipient: true,
            form: true,
            import: true,
            export: true
        },
        stop: false,
        decision: {
            stop: true,
            decision: true,
            parameter: true,
            deadline: true,
            recipient: true,
            form: true,
            archive: true,
            mailing_mediatype_sms: true,
            mailing_mediatype_post: true,
            actionbased_mailing: true,
            datebased_mailing: true,
            followup_mailing: true,
            mailing: true
        },
        parameter: {
            stop: true,
            decision: true,
            parameter: true,
            deadline: true,
            recipient: true,
            form: true,
            archive: true,
            mailing_mediatype_sms: true,
            mailing_mediatype_post: true,
            actionbased_mailing: true,
            datebased_mailing: true,
            followup_mailing: true,
            mailing: true
        },
        deadline: {
            decision: true,
            parameter: true,
            recipient: true,
            archive: true,
            mailing_mediatype_sms: true,
            mailing_mediatype_post: true,
            actionbased_mailing: true,
            datebased_mailing: true,
            followup_mailing: true,
            mailing: true,
            import: true,
            export: true
        },
        recipient: {
            decision: true,
            parameter: true,
            deadline: true,
            recipient: true,
            form: true,
            archive: true,
            mailing_mediatype_sms: true,
            mailing_mediatype_post: true,
            actionbased_mailing: true,
            datebased_mailing: true,
            followup_mailing: true,
            mailing: true,
            import: true,
            export: true
        },
        actionbased_mailing: {
            stop: true,
            decision: true,
            parameter: true,
            deadline: true,
            recipient: true,
            form: true,
            archive: true,
            import: true,
            export: true
        },
        datebased_mailing: {
            stop: true,
            decision: true,
            parameter: true,
            deadline: true,
            recipient: true,
            form: true,
            archive: true,
            import: true,
            export: true
        },
        followup_mailing: {
            stop: true,
            decision: true,
            parameter: true,
            deadline: true,
            recipient: true,
            form: true,
            archive: true,
            import: true,
            export: true
        },
        mailing: {
            stop: true,
            decision: true,
            parameter: true,
            deadline: true,
            recipient: true,
            form: true,
            archive: true,
            import: true,
            export: true
        },
        mailing_mediatype_sms: {
            stop: true,
            decision: true,
            parameter: true,
            deadline: true,
            recipient: true,
            form: true,
            archive: true,
            import: true,
            export: true
        },
        mailing_mediatype_post: {
            stop: true,
            decision: true,
            parameter: true,
            deadline: true,
            recipient: true,
            form: true,
            archive: true,
            import: true,
            export: true
        },
        archive: {
            decision: true,
            parameter: true,
            deadline: true,
            recipient: true,
            actionbased_mailing: true,
            mailing_mediatype_sms: true,
            mailing_mediatype_post: true,
            datebased_mailing: true,
            followup_mailing: true,
            mailing: true,
            import: true,
            export: true
        },
        form: {
            stop: true,
            decision: true,
            parameter: true,
            deadline: true,
            recipient: true,
            form: true,
            archive: true,
            actionbased_mailing: true,
            mailing_mediatype_sms: true,
            mailing_mediatype_post: true,
            datebased_mailing: true,
            followup_mailing: true,
            mailing: true,
            import: true,
            export: true
        },
        import: {
            deadline: function(source) {
                return source.connections.outgoing.length === 0;
            }
        },
        export: {
            stop: true,
            decision: true,
            parameter: true,
            deadline: true,
            recipient: true,
            actionbased_mailing: true,
            mailing_mediatype_sms: true,
            mailing_mediatype_post: true,
            datebased_mailing: true,
            followup_mailing: true,
            mailing: true,
            import: true,
            export: true,
            archive: true,
            form: true
        }
    };
    AGN.Lib.WM.Definitions = {
        KEY_ENTER: 13,
        KEY_SHIFT: 16,
        KEY_CTRL: 17,
        KEY_SPACE: 32,
        KEY_DELETE: 46,
        MOUSE_BUTTON_LEFT: 0,
        MOUSE_BUTTON_MIDDLE: 1,
        DEFAULT_DRAG_MODE: 0,
        GRID_CELL_DRAG_MODE: 1,
        BOTTOM: "BOTTOM",
        LEFT: "LEFT",
        RIGHT: "RIGHT",
        TOP: "TOP",
        NODE_ANIMATION_DROPPED: "animate-dropped",
        NODE_ANIMATION_AUTO_DROPPED: "animate-auto-dropped",
        Z_INDEX_VIEW_PORT: 10,
        Z_INDEX_ICON_PANEL: 50,
        Z_INDEX_DRAGGABLE_BUTTON: 60,
        Z_INDEX_ICON_TITLES_CONTAINER: 5,
        Z_INDEX_CONNECTION_OVERLAY: 9,
        Z_INDEX_ICON: 10,
        Z_INDEX_CONNECTION_HOVER: 11,
        Z_INDEX_CONNECTION_OVERLAY_HOVER: 12,
        Z_INDEX_ICON_HOVER: 13,
        Z_INDEX_ICON_TITLE_HOVER: 19,
        Z_INDEX_DRAGGED_ICON_NODE: 20,
        Z_INDEX_JSPLUMB_DRAG_OPTIONS: 25,
        Z_INDEX_NAVIGATOR_GLOBE: 30,
        Z_INDEX_NAVIGATOR_ARROWS: 31,
        Z_INDEX_CONTEXT_MENU: 40,
        CANVAS_DEFAULT_GRID_SIZE: 20,
        CANVAS_GRID_SIZE: 20,
        NODE_SIZE: 64,
        NODE_MIN_MARGIN: .1,
        TITLE_WIDTH: 94,
        MINIMAP_PADDING: 2,
        DEFAULT_AUTO_ALIGN_STEP_X: 5,
        GRID_AUTO_ALIGN_STEP_X: 2,
        AUTO_ALIGN_STEP_X: 5,
        AUTO_ALIGN_EXTRA_STEP_X: .5,
        DEFAULT_AUTO_ALIGN_STEP_Y: 6,
        GRID_AUTO_ALIGN_STEP_Y: 2,
        AUTO_ALIGN_STEP_Y: 6,
        AUTO_ALIGN_STEP_BETWEEN_GROUPS: 2,
        AUTO_DROP_STEP_X: 4,
        AUTO_DROP_STEP_Y: 3,
        MIN_ZOOM: .5,
        MAX_ZOOM: 1.5,
        DEFAULT_ZOOM: 1,
        ZOOM_STEP: .1,
        NAVIGATION_STEP: 100,
        MAX_UNDO_STEPS: 17,
        CONNECTION_COLOR: "#61B7CF",
        CONNECTION_THICKNESS: 3,
        CONNECTION_OUTLINE_COLOR: "transparent",
        CONNECTION_OUTLINE_WIDTH: 4,
        CONNECTION_HOVER_COLOR: "#216477",
        CONNECTION_ARROW_SIZE: 10,
        NODE_TYPE_START: "start",
        NODE_TYPE_STOP: "stop",
        NODE_TYPE_DECISION: "decision",
        NODE_TYPE_DEADLINE: "deadline",
        NODE_TYPE_PARAMETER: "parameter",
        NODE_TYPE_RECIPIENT: "recipient",
        NODE_TYPE_ARCHIVE: "archive",
        NODE_TYPE_FORM: "form",
        NODE_TYPE_MAILING: "mailing",
        NODE_TYPE_OWN_WORKFLOW: "ownWorkflow",
        NODE_TYPE_SC_BIRTHDAY: "scBirthday",
        NODE_TYPE_SC_DOI: "scDOI",
        NODE_TYPE_SC_ABTEST: "scABTest",
        NODE_TYPE_ACTION_BASED_MAILING: "actionbased_mailing",
        NODE_TYPE_MAILING_MEDIATYPE_SMS: "mailing_mediatype_sms",
        NODE_TYPE_MAILING_MEDIATYPE_POST: "mailing_mediatype_post",
        NODE_TYPE_DATE_BASED_MAILING: "datebased_mailing",
        NODE_TYPE_FOLLOWUP_MAILING: "followup_mailing",
        NODE_TYPE_IMPORT: "import",
        NODE_TYPE_EXPORT: "export",
        NODE_TYPES_MAILING: [ "mailing", "followup_mailing", "actionbased_mailing", "datebased_mailing", "mailing_mediatype_sms", "mailing_mediatype_post" ],
        NODE_TYPES_IMPORT_EXPORT: [ "import", "export" ],
        NODE_TYPE_START_ID: 0,
        NODE_TYPE_STOP_ID: 1,
        NODE_TYPE_DECISION_ID: 2,
        NODE_TYPE_DEADLINE_ID: 3,
        NODE_TYPE_PARAMETER_ID: 4,
        NODE_TYPE_RECIPIENT_ID: 6,
        NODE_TYPE_ARCHIVE_ID: 7,
        NODE_TYPE_FORM_ID: 8,
        NODE_TYPE_MAILING_ID: 9,
        NODE_TYPE_OWN_WORKFLOW_ID: 10,
        NODE_TYPE_SC_BIRTHDAY_ID: 11,
        NODE_TYPE_SC_DOI_ID: 12,
        NODE_TYPE_SC_ABTEST_ID: 13,
        NODE_TYPE_ACTION_BASED_MAILING_ID: 14,
        NODE_TYPE_DATE_BASED_MAILING_ID: 15,
        NODE_TYPE_FOLLOWUP_MAILING_ID: 16,
        NODE_TYPE_IMPORT_ID: 17,
        NODE_TYPE_EXPORT_ID: 18,
        NODE_TYPE_MAILING_MEDIATYPE_SMS_ID: 19,
        NODE_TYPE_MAILING_MEDIATYPE_POST_ID: 20,
        MAILING_PARAM_MAILING_LIST: 1,
        MAILING_PARAM_TARGET_GROUPS: 2,
        MAILING_PARAM_ARCHIVE: 3,
        MAILING_PARAM_LIST_SPLIT: 4,
        MAILING_PARAM_PLANNED_DATE: 5,
        MAILING_PARAM_SEND_DATE: 6,
        MAILING_PARAM_ALTGS: 7,
        DEPENDENCY_TYPE_ARCHIVE: 1,
        DEPENDENCY_TYPE_AUTO_EXPORT: 2,
        DEPENDENCY_TYPE_AUTO_IMPORT: 3,
        DEPENDENCY_TYPE_MAILING_DELIVERY: 4,
        DEPENDENCY_TYPE_MAILING_LINK: 5,
        DEPENDENCY_TYPE_MAILING_REFERENCE: 6,
        DEPENDENCY_TYPE_MAILINGLIST: 7,
        DEPENDENCY_TYPE_PROFILE_FIELD: 8,
        DEPENDENCY_TYPE_PROFILE_FIELD_HISTORY: 9,
        DEPENDENCY_TYPE_TARGET_GROUP: 11,
        DEPENDENCY_TYPE_USER_FORM: 12,
        GENDER_PROFILE_FIELD: "gender",
        FIELD_TYPE_DATE: "date",
        SPLIT_DEFAULT_PARAMETERS: [ 5, 10, 15, 20, 25, 30, 33, 40, 50 ],
        TITLE_MAX_TARGETS: 2,
        PDF_SIZE: "A4",
        PDF_ORIENTATION: "landscape",
        PAGE_DIMENSIONS: {
            A4: {
                width: 800,
                height: 1360
            }
        },
        ICONS_CONFIG: ICONS_CONFIG,
        CONNECTION_CONSTRAINTS: CONNECTION_CONSTRAINTS,
        NODE_POPOVER_TEMPLATE: '<div class="popover popover-wide" role="tooltip" ><div class="arrow"></div><div class="popover-content" style="width: auto; height: auto; max-width: 300px; max-height: 350px; overflow: auto;"></div></div>',
        EMPTY_OPTION_PLACEHOLDER: "--"
    };
})();

(function() {
    var Def = AGN.Lib.WM.Definitions, Helpers = AGN.Lib.Helpers, DateFormat = AGN.Lib.DateFormat;
    AGN.Lib.WM.Utils = {
        checkActivation: function(withAlert) {
            var currentWorkflowStatus = $("#workflow-status").val();
            if (Def.constants.initialWorkflowStatus === Def.constants.statusActive && (currentWorkflowStatus === Def.constants.statusActive || currentWorkflowStatus === Def.constants.statusTesting)) {
                if (withAlert) {
                    AGN.Lib.Messages(t("workflow.defaults.error"), t("error.workflow.saveActivatedWorkflow"), "alert");
                }
                return true;
            } else {
                return false;
            }
        },
        getConfigData: function($e) {
            return Helpers.objFromString($e.data("config"));
        },
        mapAsOptionsHtml: function(options) {
            var html = "";
            Object.keys(options).forEach(function(key) {
                var attributes = 'value="' + key + '"';
                html += "<option " + attributes + ">" + options[key] + "</option>";
            });
            return html;
        },
        arrayAsOptionsHtml: function(options) {
            var html = "";
            options.forEach(function(option) {
                var attributes = 'value="' + option.id + '"';
                var extras = option.data;
                if (extras) {
                    Object.keys(extras).forEach(function(k) {
                        attributes += " data-" + k + '="' + extras[k].replace('"', "&quot;") + '"';
                    });
                }
                var text = option.text.replace("<", "&lt;").replace(">", "&gt;");
                html += "<option " + attributes + ">" + text + "</option>";
            });
            return html;
        }
    };
    AGN.Lib.WM.DateTimeUtils = {
        toDateTime: function(date, hour, minute) {
            var value = null;
            if (!!date && date.getMonth) {
                value = new Date(date);
                if (!!hour && hour !== 0) {
                    value.setHours(hour);
                }
                if (!!minute && minute !== 0) {
                    value.setMinutes(minute);
                }
            }
            return value;
        },
        getDateTimeValue: function(date, hour, minute) {
            var value = this.toDateTime(date, hour, minute);
            return value != null ? value.getTime() : null;
        },
        getDateTimeStr: function(date, hour, minute, datePattern) {
            if (!date || !date.getMonth) {
                return "";
            }
            hour = hour || date.getHours();
            minute = minute || date.getMinutes();
            var dateTime = this.toDateTime(date, hour, minute);
            if (!!dateTime) {
                return DateFormat.format(dateTime, datePattern);
            } else {
                return "";
            }
        },
        getDateStr: function(date, datePattern) {
            return this.getDateTimeStr(date, null, null, datePattern);
        }
    };
})();

(function() {
    function Constraints(rules) {
        this.rules = rules;
    }
    Constraints.prototype.isConstraint = function(value) {
        return _.isBoolean(value) || _.isFunction(value);
    };
    Constraints.prototype.evaluate = function(constraint, source, target) {
        if (constraint === true || constraint === false) {
            return constraint;
        }
        if (_.isFunction(constraint)) {
            return constraint(source, target);
        }
        return undefined;
    };
    Constraints.prototype.getRulesToCheck = function(source, target) {
        return [ {
            from: source.type,
            to: [ target.type, "*" ]
        }, {
            from: "*",
            to: [ target.type, "*" ]
        } ];
    };
    Constraints.prototype.getRelevantConstraints = function(source, target) {
        var isConstraint = this.isConstraint;
        var rulesToCheck = this.getRulesToCheck(source, target);
        var rules = this.rules;
        var constraints = [];
        rulesToCheck.forEach(function(rule) {
            var isRuleMissing = true;
            if (_.has(rules, rule.from)) {
                var value = rules[rule.from];
                if (isConstraint(value)) {
                    constraints.push(value);
                    isRuleMissing = false;
                } else {
                    rule.to.forEach(function(to) {
                        if (_.has(rules[rule.from], to)) {
                            value = rules[rule.from][to];
                            if (isConstraint(value)) {
                                constraints.push(value);
                                isRuleMissing = false;
                            }
                        }
                    });
                }
            }
            if (isRuleMissing && rule.from != "*") {
                constraints.push(false);
            }
        });
        return constraints;
    };
    Constraints.prototype.check = function(source, target) {
        var constraints = this.getRelevantConstraints(source, target);
        var result = false;
        for (var i = 0; i < constraints.length; i++) {
            if (this.evaluate(constraints[i], source, target)) {
                result = true;
            } else {
                return false;
            }
        }
        return result;
    };
    AGN.Lib.WM.ConnectionConstraints = Constraints;
})();

(function() {
    var DateTimeUtils = AGN.Lib.WM.DateTimeUtils, Template = AGN.Lib.Template, Def = AGN.Lib.WM.Definitions, Popover = AGN.Lib.Popover;
    function Node(type, data) {
        this.id = null;
        this.x = 0;
        this.y = 0;
        this.type = type;
        this.title = "";
        this.overlayTitle = "";
        this.overlayImage = {
            image: "",
            title: "",
            visible: false
        };
        this.filled = false;
        this.editable = true;
        this.expandable = false;
        this.dependent = false;
        this.inRecipientsChain = false;
        this.anchors = Def.ICONS_CONFIG[type].anchors;
        this.data = data;
        this.$element = Node.create$(type);
        this.$element.data("agn:node", this);
        this.$connectionButton = this.$element.find(".node-connect-button");
        this.$titleDiv = Node.createTitleDiv$();
        this.$titleSpan = this.$titleDiv.find(".icon-title-span");
        this.$overlayTitle = this.$element.find(".icon-overlay-title");
        this.$overlayImage = this.$element.find(".icon-overlay-image img");
        this.nodePopover = new NodePopover(this);
        this.lastTitleAnchor = Def.BOTTOM;
    }
    Node.restore = function(node) {
        var agnData = node.get$().data("agn:node");
        if (!agnData) {
            node.get$().data("agn:node", node);
        }
        return node;
    };
    Node.get = function($element) {
        if ($element instanceof HTMLElement) {
            $element = $($element);
        }
        if (!$element.is(".node")) {
            $element = $element.closest(".node");
        }
        return $element.data("agn:node");
    };
    Node.isDecisionNode = function(node) {
        return node.getType() === Def.NODE_TYPE_DECISION;
    };
    Node.isMailingNode = function(node) {
        if (!node) {
            return false;
        }
        return Def.NODE_TYPES_MAILING.includes(node.getType());
    };
    Node.isBranchingDecisionNode = function(node) {
        if (Node.isDecisionNode(node)) {
            var data = node.getData();
            if (data.decisionType === Def.constants.decisionTypeDecision) {
                return true;
            }
        }
        return false;
    };
    Node.isDecisionBranchesOrderFromPositiveToNegative = function(source, target1, target2) {
        if (target1.y <= source.y && target2.y <= source.y) {
            if (target1.y < target2.y) {
                return true;
            } else if (target2.y < target1.y) {
                return false;
            } else {
                return target1.x < target2.x;
            }
        } else if (target1.y > source.y && target2.y > source.y) {
            return target1.x > target2.x;
        } else {
            return target1.y < target2.y;
        }
    };
    Node.getDecisionBranches = function(connections) {
        if (connections.length === 2) {
            var source = Node.getPosition(connections[0].source.get$());
            var target1 = Node.getPosition(connections[0].target.get$());
            var target2 = Node.getPosition(connections[1].target.get$());
            if (this.isDecisionBranchesOrderFromPositiveToNegative(source, target1, target2)) {
                return {
                    positive: connections[0],
                    negative: connections[1]
                };
            } else {
                return {
                    positive: connections[1],
                    negative: connections[0]
                };
            }
        }
        return null;
    };
    Node.isCommented = function(node) {
        return !!_.trim(node.getComment());
    };
    Node.isSelected = function($element) {
        return $element.hasClass("ui-selected");
    };
    Node.setSelected = function($element, isSelected) {
        return $element.toggleClass("ui-selected", !!isSelected);
    };
    Node.isChainSource = function($element) {
        return $element.hasClass("chain-mode-source");
    };
    Node.setChainSource = function($element, isSource) {
        $element.toggleClass("chain-mode-source", !!isSource);
    };
    Node.getAnchors = function($node) {
        var node = Node.get($node);
        if (node) {
            return node.getAnchors();
        }
        return Def.ICONS_CONFIG[$node.data("type")].anchors;
    };
    Node.getAnchorsInUse = function(endpoints) {
        var anchorsInUse = {};
        endpoints.forEach(function(endpoint) {
            var orientation = endpoint.anchor.getOrientation();
            if (orientation[0] > 0) {
                anchorsInUse[Def.RIGHT] = true;
            } else if (orientation[0] < 0) {
                anchorsInUse[Def.LEFT] = true;
            } else if (orientation[1] > 0) {
                anchorsInUse[Def.BOTTOM] = true;
            } else if (orientation[1] < 0) {
                anchorsInUse[Def.TOP] = true;
            }
        });
        return anchorsInUse;
    };
    Node.getPosition = function($node) {
        var position = $node.position();
        return {
            x: position.left,
            y: position.top
        };
    };
    Node.getBox = function($node) {
        var position = $node.position();
        var rect = $node[0].getBoundingClientRect();
        return {
            minX: position.left,
            minY: position.top,
            maxX: position.left + rect.width,
            maxY: position.top + rect.height
        };
    };
    Node.isInRegion = function($node, regionBox) {
        var nodeBox = Node.getBox($node);
        return (nodeBox.minX >= regionBox.minX && nodeBox.minX <= regionBox.maxX || nodeBox.maxX >= regionBox.minX && nodeBox.maxX <= regionBox.maxX) && (nodeBox.minY >= regionBox.minY && nodeBox.minY <= regionBox.maxY || nodeBox.maxY >= regionBox.minY && nodeBox.maxY <= regionBox.maxY);
    };
    Node.getCollisionBox = function($node) {
        var anchors = Node.getAnchors($node);
        var position = $node.position();
        var rect = $node[0].getBoundingClientRect();
        var paddingLeft = (anchors[0][0] - Def.NODE_MIN_MARGIN) * rect.width;
        var paddingTop = (anchors[1][1] - Def.NODE_MIN_MARGIN) * rect.height;
        var paddingRight = (1 - anchors[2][0] - Def.NODE_MIN_MARGIN) * rect.width;
        var paddingBottom = (1 - anchors[3][1] - Def.NODE_MIN_MARGIN) * rect.height;
        return {
            minX: position.left + paddingLeft,
            minY: position.top + paddingTop,
            maxX: position.left + rect.width - paddingRight,
            maxY: position.top + rect.height - paddingBottom
        };
    };
    Node.detectBoxCollision = function(box1, box2) {
        return !(box1.minX > box2.maxX || box1.maxX < box2.minX || box1.minY > box2.maxY || box1.maxY < box2.minY);
    };
    Node.create$ = function() {
        var render = null;
        return function(type) {
            if (render == null) {
                render = Template.prepare("workflow-node");
            }
            return $(render({
                icons: Def.ICONS_CONFIG[type].icons
            }));
        };
    }();
    Node.createDraggable$ = function() {
        var render = null;
        return function(type) {
            if (render == null) {
                render = Template.prepare("workflow-draggable-node");
            }
            return $(render({
                type: type,
                icons: Def.ICONS_CONFIG[type].icons
            }));
        };
    }();
    Node.createTitleDiv$ = function() {
        var render = null;
        return function() {
            if (render == null) {
                render = Template.prepare("workflow-icon-title");
            }
            return $(render({}));
        };
    }();
    Node.create = function(type) {
        var data = {
            iconComment: ""
        };
        var node = new Node(type, data);
        switch (type) {
          case "scABTest":
          case "scBirthday":
          case "scDOI":
            node.setFilled(true);
            node.setExpandable(true);
            data.copyContent = true;
            data.created = false;
            break;

          case "ownWorkflow":
            node.setExpandable(true);
            data.ownWorkflowId = 0;
            data.copyContent = true;
            data.created = false;
            break;

          case "start":
            data.startType = null;
            data.date = null;
            data.hour = 0;
            data.minute = 0;
            data.sendReminder = false;
            data.remindAdminId = 0;
            data.remindAtOnce = false;
            data.scheduleReminder = false;
            data.remindSpecificDate = false;
            data.remindDate = new Date();
            data.remindHour = 0;
            data.remindMinute = 0;
            data.event = null;
            data.reaction = null;
            data.mailingId = 0;
            data.profileField = "";
            data.dateProfileField = "";
            data.dateFieldOperator = 1;
            data.dateFieldValue = "";
            data.useRules = false;
            data.rules = [];
            data.executeOnce = true;
            data.comment = "";
            data.recipients = "";
            data.adminTimezone = "";
            break;

          case "stop":
            data.endType = null;
            data.date = null;
            data.hour = 0;
            data.minute = 0;
            data.sendReminder = false;
            data.remindAdminId = 0;
            data.remindAtOnce = false;
            data.scheduleReminder = false;
            data.remindSpecificDate = false;
            data.remindDate = new Date();
            data.remindHour = 0;
            data.remindMinute = 0;
            data.event = null;
            data.reaction = null;
            data.mailingId = 0;
            data.profileField = "";
            data.useRules = false;
            data.rules = [];
            data.executeOnce = true;
            data.comment = "";
            data.recipients = "";
            data.adminTimezone = "";
            break;

          case "decision":
            data.decisionType = null;
            data.decisionCriteria = null;
            data.reaction = null;
            data.mailingId = 0;
            data.linkId = 0;
            data.profileField = "";
            data.aoDecisionCriteria = null;
            data.threshold = "";
            data.decisionDate = new Date();
            data.rules = [];
            data.includeVetoed = true;
            break;

          case "deadline":
            data.deadlineType = null;
            data.date = new Date();
            data.timeUnit = null;
            data.delayValue = 0;
            data.hour = 0;
            data.minute = 0;
            data.useTime = false;
            break;

          case "parameter":
            data.value = 0;
            break;

          case "recipient":
            node.setDependent(false);
            data.mailinglistId = 0;
            data.targets = [];
            data.altgs = [];
            data.targetsOption = null;
            break;

          case "archive":
            data.campaignId = 0;
            data.archived = false;
            break;

          case "form":
            data.userFormId = 0;
            data.formType = "form";
            break;

          case "mailing":
            data.mailingId = 0;
            data.skipEmptyBlocks = false;
            data.doubleCheck = true;
            break;

          case "actionbased_mailing":
          case "datebased_mailing":
          case "mailing_mediatype_sms":
          case "mailing_mediatype_post":
            data.mailingId = 0;
            break;

          case "followup_mailing":
            data.baseMailingId = 0;
            data.mailingId = 0;
            data.decisionCriterion = "OPENED";
            break;

          case "import":
          case "export":
            data.importexportId = 0;
            data.errorTolerant = false;
            break;
        }
        return node;
    };
    Node.isExpandableType = function(type) {
        switch (type) {
          case "scABTest":
          case "scBirthday":
          case "scDOI":
          case "ownWorkflow":
            return true;

          default:
            return false;
        }
    };
    Node.deserialize = function(object) {
        var data = $.extend({}, object);
        var node = new Node(object.type, data);
        node.setId(object.id);
        node.setCoordinates(object.x, object.y);
        node.setTitle(object.iconTitle);
        node.setComment(object.iconComment);
        node.setFilled(object.filled);
        node.setEditable(object.editable);
        if ([ "ownWorkflow", "scBirthday", "scDOI", "scABTest" ].includes(object.type)) {
            node.setExpandable(true);
        }
        delete data["id"];
        delete data["x"];
        delete data["y"];
        delete data["type"];
        delete data["iconTitle"];
        delete data["filled"];
        delete data["editable"];
        [ "date", "remindDate", "decisionDate" ].forEach(function(k) {
            if (data[k]) {
                var string = data[k].toString();
                if (string.includes("-")) {
                    var parts = string.split("-");
                    data[k] = new Date(parts[0], parts[1] - 1, parts[2]);
                } else {
                    data[k] = new Date(data[k]);
                }
            }
        });
        return node;
    };
    Node.deserializeConnections = function(icons, nodesMap) {
        var connections = [];
        icons.forEach(function(icon) {
            var source = nodesMap[icon.id];
            if (source instanceof Node) {
                if (icon.connections) {
                    icon.connections.forEach(function(connection) {
                        var target = nodesMap[connection.targetIconId];
                        if (target instanceof Node) {
                            connections.push({
                                source: source,
                                target: target
                            });
                        }
                    });
                }
            }
        });
        return connections;
    };
    Node.toMap = function(nodes) {
        var map = {};
        nodes.forEach(function(node) {
            map[node.getId()] = node;
        });
        return map;
    };
    Node.prototype.appendTo = function($container, $titlesContainer, animation) {
        this.$container = $container;
        this.$titlesContainer = $titlesContainer;
        if (animation) {
            this.$element.addClass(animation);
        }
        $container.append(this.$element);
        $titlesContainer.append(this.$titleDiv);
        this.$titleDiv.toggleClass("expandable", this.$titleSpan.height() > this.$titleDiv.height());
    };
    Node.prototype.isAppended = function() {
        return !!this.$container;
    };
    Node.prototype.get$ = function() {
        return this.$element;
    };
    Node.prototype.getId = function() {
        return this.id;
    };
    Node.prototype.setId = function(id) {
        this.id = id;
        this.$element.prop("id", id);
    };
    Node.prototype.getX = function() {
        return this.x;
    };
    Node.prototype.getY = function() {
        return this.y;
    };
    Node.prototype.getCoordinates = function() {
        return {
            x: this.x,
            y: this.y
        };
    };
    Node.prototype.setCoordinates = function(x, y) {
        this.x = x;
        this.y = y;
        this.$element.css("left", x * Def.CANVAS_GRID_SIZE);
        this.$element.css("top", y * Def.CANVAS_GRID_SIZE);
    };
    Node.prototype.updateCoordinates = function(scale) {
        var position = Node.getPosition(this.$element);
        this.x = position.x / scale / Def.CANVAS_GRID_SIZE;
        this.y = position.y / scale / Def.CANVAS_GRID_SIZE;
    };
    Node.prototype.getType = function() {
        return this.type;
    };
    Node.prototype.setType = function(type) {
        this.type = type;
    };
    Node.prototype.getTitle = function() {
        return this.title;
    };
    Node.prototype.setTitle = function(title) {
        this.title = title;
        if (title) {
            this.$titleSpan.text(title);
            this.positionTitle(this.lastTitleAnchor);
            this.$titleDiv.toggleClass("expandable", this.$titleSpan.height() > this.$titleDiv.height());
        }
        this.setTitleEnabled(!!title);
    };
    Node.prototype.setTitleEnabled = function(isEnabled) {
        this.$titleDiv.toggle(!!isEnabled && !!this.title);
    };
    Node.prototype.setTitleExpanded = function(isExpanded) {
        this.$titleDiv.toggleClass("expanded", !!isExpanded);
        if (this.isAppended()) {
            if (isExpanded) {
                this.$titleDiv.appendTo(this.$container);
            } else {
                this.$titleDiv.appendTo(this.$titlesContainer);
            }
        }
    };
    Node.prototype.positionTitle = function(anchor) {
        this.lastTitleAnchor = anchor;
        var minX = this.x * Def.CANVAS_GRID_SIZE;
        var maxX = minX + Def.NODE_SIZE;
        var minY = this.y * Def.CANVAS_GRID_SIZE;
        var maxY = minY + Def.NODE_SIZE;
        switch (anchor) {
          case Def.BOTTOM:
            this.$titleDiv.css({
                top: maxY,
                left: minX + (Def.NODE_SIZE - Def.TITLE_WIDTH) / 2,
                transform: "none"
            });
            break;

          case Def.LEFT:
            this.$titleDiv.css({
                top: (minY + maxY) / 2,
                left: minX - Def.TITLE_WIDTH,
                transform: "translateY(-50%)"
            });
            break;

          case Def.RIGHT:
            this.$titleDiv.css({
                top: (minY + maxY) / 2,
                left: maxX,
                transform: "translateY(-50%)"
            });
            break;

          case Def.TOP:
            this.$titleDiv.css({
                top: minY,
                left: minX + (Def.NODE_SIZE - Def.TITLE_WIDTH) / 2,
                transform: "translateY(-100%)"
            });
            break;

          default:
            return;
        }
    };
    Node.prototype.getOverlayTitle = function() {
        return this.overlayTitle;
    };
    Node.prototype.setOverlayTitle = function(overlayTitle) {
        this.overlayTitle = overlayTitle;
        this.$overlayTitle.text(_.trim(overlayTitle));
    };
    Node.prototype.getOverlayImage = function() {
        return this.overlayImage;
    };
    Node.prototype.setOverlayImage = function(overlayImage) {
        this.overlayImage = $.extend({
            image: "",
            title: "",
            visible: false
        }, overlayImage);
        var src = !!_.trim(this.overlayImage.image) ? Def.constants.imagePath + "/" + _.trim(this.overlayImage.image) : "";
        this.$overlayImage.prop("src", src);
        this.$overlayImage.prop("title", this.overlayImage.title);
        if (this.overlayImage.visible) {
            this.$overlayImage.show();
        } else {
            this.$overlayImage.hide();
        }
    };
    Node.prototype.getComment = function() {
        return this.comment;
    };
    Node.prototype.setComment = function(comment) {
        this.comment = this.data.iconComment = comment;
        this.$element.toggleClass("icon-commented", !!_.trim(comment));
    };
    Node.prototype.updateCommentLabels = function() {
        this.$element.toggleClass("icon-commented", !!_.trim(this.comment));
    };
    Node.prototype.setFootnote = function(footnoteId) {
        if (footnoteId > 0) {
            this.$element.attr("comment-footnote", footnoteId);
        } else {
            this.$element.removeAttr("comment-footnote");
        }
    };
    Node.prototype.isFilled = function() {
        return this.filled;
    };
    Node.prototype.setFilled = function(filled) {
        this.filled = filled;
        this.$element.toggleClass("active", filled);
    };
    Node.prototype.isEditable = function() {
        return this.editable;
    };
    Node.prototype.setEditable = function(editable) {
        this.editable = editable;
    };
    Node.prototype.isExpandable = function() {
        return this.expandable;
    };
    Node.prototype.setExpandable = function(expandable) {
        this.expandable = expandable;
    };
    Node.prototype.isDependent = function() {
        return this.dependent;
    };
    Node.prototype.setDependent = function(dependent) {
        this.dependent = dependent;
    };
    Node.prototype.isInRecipientsChain = function() {
        return this.inRecipientsChain;
    };
    Node.prototype.setInRecipientsChain = function(inRecipientsChain) {
        this.inRecipientsChain = inRecipientsChain;
    };
    Node.prototype.getAnchors = function() {
        return this.anchors;
    };
    Node.prototype.setAnchors = function(anchors) {
        this.anchors = anchors;
    };
    Node.prototype.getData = function() {
        return this.data;
    };
    Node.prototype.setData = function(data) {
        this.data = data;
    };
    Node.prototype.setInteractionEnabled = function(isEnabled) {
        this.$connectionButton.toggle(!!isEnabled);
    };
    Node.prototype.removePopover = function() {
        this.nodePopover.remove();
    };
    Node.prototype.setPopoverEnabled = function(isEnabled) {
        if (!isEnabled) {
            this.nodePopover._hidePopover(true);
        }
        this.nodePopover.setEnabled(isEnabled);
    };
    Node.prototype.setPopoverShown = function(isShown) {
        if (isShown) {
            this.nodePopover.show();
        } else {
            this.nodePopover.hide();
        }
    };
    Node.prototype.setHovered = function(isHovered) {
        this.setPopoverShown(isHovered);
        this.setTitleExpanded(isHovered);
    };
    Node.prototype.remove = function() {
        this.nodePopover.remove();
        this.$element.remove();
        this.$titleDiv.remove();
        this.$container = null;
        this.$titlesContainer = null;
    };
    Node.prototype.serialize = function() {
        var object = $.extend({}, this.data, {
            id: this.id,
            x: this.x,
            y: this.y,
            type: this.type,
            filled: this.filled,
            editable: this.editable,
            iconTitle: this.title
        });
        if ("date" in object && "hour" in object && "minute" in object) {
            object.date = DateTimeUtils.getDateTimeValue(object.date, object.hour, object.minute);
        }
        if ("remindDate" in object && "remindHour" in object && "remindMinute" in object) {
            object.remindDate = DateTimeUtils.getDateTimeValue(object.remindDate, object.remindHour, object.remindMinute);
        }
        if ("decisionDate" in object) {
            object.decisionDate = DateTimeUtils.getDateTimeValue(object.decisionDate);
        }
        return object;
    };
    function NodePopover(node) {
        if (node instanceof Node) {
            this.node = node;
        } else {
            this.node = Node.get(node);
        }
        this.popover = undefined;
        this.timeoutId = undefined;
        this.isEnabled = true;
    }
    NodePopover.prototype.remove = function() {
        if (this.popover) {
            this.popover.hide();
        }
        Popover.remove(this.node.get$());
        this.popover = null;
    };
    NodePopover.destroyAll = function() {
        $("[rel=popover]").each(function(i, node) {
            Node.get($(node)).removePopover();
        });
        $(".popover").remove();
    };
    NodePopover.prototype.initPopover = function() {
        var self = this;
        self.deferred = false;
        self.content = null;
        var popover = Popover.new(self.node.get$(), {
            trigger: "manual",
            html: true,
            template: Def.NODE_POPOVER_TEMPLATE,
            content: function() {
                return self.getPopoverContent();
            }
        });
        if (self.isEnabled) {
            popover.enable();
        } else {
            popover.disable();
        }
        var $tip = popover.tip();
        $tip.on({
            mouseenter: function() {
                self._showPopover();
            },
            mouseleave: function() {
                self._hidePopover(true);
            }
        });
        return popover;
    };
    NodePopover.prototype.show = function() {
        NodePopover.destroyAll();
        this.popover = this.initPopover();
        if (this.popover.hasContent() && this.popover.enabled) {
            this._showPopover();
        }
    };
    NodePopover.prototype.hide = function(immediate) {
        this._hidePopover(immediate);
    };
    NodePopover.prototype.getPopoverContent = function() {
        const self = this;
        var node = this.node;
        var content = "";
        var thumbnail = NodePopover.getThumbnail(node);
        if (thumbnail && !_.isEmpty(thumbnail.src)) {
            content += '<img src="' + thumbnail.src + '" style="width: 100%; height: 100%;" />';
        }
        if (Node.isCommented(node)) {
            content += "<div>" + node.getComment() + "</div>";
        }
        if (content && self.deferred === false) {
            this.deferred = $.Deferred();
            var $container = $("<div></div>");
            $container.css({
                position: "fixed",
                visibility: "hidden"
            });
            $container.html(content);
            $elements = $container.children();
            $(document.body).append($container);
            this.deferred.done(function() {
                $elements.detach();
                $container.remove();
                self.content = $elements;
            });
            var images = $elements.find("img").add($elements.filter("img")).filter(function() {
                return this.complete ? null : this;
            });
            if (images.length > 0) {
                self.deferred.done(function() {
                    if (self.popover) {
                        self.popover.setContent();
                        if (node.get$().is(":hover")) {
                            self._showPopover();
                        }
                    }
                });
                var checkLoadingComplete = function() {
                    var complete = true;
                    for (var i = 0; i < images.length; i++) {
                        var image = images[i];
                        if (image) {
                            if (image.complete) {
                                $(image).off("load error");
                                images[i] = null;
                            } else {
                                complete = false;
                            }
                        }
                    }
                    return complete;
                };
                for (var i = 0; i < images.length; i++) {
                    $(images[i]).on("load error", function() {
                        if (checkLoadingComplete()) {
                            self.deferred.resolve();
                        }
                    });
                }
            } else {
                self.deferred.resolve();
            }
        }
        return this.content;
    };
    NodePopover.getThumbnail = function(node) {
        if (Node.isMailingNode(node) && node.getData().mailingId > 0) {
            return NodePopover.getMailingThumbnail(node.getData().mailingId);
        }
        return "";
    };
    NodePopover.getMailingThumbnail = _.memoize(function(mailingId) {
        var img = "";
        $.ajax({
            type: "POST",
            url: AGN.url("/workflow/getMailingThumbnail.action"),
            async: false,
            data: {
                mailingId: mailingId
            },
            success: function(componentId) {
                if (componentId > 0) {
                    img = new Image();
                    img.src = AGN.url("/sc?compID=" + componentId);
                }
            }
        });
        return img;
    });
    NodePopover.prototype._stopHiding = function() {
        if (this.timeoutId) {
            clearTimeout(this.timeoutId);
            this.timeoutId = undefined;
        }
    };
    NodePopover.prototype._showPopover = function() {
        this._stopHiding();
        this.popover.show();
    };
    NodePopover.prototype._hidePopover = function(immediate) {
        this._stopHiding();
        if (!this.popover) {
            return;
        }
        if (immediate === true) {
            if (this.popover) {
                this.popover.hide();
            }
        } else {
            var self = this;
            this.timeoutId = setTimeout(function() {
                self._hidePopover(true);
            }, 200);
        }
    };
    NodePopover.prototype.setEnabled = function(isEnabled) {
        this.isEnabled = isEnabled;
        if (!this.popover) {
            return;
        }
        if (isEnabled) {
            this.popover.enable();
        } else {
            this.popover.disable();
        }
    };
    AGN.Lib.WM.NodePopover = NodePopover;
    AGN.Lib.WM.Node = Node;
})();

(function() {
    var Node = AGN.Lib.WM.Node;
    function Vertex(node) {
        this.id = node.getId();
        this.node = node;
        this.position = Node.getPosition(node.get$());
        this.box = Node.getBox(node.get$());
        this.connections = {
            incoming: [],
            outgoing: []
        };
    }
    Vertex.nodesToVertices = function(nodes) {
        return nodes.map(function(node) {
            return new Vertex(node);
        });
    };
    Vertex.verticesToMap = function(vertices) {
        var map = {};
        vertices.forEach(function(vertex) {
            map[vertex.id] = vertex;
        });
        return map;
    };
    Vertex.verticesFrom = function(nodes, connections) {
        var vertices = Vertex.nodesToVertices(nodes);
        var vertexMap = Vertex.verticesToMap(vertices);
        connections.forEach(function(connection) {
            var source, target;
            if ("sourceId" in connection) {
                source = vertexMap[connection.sourceId];
                target = vertexMap[connection.targetId];
            } else {
                source = vertexMap[connection.source.getId()];
                target = vertexMap[connection.target.getId()];
            }
            source.connections.outgoing.push(target);
            target.connections.incoming.push(source);
        });
        return vertices;
    };
    Vertex.compareByPosition = function(v1, v2) {
        var box1 = v1.box;
        var box2 = v2.box;
        if (box1.minX == box2.minX) {
            return box1.minY - box2.minY;
        }
        return box1.minX - box2.minX;
    };
    Vertex.filterUnvisited = function(vertices, visitedIds) {
        return vertices.filter(function(vertex) {
            if (visitedIds[vertex.id]) {
                return false;
            } else {
                visitedIds[vertex.id] = true;
                return true;
            }
        });
    };
    Vertex.getDecisionBranches = function(sourceVertex) {
        var connections = sourceVertex.connections.outgoing.map(function(targetVertex) {
            return {
                source: sourceVertex.node,
                target: targetVertex.node,
                targetVertex: targetVertex
            };
        });
        var targets = Node.getDecisionBranches(connections);
        if (targets) {
            return {
                positive: targets.positive.targetVertex,
                negative: targets.negative.targetVertex
            };
        }
        return null;
    };
    Vertex.getIncomingChains = function(vertex) {
        var visitedIds = {};
        var chains = [];
        collectIncomingChains([], vertex, visitedIds, chains);
        return chains;
    };
    Vertex.getOutgoingChains = function(vertex) {
        var visitedIds = {};
        var chains = [];
        collectOutgoingChains([], vertex, visitedIds, chains);
        return chains;
    };
    Vertex.prototype.getNode = function() {
        return this.node;
    };
    Vertex.prototype.siblings = function() {
        return this.connections.incoming.concat(this.connections.outgoing);
    };
    Vertex.prototype.rightSiblingsOrdered = function() {
        var siblings = this.connections.outgoing;
        if (Node.isBranchingDecisionNode(this.node)) {
            var targets = Vertex.getDecisionBranches(this);
            if (targets) {
                return [ targets.positive, targets.negative ];
            }
        }
        return siblings.sort(function(v1, v2) {
            return v1.node.getY() - v2.node.getY();
        });
    };
    function collectIncomingChains(chain, vertex, visitedIds, chains) {
        if (visitedIds[vertex.id]) {
            chains.push(chain);
        } else {
            chain.push(vertex.node);
            var connections = vertex.connections.incoming;
            if (connections.length) {
                visitedIds[vertex.id] = true;
                if (connections.length == 1) {
                    collectIncomingChains(chain, connections[0], visitedIds, chains);
                } else {
                    connections.forEach(function(connection) {
                        collectIncomingChains(chain.slice(), connection, visitedIds, chains);
                    });
                }
                visitedIds[vertex.id] = false;
            } else {
                chains.push(chain);
            }
        }
    }
    function collectOutgoingChains(chain, vertex, visitedIds, chains) {
        if (visitedIds[vertex.id]) {
            chains.push(chain);
        } else {
            chain.push(vertex.node);
            var connections = vertex.connections.outgoing;
            if (connections.length) {
                visitedIds[vertex.id] = true;
                if (connections.length == 1) {
                    collectOutgoingChains(chain, connections[0], visitedIds, chains);
                } else {
                    connections.forEach(function(connection) {
                        collectOutgoingChains(chain.slice(), connection, visitedIds, chains);
                    });
                }
                visitedIds[vertex.id] = false;
            } else {
                chains.push(chain);
            }
        }
    }
    AGN.Lib.WM.Vertex = Vertex;
})();

(function() {
    var Vertex = AGN.Lib.WM.Vertex;
    function VertexGroup(vertices) {
        this.vertices = vertices;
        this.box = vertices.map(function(v) {
            return v.box;
        }).reduce(function(b1, b2) {
            return {
                minX: Math.min(b1.minX, b2.minX),
                minY: Math.min(b1.minY, b2.minY),
                maxX: Math.max(b1.maxX, b2.maxX),
                maxY: Math.max(b1.maxY, b2.maxY)
            };
        });
    }
    VertexGroup.detectGroups = function(vertices) {
        var groups = [];
        var visitedIds = {};
        vertices.forEach(function(vertex) {
            var group = VertexGroup.detectGroup(vertex, visitedIds);
            if (group) {
                groups.push(group);
            }
        });
        return groups.sort(VertexGroup.compareByPosition);
    };
    VertexGroup.detectGroup = function(vertex, visitedIds) {
        if (visitedIds[vertex.id]) {
            return null;
        }
        var group = [];
        var vertices = vertex.siblings();
        group.push(vertex);
        visitedIds[vertex.id] = true;
        while (vertices.length) {
            vertices = _.flatMap(vertices, function(v) {
                if (visitedIds[v.id]) {
                    return [];
                } else {
                    group.push(v);
                    visitedIds[v.id] = true;
                    return v.siblings();
                }
            });
        }
        return new VertexGroup(group);
    };
    VertexGroup.compareByPosition = function(g1, g2) {
        var d = g1.box.minX + g1.box.maxX - (g2.box.minX + g2.box.maxX);
        if (d == 0) {
            return g1.box.minY + g1.box.maxY - (g2.box.minY + g2.box.maxY);
        }
        return d;
    };
    VertexGroup.prototype.getNodes = function() {
        return this.vertices.map(function(vertex) {
            return vertex.getNode();
        });
    };
    VertexGroup.prototype.getStartingVertices = function() {
        var startingVertices = this.vertices.filter(function(vertex) {
            return vertex.connections.incoming.length == 0;
        });
        if (startingVertices.length) {
            return startingVertices.sort(Vertex.compareByPosition);
        }
        var bestCandidate = this.vertices.reduce(function(v1, v2) {
            var rate1 = v1.connections.outgoing.length / v1.connections.incoming.length;
            var rate2 = v2.connections.outgoing.length / v2.connections.incoming.length;
            if (rate1 == rate2) {
                return Vertex.compareByPosition(v1, v2) >= 0 ? v1 : v2;
            }
            return rate1 > rate2 ? v1 : v2;
        });
        return [ bestCandidate ];
    };
    AGN.Lib.WM.VertexGroup = VertexGroup;
})();

(function() {
    var Def = AGN.Lib.WM.Definitions, DateTimeUtils = AGN.Lib.WM.DateTimeUtils;
    var ENTITY_NAMES_BY_TYPE = {};
    var NodeTitleHelper = function() {};
    function getEntityNameByType(type, id, url) {
        if (id <= 0) {
            return "";
        }
        if (_.isEmpty(ENTITY_NAMES_BY_TYPE[type])) {
            $.ajax({
                url: AGN.url(url),
                async: false
            }).done(function(resp) {
                ENTITY_NAMES_BY_TYPE[type] = _.extend({}, resp);
            });
        }
        var name = ENTITY_NAMES_BY_TYPE[type][id];
        return !!name ? name : "";
    }
    NodeTitleHelper.getWebFormName = function(webFormId) {
        return getEntityNameByType("form", webFormId, "/workflow/ajax/getWebFormNames.action");
    };
    NodeTitleHelper.getTargetName = function(targetId) {
        return getEntityNameByType("target", targetId, "/workflow/ajax/getTargetNames.action");
    };
    NodeTitleHelper.getMailingName = function(mailingId) {
        return getEntityNameByType("mailing", mailingId, "/workflow/ajax/getMailingNames.action");
    };
    NodeTitleHelper.getArchiveName = function(archiveId) {
        return getEntityNameByType("archive", archiveId, "/workflow/ajax/getArchiveNames.action");
    };
    NodeTitleHelper.getAutoExportName = function(autoExportId) {
        return getEntityNameByType("autoExport", autoExportId, "/workflow/ajax/getAutoExportNames.action");
    };
    NodeTitleHelper.getAutoImportName = function(autoImportId) {
        return getEntityNameByType("autoImport", autoImportId, "/workflow/ajax/getAutoImportNames.action");
    };
    NodeTitleHelper.getMailinglistName = function(mailinglistId) {
        return getEntityNameByType("mailinglist", mailinglistId, "/workflow/ajax/getMailinglistNames.action");
    };
    function getReactionImage(reaction) {
        switch (reaction) {
          case Def.constants.reactionOpened:
            return "reaction_opened.png";

          case Def.constants.reactionNotOpened:
            return "reaction_notopened.png";

          case Def.constants.reactionClicked:
            return "reaction_clicked.png";

          case Def.constants.reactionNotClicked:
            return "reaction_notclicked.png";

          case Def.constants.reactionBought:
            return "reaction_bought.png";

          case Def.constants.reactionNotBought:
            return "reaction_notbought.png";

          case Def.constants.reactionChangeOfProfile:
            return "reaction_profilechange.png";

          case Def.constants.reactionWaitingForConfirm:
            return "reaction_wfc.png";

          case Def.constants.reactionOptIn:
            return "reaction_optin.png";

          case Def.constants.reactionOptOut:
            return "reaction_optout.png";

          case Def.constants.reactionClickedLink:
            return "reaction_clicked.png";

          case Def.constants.reactionOpenedAndClicked:
            return "reaction_profilechange.png";

          case Def.constants.reactionOpenedOrClicked:
            return "reaction_profilechange.png";
        }
    }
    function getReactionName(reaction) {
        switch (reaction) {
          case Def.constants.reactionOpened:
            return t("workflow.reaction.opened");

          case Def.constants.reactionNotOpened:
            return t("workflow.reaction.not_opened");

          case Def.constants.reactionClicked:
            return t("workflow.reaction.clicked");

          case Def.constants.reactionNotClicked:
            return t("workflow.reaction.not_clicked");

          case Def.constants.reactionBought:
            return t("workflow.reaction.bought");

          case Def.constants.reactionNotBought:
            return t("workflow.reaction.not_bought");

          case Def.constants.reactionChangeOfProfile:
            return t("workflow.reaction.change_of_profile");

          case Def.constants.reactionWaitingForConfirm:
            return t("workflow.reaction.waiting_for_confirm");

          case Def.constants.reactionOptIn:
            return t("workflow.reaction.opt_in");

          case Def.constants.reactionOptOut:
            return t("workflow.reaction.opt_out");

          case Def.constants.reactionClickedLink:
            return t("workflow.reaction.clicked_on_link");

          case Def.constants.reactionOpenedAndClicked:
            return t("workflow.reaction.opened_and_clicked");

          case Def.constants.reactionOpenedOrClicked:
            return t("workflow.reaction.opened_or_clicked");
        }
    }
    function getDelayUnitName(delayValue, delayUnit) {
        if (delayValue > 1) {
            switch (delayUnit) {
              case Def.constants.deadlineTimeUnitMinute:
                return t("workflow.deadline.minutes");

              case Def.constants.deadlineTimeUnitHour:
                return t("workflow.defaults.hours");

              case Def.constants.deadlineTimeUnitDay:
                return t("workflow.defaults.days");

              case Def.constants.deadlineTimeUnitWeek:
                return t("workflow.defaults.weeks");

              case Def.constants.deadlineTimeUnitMonth:
                return t("workflow.defaults.months");
            }
        } else {
            switch (delayUnit) {
              case Def.constants.deadlineTimeUnitMinute:
                return t("workflow.deadline.minute");

              case Def.constants.deadlineTimeUnitHour:
                return t("workflow.defaults.hour");

              case Def.constants.deadlineTimeUnitDay:
                return t("workflow.defaults.day");

              case Def.constants.deadlineTimeUnitWeek:
                return t("workflow.defaults.week");

              case Def.constants.deadlineTimeUnitMonth:
                return t("workflow.defaults.month");
            }
        }
    }
    function getDecisionCriteriaName(value) {
        switch (value) {
          case Def.constants.decisionAOCriteriaClickRate:
            return t("workflow.defaults.ckickrate");

          case Def.constants.decisionAOCriteriaOpenrate:
            return t("workflow.opening_rate");

          default:
            return t("workflow.statistic.revenue");
        }
    }
    function getCloseParenthesis(value) {
        switch (Number(value)) {
          case 1:
            return ")";

          case 0:
            return "";
        }
    }
    function getOpenParenthesis(value) {
        switch (Number(value)) {
          case 1:
            return "(";

          case 0:
            return "";
        }
    }
    function getProfileFieldValue(field, value) {
        if (field && Def.GENDER_PROFILE_FIELD === field.toLowerCase()) {
            return Def.constants.genderOptions[!value ? 0 : value];
        } else {
            return _.isEmpty(value) ? "" : value;
        }
    }
    function getRulesDescription(profileField, rules) {
        var rulesMsg = "";
        rules.forEach(function(rule) {
            rulesMsg += (_.isEmpty(rulesMsg) ? "" : " " + rule.chainOperator + " ") + getOpenParenthesis(rule.parenthesisOpened) + profileField + " " + Def.constants.operatorsMap[rule.primaryOperator] + " " + getProfileFieldValue(profileField, rule.primaryValue) + getCloseParenthesis(rule.parenthesisClosed);
        });
        return t("workflow.start.rule") + (!!rulesMsg ? ": " + rulesMsg : "");
    }
    function getTargetsDescription(targets, option) {
        var targetNames = [];
        for (var i = 0; i < Def.TITLE_MAX_TARGETS && i < targets.length; i++) {
            targetNames.push(NodeTitleHelper.getTargetName(targets[i]));
        }
        var separator = ", ";
        if (Def.constants.targetOptions[option]) {
            separator = " " + Def.constants.targetOptions[option] + " ";
        }
        if (targets.length > Def.TITLE_MAX_TARGETS) {
            return targetNames.join(separator) + " " + t("defaults.andMore", targets.length - Def.TITLE_MAX_TARGETS) + "...";
        } else {
            return targetNames.join(separator);
        }
    }
    function getDateDescription(date, hour, minute) {
        if (date) {
            if (arguments.length === 1) {
                return DateTimeUtils.getDateStr(date, Def.constants.localeDateTimePattern);
            } else {
                return DateTimeUtils.getDateTimeStr(date, hour, minute, Def.constants.localeDateTimePattern);
            }
        } else {
            return "";
        }
    }
    function getDelayDescription(value, timeUnit) {
        return value + " " + getDelayUnitName(value, timeUnit);
    }
    function getReactionDescription(reaction, mailingId) {
        return t("workflow.reaction.title") + ": " + getReactionName(reaction) + ",\n" + t("workflow.defaults.mailing") + ": " + NodeTitleHelper.getMailingName(mailingId);
    }
    function getAutoOptimizationDescription(criteria, threshold, date) {
        var description = getDecisionCriteriaName(criteria) + (_.isEmpty(threshold) ? "" : ": " + threshold) + "\n";
        if (!!date) {
            description += t("workflow.defaults.date") + ": " + getDateDescription(date);
        }
        return description;
    }
    function getDateBasedStartDescription(field, operator, value) {
        return field + " " + Def.constants.operatorsMap[operator] + (!value ? "" : " " + value);
    }
    function getFollowupMailingDescription(followUpMailingName, baseMailingName, reaction) {
        if (followUpMailingName) {
            if (baseMailingName) {
                return baseMailingName + " (" + getReactionName(reaction) + ") " + followUpMailingName;
            } else {
                return followUpMailingName;
            }
        }
    }
    function getRecipientDescription(mailinglistId, targets, targetsOption, showMailingList) {
        var title = "";
        if (showMailingList) {
            title += t("workflow.mailinglist.short") + ": " + NodeTitleHelper.getMailinglistName(mailinglistId);
        }
        if (!_.isEmpty(targets)) {
            if (!_.isEmpty(title)) {
                title += "\n";
            }
            title += t("workflow.target.short") + ": " + getTargetsDescription(targets, targetsOption);
        }
        return title;
    }
    NodeTitleHelper.positionTitle = function(node, anchorsInUse) {
        if (anchorsInUse[Def.BOTTOM]) {
            if (anchorsInUse[Def.LEFT]) {
                if (anchorsInUse[Def.RIGHT]) {
                    if (anchorsInUse[Def.TOP]) {
                        node.positionTitle(Def.BOTTOM);
                    } else {
                        node.positionTitle(Def.TOP);
                    }
                } else {
                    node.positionTitle(Def.RIGHT);
                }
            } else {
                node.positionTitle(Def.LEFT);
            }
        } else {
            node.positionTitle(Def.BOTTOM);
        }
    };
    var getStartNodeTitle = function(data) {
        var startType = data.startType;
        var title = "";
        if (Def.constants.startTypeDate === startType) {
            title = t("workflow.start.start_date") + ":\n" + getDateDescription(data.date, data.hour, data.minute);
        } else if (Def.constants.startTypeEvent === startType) {
            var eventType = data.event;
            if (Def.constants.startEventReaction === eventType) {
                title = t("workflow.start.start_event") + ":\n" + getReactionName(data.reaction) + ": (" + getDateDescription(data.date, data.hour, data.minute) + ")";
            } else if (Def.constants.startEventDate === eventType) {
                title = t("workflow.start.start_event") + ":\n" + getDateBasedStartDescription(data.dateProfileField, data.dateFieldOperator, data.dateFieldValue) + ":\n" + "(" + getDateDescription(data.date, data.hour, data.minute) + ")";
            }
        }
        return title;
    };
    var getStopNodeTitle = function(data, node, isNormalWorkflow) {
        var endType = data.endType;
        var title = "";
        if (Def.constants.endTypeDate === endType) {
            title = t("workflow.stop.end_date") + ":\n" + getDateDescription(data.date, data.hour, data.minute);
        } else if (Def.constants.endTypeAutomatic === endType) {
            title = isNormalWorkflow ? t("workflow.stop.automatic_end") : t("workflow.stop.open_end");
        }
        return title;
    };
    var getDeadlineNodeTitle = function(data) {
        var deadlineType = data.deadlineType;
        var title = "";
        if (Def.constants.deadlineTypeFixedDeadline === deadlineType) {
            title = t("workflow.deadline.title") + ":\n" + getDateDescription(data.date, data.hour, data.minute);
        } else if (Def.constants.deadlineTypeDelay === deadlineType) {
            title = t("workflow.defaults.delay") + ":\n" + getDelayDescription(data.delayValue, data.timeUnit);
        }
        return title;
    };
    var getDecisionNodeTitle = function(data) {
        var decisionType = data.decisionType;
        var title = "";
        if (Def.constants.decisionTypeAutoOptimization === decisionType) {
            title = t("workflow.mailing.autooptimization") + ":\n" + getAutoOptimizationDescription(data.aoDecisionCriteria, data.threshold, data.decisionDate);
        } else {
            if (Def.constants.decisionReaction === data.decisionCriteria) {
                title = t("workflow.decision") + ",\n" + getReactionDescription(data.reaction, data.mailingId);
            } else {
                title = t("workflow.decision") + ",\n" + getRulesDescription(data.profileField, data.rules);
            }
        }
        return title;
    };
    var getFollowUpMailingNodeTitle = function(data, node) {
        var baseMailingName, followUpMailingName;
        var title = node.getTitle();
        baseMailingName = NodeTitleHelper.getMailingName(data.baseMailingId) || "?";
        followUpMailingName = NodeTitleHelper.getMailingName(data.mailingId) || "?";
        var description = getFollowupMailingDescription(followUpMailingName, baseMailingName, data.decisionCriterion);
        if (description) {
            title = description;
        }
        return title;
    };
    var MAILING_TITLE_CONFIG = {
        title: function(data) {
            return NodeTitleHelper.getMailingName(data.mailingId);
        }
    };
    var TITLE_CONFIG = {
        "*": {
            overlayImage: {},
            overlayTitle: "",
            title: ""
        },
        start: {
            title: getStartNodeTitle,
            isImageAvailable: function(data) {
                return Def.constants.startTypeEvent === data.startType && Def.constants.startEventReaction === data.event;
            },
            overlayImage: function(data) {
                if (this.isImageAvailable(data)) {
                    return {
                        visible: true,
                        image: getReactionImage(data.reaction),
                        title: getReactionName(data.reaction)
                    };
                } else {
                    return {};
                }
            }
        },
        stop: {
            title: getStopNodeTitle
        },
        deadline: {
            title: getDeadlineNodeTitle
        },
        parameter: {
            title: "",
            overlayTitle: function(data) {
                return data.value;
            }
        },
        decision: {
            title: getDecisionNodeTitle,
            branches: {
                title: function() {
                    return {
                        positive: t("workflow.defaults.yes"),
                        negative: t("workflow.defaults.no")
                    };
                }
            }
        },
        recipient: {
            title: function(data, node) {
                return getRecipientDescription(data.mailinglistId, data.targets, data.targetsOption, !node.isInRecipientsChain());
            }
        },
        archive: {
            title: function(data) {
                return NodeTitleHelper.getArchiveName(data.campaignId);
            }
        },
        form: {
            title: function(data) {
                return NodeTitleHelper.getWebFormName(data.userFormId);
            }
        },
        mailing: MAILING_TITLE_CONFIG,
        mailing_mediatype_sms: MAILING_TITLE_CONFIG,
        mailing_mediatype_post: MAILING_TITLE_CONFIG,
        actionbased_mailing: MAILING_TITLE_CONFIG,
        datebased_mailing: MAILING_TITLE_CONFIG,
        followup_mailing: {
            title: getFollowUpMailingNodeTitle
        },
        import: {
            title: function(data) {
                return NodeTitleHelper.getAutoImportName(data.importexportId);
            }
        },
        export: {
            title: function(data) {
                return NodeTitleHelper.getAutoExportName(data.importexportId);
            }
        }
    };
    function ignoreUpdateTitle(node) {
        var type = node.getType();
        if (Def.NODE_TYPES_MAILING.includes(type) || Def.NODE_TYPES_IMPORT_EXPORT.includes(type)) {
            return !!node.getTitle();
        }
        return false;
    }
    NodeTitleHelper.getDecisionBranchesLabels = function() {
        return TITLE_CONFIG.decision.branches.title();
    };
    NodeTitleHelper.updateTitle = function(node, isNormalWorkflow, forceUpdate) {
        if (!forceUpdate && ignoreUpdateTitle(node)) {
            return;
        }
        if (!node.isFilled()) {
            node.setTitle("");
            node.setOverlayImage({});
            node.setOverlayTitle("");
            return;
        }
        node.setTitle(generateNodeTitle(node, isNormalWorkflow));
        node.setOverlayImage(generateOverlayImage(node));
        node.setOverlayTitle(generateOverlayTitle(node));
    };
    function generateOverlayImage(node) {
        return getConfiguration(node.getType(), "overlayImage", node.getData());
    }
    function generateOverlayTitle(node) {
        return getConfiguration(node.getType(), "overlayTitle", node.getData());
    }
    function generateNodeTitle(node, isNormalWorkflow) {
        return getConfiguration(node.getType(), "title", node.getData(), node, isNormalWorkflow);
    }
    function getConfiguration(type, configName) {
        var configs = TITLE_CONFIG[type];
        if (!configs.hasOwnProperty(configName)) {
            configs = TITLE_CONFIG["*"];
        }
        var config = configs[configName];
        var args = Array.prototype.slice.call(arguments, 2);
        return _.isFunction(config) ? config.apply(configs, args) : config;
    }
    AGN.Lib.WM.NodeTitleHelper = NodeTitleHelper;
})();

(function() {
    var Node = AGN.Lib.WM.Node, Def = AGN.Lib.WM.Definitions;
    var MinimapCanvas = function(minimap, selector, options) {
        this.minimap = minimap;
        this.$element = minimap.$container.find(selector);
        this.scale = 1;
    };
    MinimapCanvas.prototype.setScale = function(scale) {
        this.scale = scale;
    };
    MinimapCanvas.prototype.getScale = function() {
        return this.scale;
    };
    MinimapCanvas.prototype.getPosition = function() {
        var position = this.$element.position();
        return {
            x: position.left,
            y: position.top
        };
    };
    MinimapCanvas.prototype.update = function() {
        this.reset();
        var pureBox = this.minimap.getPureIconsBox();
        var padding = Def.MINIMAP_PADDING * 2;
        var width = pureBox.maxX - pureBox.minX + padding;
        var height = pureBox.maxY - pureBox.minY + padding;
        var xRatio = (this.minimap.getWidth() - padding) / width;
        var yRatio = (this.minimap.getHeight() - padding) / height;
        this.setScale(Math.min(xRatio, yRatio));
        var left = -pureBox.minX * this.scale + Def.MINIMAP_PADDING;
        var top = -pureBox.minY * this.scale + Def.MINIMAP_PADDING;
        this.$element.css({
            transform: "scale(" + this.scale + ")",
            width: width,
            height: height,
            left: left,
            top: top
        });
        this.renderIcons();
    };
    MinimapCanvas.prototype.renderIcons = function() {
        var self = this;
        this.minimap.getPureIconsPosition().forEach(function(position) {
            var $node = $('<div class="miniview-element"></div>').css({
                width: Def.NODE_SIZE,
                height: Def.NODE_SIZE,
                left: position.x,
                top: position.y
            });
            self.$element.append($node);
        });
    };
    MinimapCanvas.prototype.reset = function() {
        this.scale = 1;
        this.$element.css({
            transform: "scale(1)",
            width: 0,
            height: 0,
            left: 0,
            top: 0
        });
        this.$element.html("");
    };
    var MinimapPanner = function(minimap, selector, options) {
        this.minimap = minimap;
        this.$element = minimap.get$().find(selector);
        this.onDrag = _.isFunction(options.onPannerDrag) ? options.onPannerDrag : _.noop;
        this.containment = $.extend({
            mode: "",
            padding: 0
        }, options.containment);
        this.containmentBox = null;
        var self = this;
        var prevX = 0;
        var prevY = 0;
        this.$element.draggable({
            start: function(event, ui) {
                prevX = ui.position.left;
                prevY = ui.position.top;
                if (!self.containmentBox) {
                    self.containmentBox = self.getContainmentBox(self.containment);
                }
            },
            drag: function(event, ui) {
                var scale = self.getScale();
                if (self.containmentBox) {
                    var left = ui.position.left;
                    var top = ui.position.top;
                    if (left < self.containmentBox.minX) {
                        ui.position.left = self.containmentBox.minX;
                    } else if (left > self.containmentBox.maxX) {
                        ui.position.left = self.containmentBox.maxX;
                    }
                    if (top < self.containmentBox.minY) {
                        ui.position.top = self.containmentBox.minY;
                    } else if (top > self.containmentBox.maxY) {
                        ui.position.top = self.containmentBox.maxY;
                    }
                }
                var dX = (prevX - ui.position.left) / scale;
                var dY = (prevY - ui.position.top) / scale;
                prevX = ui.position.left;
                prevY = ui.position.top;
                self.onDrag.call(self, dX, dY);
            }
        });
    };
    MinimapPanner.prototype.getContainmentBox = function(options) {
        if (!options.mode || options.mode == "none") {
            return undefined;
        }
        var $minimap = this.minimap.get$();
        var scaledWidth = this.getScaledWidth();
        var scaledHeight = this.getScaledHeight();
        if (options.mode == "panner-box") {
            return {
                minX: -scaledWidth + options.padding,
                maxX: $minimap.width() - options.padding,
                minY: -scaledHeight + options.padding,
                maxY: $minimap.height() - options.padding
            };
        } else if (options.mode == "minimap-box") {
            return {
                minX: options.padding,
                maxX: Math.max(0, $minimap.width() - scaledWidth) - options.padding,
                minY: options.padding,
                maxY: Math.max(0, $minimap.height() - scaledHeight) - options.padding
            };
        }
        return undefined;
    };
    MinimapPanner.prototype.getScale = function() {
        return this.minimap.getMiniCanvasScale() / this.minimap.getCanvasZoom();
    };
    MinimapPanner.prototype.getScaledWidth = function() {
        return this.getWidth() * this.getScale();
    };
    MinimapPanner.prototype.getScaledHeight = function() {
        return this.getHeight() * this.getScale();
    };
    MinimapPanner.prototype.getWidth = function() {
        return this.$element.width();
    };
    MinimapPanner.prototype.getHeight = function() {
        return this.$element.height();
    };
    MinimapPanner.prototype.update = function() {
        var viewPortScreen = this.minimap.getCanvasParent$();
        var originWidth = viewPortScreen.width();
        var originHeight = viewPortScreen.height();
        var width = originWidth + Def.MINIMAP_PADDING * 2;
        var height = originHeight + Def.MINIMAP_PADDING * 2;
        this.$element.css({
            width: width,
            height: height
        });
        this.containmentBox = this.getContainmentBox(this.containment);
        this.updatePosition();
    };
    MinimapPanner.prototype.updatePosition = function() {
        var position = this.minimap.getCanvasPosition();
        var delta = this.minimap.getMiniCanvasPosition();
        var scale = this.getScale();
        var left = -position.x * scale + delta.x;
        var top = -position.y * scale + delta.y;
        this.$element.css({
            transform: "scale(" + scale + ")",
            left: left,
            top: top
        });
    };
    var Minimap = function(canvas, options) {
        this.$container = $("#minimap");
        this.canvas = canvas;
        this.$collapseBtn = this.$container.find(".minimap-collapse");
        this.miniCanvas = new MinimapCanvas(this, ".minimap-canvas", options);
        this.miniPanner = new MinimapPanner(this, ".minimap-panner", options);
        this.enabled = false;
        var self = this;
        this.$container.on("click", ".minimap-panner, .minimap-collapse", function(e) {
            e.preventFocusOnArea = true;
        });
        this.$collapseBtn.on("click", function(e) {
            self.collapseMinimap();
        });
        this.$container.on("click", function(e) {
            if (e.preventFocusOnArea) {
                return;
            }
            var rec = self.$container[0].getBoundingClientRect();
            var pX = e.clientX - rec.left;
            var pY = e.clientY - rec.top;
            self.focusOnClickedArea(pX, pY);
        });
    };
    Minimap.prototype.get$ = function() {
        return this.$container;
    };
    Minimap.prototype.getWidth = function() {
        return this.get$().width();
    };
    Minimap.prototype.getHeight = function() {
        return this.get$().height();
    };
    Minimap.prototype.moveCanvasTo = function(x, y) {
        this.canvas.moveTo(x, y);
    };
    Minimap.prototype.getCanvas$ = function() {
        return this.canvas.get$();
    };
    Minimap.prototype.getCanvasParent$ = function() {
        return this.canvas.get$().parent();
    };
    Minimap.prototype.focusOnClickedArea = function(pointerX, pointerY) {
        var miniCanvasPosition = this.getMiniCanvasPosition();
        var scale = this.getMiniPannerScale();
        var x = (pointerX - miniCanvasPosition.x) / scale;
        var y = (pointerY - miniCanvasPosition.y) / scale;
        var miniPannerCenter = this.getMiniPannerCenter();
        var zoom = this.getCanvasZoom();
        var centeredX = (x - miniPannerCenter.x) * zoom;
        var centeredY = (y - miniPannerCenter.y) * zoom;
        this.moveCanvasTo(-centeredX, -centeredY);
    };
    Minimap.prototype.collapseMinimap = function() {
        this.$container.toggleClass("minimap-collapsed");
        this.updateMinimap();
    };
    Minimap.prototype.getIcons = function() {
        return this.canvas.getIcons();
    };
    Minimap.prototype.getPureIconsPosition = function() {
        var zoom = this.getCanvasZoom();
        return this.getIcons().map(function($element) {
            var position = Node.getPosition($element);
            return {
                x: position.x / zoom,
                y: position.y / zoom
            };
        });
    };
    Minimap.prototype.getPureIconsBox = function() {
        return this.canvas.getPureIconsBox();
    };
    Minimap.prototype.getMiniCanvasScale = function() {
        return this.miniCanvas.getScale();
    };
    Minimap.prototype.getMiniCanvasPosition = function() {
        return this.miniCanvas.getPosition();
    };
    Minimap.prototype.getMiniPannerScale = function() {
        return this.miniCanvas.getScale();
    };
    Minimap.prototype.getMiniPannerCenter = function() {
        return {
            x: this.miniPanner.getWidth() / 2,
            y: this.miniPanner.getHeight() / 2
        };
    };
    Minimap.prototype.getCanvasZoom = function() {
        return this.canvas.getZoom();
    };
    Minimap.prototype.getCanvasPosition = function() {
        return this.canvas.getPosition();
    };
    Minimap.prototype.updateMinimap = function() {
        if (this.enabled) {
            this.miniCanvas.update();
            this.miniPanner.update();
        }
    };
    Minimap.prototype.onPanZoom = function() {
        if (this.enabled) {
            this.miniPanner.updatePosition();
        }
    };
    Minimap.prototype.setEnabled = function(isEnabled) {
        this.enabled = isEnabled;
        if (isEnabled) {
            this.updateMinimap();
            this.get$().show();
        } else {
            this.get$().hide();
        }
    };
    AGN.Lib.WM.Minimap = Minimap;
})();

(function() {
    var Def = AGN.Lib.WM.Definitions, Node = AGN.Lib.WM.Node, Minimap = AGN.Lib.WM.Minimap;
    var Canvas = function($canvas) {
        var self = this;
        this.$canvas = $canvas;
        this.mouseWheelZoomEnabled = false;
        this.panningEnabled = false;
        this.zoomEventHandler = null;
        this.moveEventHandler = null;
        this.ignoreNextZoomEvent = false;
        this.minimap = new Minimap(this, {
            containment: {
                mode: "panner-box",
                padding: 5
            },
            onPannerDrag: function(dX, dY) {
                if (dX || dY) {
                    var position = self.getPosition();
                    self.moveTo(position.x + dX, position.y + dY);
                }
            }
        });
        this.panzoom = panzoom($canvas[0], {
            minZoom: Def.MIN_ZOOM,
            maxZoom: Def.MAX_ZOOM,
            initialZoom: Def.DEFAULT_ZOOM,
            disableKeyboardInteraction: true,
            smoothScroll: false,
            onDoubleClick: function() {
                return false;
            },
            beforeWheel: function() {
                return !self.mouseWheelZoomEnabled;
            },
            beforeMouseDown: function() {
                return !self.panningEnabled;
            }
        });
        this.panzoom.on("zoom", function() {
            if (self.zoomEventHandler) {
                if (self.ignoreNextZoomEvent) {
                    self.ignoreNextZoomEvent = false;
                } else {
                    self.zoomEventHandler.call(null, self.getZoom());
                    self.minimap.onPanZoom();
                }
            }
        });
        this.panzoom.on("pan", function() {
            self.minimap.onPanZoom();
            if (self.moveEventHandler) {
                self.moveEventHandler.call(null, self.getPosition());
            }
        });
    };
    Canvas.prototype.get$ = function() {
        return this.$canvas;
    };
    Canvas.prototype.setMinimapEnabled = function(isEnabled) {
        this.minimap.setEnabled(isEnabled);
    };
    Canvas.prototype.updateMinimap = function() {
        this.minimap.updateMinimap();
    };
    Canvas.prototype.setPanningEnabled = function(isEnabled) {
        this.panningEnabled = !!isEnabled;
    };
    Canvas.prototype.setMouseWheelZoomEnabled = function(isEnabled) {
        this.mouseWheelZoomEnabled = isEnabled;
    };
    Canvas.prototype.getZoom = function() {
        var transform = this.panzoom.getTransform();
        return transform.scale;
    };
    Canvas.prototype.getPosition = function() {
        var transform = this.panzoom.getTransform();
        return {
            x: transform.x,
            y: transform.y
        };
    };
    Canvas.prototype.getVisibleArea = function() {
        var $viewport = this.$canvas.parent();
        var viewportWidth = $viewport.width();
        var viewportHeight = $viewport.height();
        var transform = this.panzoom.getTransform();
        return {
            minX: -transform.x / transform.scale,
            minY: -transform.y / transform.scale,
            maxX: (viewportWidth - transform.x) / transform.scale,
            maxY: (viewportHeight - transform.y) / transform.scale
        };
    };
    Canvas.prototype.moveTo = function(x, y) {
        this.panzoom.moveTo(x, y);
    };
    Canvas.prototype.setZoom = function(scale) {
        var transform = this.panzoom.getTransform();
        this.ignoreNextZoomEvent = true;
        this.panzoom.zoomAbs(transform.x, transform.y, scale);
        this.minimap.onPanZoom();
    };
    Canvas.prototype.setOnZoom = function(handler) {
        this.zoomEventHandler = handler;
    };
    Canvas.prototype.setOnMove = function(handler) {
        this.moveEventHandler = handler;
    };
    Canvas.prototype.getCanvasParent$ = function() {
        return this.get$().parent();
    };
    Canvas.prototype.getIcons = function() {
        var icons = [];
        this.get$().children(".node").each(function(index, element) {
            icons.push($(element));
        });
        return icons;
    };
    Canvas.prototype.getPureIconsBox = function() {
        var icons = this.getIcons();
        var zoom = this.getZoom();
        if (icons.length) {
            var box = icons.map(function($node) {
                return Node.getBox($node);
            }).reduce(function(result, current, index) {
                return {
                    minX: Math.min(result.minX, current.minX),
                    minY: Math.min(result.minY, current.minY),
                    maxX: Math.max(result.maxX, current.maxX),
                    maxY: Math.max(result.maxY, current.maxY)
                };
            });
            return {
                minX: box.minX / zoom - Def.CANVAS_GRID_SIZE,
                minY: box.minY / zoom - Def.CANVAS_GRID_SIZE,
                maxX: box.maxX / zoom + Def.CANVAS_GRID_SIZE,
                maxY: box.maxY / zoom + Def.CANVAS_GRID_SIZE
            };
        } else {
            var $viewport = this.getCanvasParent$();
            return {
                minX: -Def.CANVAS_GRID_SIZE,
                minY: -Def.CANVAS_GRID_SIZE,
                maxX: $viewport.width() / zoom + Def.CANVAS_GRID_SIZE,
                maxY: $viewport.height() / zoom + Def.CANVAS_GRID_SIZE
            };
        }
    };
    Canvas.prototype.fitPdfPage = function(size, orientation) {
        var box = this.getPureIconsBox();
        var width = box.maxX - box.minX + Def.NODE_MIN_MARGIN;
        var height = box.maxY - box.minY + Def.NODE_MIN_MARGIN;
        if (!Def.PAGE_DIMENSIONS[size]) {
            return;
        }
        var pageDimension = Def.PAGE_DIMENSIONS[size];
        var isLandscape = orientation == "landscape";
        var sceneWidth = isLandscape ? pageDimension.height : pageDimension.width;
        var sceneHeight = isLandscape ? pageDimension.width : pageDimension.height;
        var transformX = 0;
        var transformY = 0;
        var scale = 1;
        if (width > sceneWidth || height > sceneHeight) {
            if (width / height < sceneWidth / sceneHeight) {
                scale = sceneHeight / height;
            } else {
                scale = sceneWidth / width;
            }
        }
        if (box.minX < 0) {
            transformX = -box.minX * scale;
        }
        if (box.minY < 0) {
            transformY = -box.minY * scale;
        }
        var transformCss = "matrix(" + scale + ", 0, 0, " + scale + ", " + transformX + ", " + transformY + ")";
        var transformOrigin = "left top 0";
        this.getCanvasParent$().css({
            transform: transformCss,
            "-webkit-transform": transformCss,
            "transform-origin": transformOrigin,
            "-webkit-transform-origin": transformOrigin,
            "backface-visibility": "hidden",
            "-webkit-backface-visibility": "hidden",
            overflow: "visible"
        });
    };
    AGN.Lib.WM.Canvas = Canvas;
})();

(function() {
    var Def = AGN.Lib.WM.Definitions, Confirm = AGN.Lib.Confirm;
    var Dialogs = {
        Activation: activationDialog,
        Deactivation: deactivationDialog,
        confirmSaveBeforePdfGenerating: confirmSaveBeforePdfGeneratingDialog,
        confirmTestingStartStop: confirmTestingStartStop,
        confirmMailingDataTransfer: confirmMailingDataTransfer,
        confirmOwnWorkflowExpanding: confirmOwnWorkflowExpanding,
        confirmCopy: confirmCopy
    };
    function activationDialog(onSuccess, mailingNames, isUnpause) {
        var $activatingDialog = $("#activating-campaign-dialog");
        if (!isUnpause) {
            $("#activating-campaign-mailings").html(mailingNames);
        }
        $activatingDialog.css("visibility", "visible");
        $activatingDialog.show();
        var activateBtn = $("#activating-campaign-activate-button");
        activateBtn.off("click");
        activateBtn.on("click", function() {
            onSuccess();
            $activatingDialog.dialog("close");
            return false;
        });
        $activatingDialog.dialog({
            open: function() {
                var title = $activatingDialog.parent().find(".ui-dialog-title");
                title.empty();
                title.append('<span class="dialog-title-image">' + t(isUnpause ? "workflow.activating.unpauseTitle" : "workflow.activating.title") + "</span>");
                title.find(".dialog-title-image").css("padding-left", "0px");
            },
            modal: true,
            resizable: false,
            width: 650,
            minHeight: 0,
            close: function() {
                return false;
            }
        });
    }
    function deactivationDialog(onSuccess) {
        var $inactivatingDialog = $("#inactivating-campaign-dialog");
        $inactivatingDialog.css("visibility", "visible");
        $inactivatingDialog.show();
        var deactivatingBtn = $("#inactivating-campaign-inactivate-button");
        deactivatingBtn.off("click");
        deactivatingBtn.on("click", function() {
            onSuccess();
            $inactivatingDialog.dialog("close");
            return false;
        });
        $inactivatingDialog.dialog({
            open: function() {
                var title = $inactivatingDialog.parent().find(".ui-dialog-title");
                title.empty();
                title.append('<span class="dialog-title-image">' + t("workflow.inactivating.title") + "</span>");
                title.find(".dialog-title-image").css("padding-left", "0px");
            },
            modal: true,
            resizable: false,
            width: 650,
            minHeight: 0,
            close: function() {
                return false;
            }
        });
    }
    function confirmMailingDataTransfer(paramsToAsk) {
        return Confirm.createFromTemplate({
            Def: Def,
            paramsToAsk: paramsToAsk
        }, "mailing-data-transfer-modal");
    }
    function confirmOwnWorkflowExpanding() {
        return Confirm.createFromTemplate({}, "own-workflow-expanding-modal");
    }
    function confirmSaveBeforePdfGeneratingDialog(onSuccess, message) {
        var $beforePdfGeneratingDialog = $("#workflow-save-before-pdf-dialog");
        var $cancelBtn = $("#save-before-pdf-btn-cancel");
        $cancelBtn.off("click");
        $cancelBtn.on("click", function() {
            $beforePdfGeneratingDialog.dialog("close");
            return false;
        });
        if (_.isFunction(onSuccess)) {
            onSuccess = _.noop;
        }
        var $saveBtn = $("#save-before-pdf-btn-save");
        $saveBtn.off("click");
        $saveBtn.on("click", function() {
            onSuccess();
            $beforePdfGeneratingDialog.dialog("close");
            return false;
        });
        $("#workflow-save-before-pdf-dialog .dialog-message").html(message);
        $beforePdfGeneratingDialog.dialog({
            title: '<span class="dialog-fat-title">' + t("workflow.pdf.save_campaign") + "</span>",
            dialogClass: "no-close",
            width: 650,
            modal: true,
            resizable: false,
            close: function() {
                return false;
            }
        });
    }
    function confirmTestingStartStop(isStartTesting) {
        return Confirm.createFromTemplate({
            startTesting: isStartTesting,
            shortname: Def.shortname
        }, "testing-modal");
    }
    function confirmCopy(hasContent) {
        return Confirm.createFromTemplate({
            hasContent: hasContent === true
        }, "workflow-copy-modal");
    }
    AGN.Lib.WM.Dialogs = Dialogs;
})();

(function() {
    var Def = AGN.Lib.WM.Definitions, Node = AGN.Lib.WM.Node;
    var Snippets = {};
    Snippets.loadSample = function(type, gridEnabled, callback) {
        if ([ Def.NODE_TYPE_SC_ABTEST, Def.NODE_TYPE_SC_BIRTHDAY, Def.NODE_TYPE_SC_DOI ].includes(type)) {
            $.ajax({
                url: AGN.url("/workflow/getSampleWorkflowContent.action"),
                type: "POST",
                async: false,
                data: {
                    type: type,
                    gridEnabled: gridEnabled
                },
                success: asDeserializationCallback(callback)
            });
        } else {
            console.error("Unknown sample type: " + type);
        }
    };
    Snippets.loadOwnWorkflow = function(workflowId, copyContent, callback) {
        $.ajax({
            url: AGN.url("/workflow/getWorkflowContent.action"),
            type: "POST",
            async: false,
            data: {
                workflowId: workflowId,
                isWithContent: copyContent
            },
            success: asDeserializationCallback(callback)
        });
    };
    Snippets.removeStartStop = function(nodes, connections, removeStart, removeStop) {
        if (removeStart || removeStop) {
            var removedNodes = [];
            var newNodes = nodes.filter(function(node) {
                var type = node.getType();
                if (removeStart && type === Def.NODE_TYPE_START || removeStop && type === Def.NODE_TYPE_STOP) {
                    removedNodes.push(node);
                    return false;
                } else {
                    return true;
                }
            });
            if (newNodes.length < nodes.length) {
                Array.prototype.splice.apply(nodes, [ 0, nodes.length ].concat(newNodes));
                var newConnections = connections.filter(function(connection) {
                    return !(removedNodes.includes(connection.source) || removedNodes.includes(connection.target));
                });
                if (newConnections.length < connections.length) {
                    Array.prototype.splice.apply(connections, [ 0, connections.length ].concat(newConnections));
                }
            }
        }
    };
    Snippets.adjustPositions = function(nodes, snippetStartX, snippetStartY, useStartPositionNode) {
        var startingX = 0, startingY = 0;
        if (useStartPositionNode) {
            var node = getStartPositionNode(nodes);
            startingX = node.getX();
            startingY = node.getY();
        } else {
            var minX = 0, maxX = 0, minY = 0, maxY = 0;
            var first = true;
            nodes.forEach(function(node) {
                if (first) {
                    minX = maxX = node.getX();
                    minY = maxY = node.getY();
                    first = false;
                } else {
                    minX = Math.min(minX, node.getX());
                    maxX = Math.max(maxX, node.getX());
                    minY = Math.min(minY, node.getY());
                    maxY = Math.max(maxY, node.getY());
                }
            });
            startingX = Math.round((minX + maxX) / 2);
            startingY = Math.round((minY + maxY) / 2);
        }
        nodes.forEach(function(node) {
            node.setCoordinates(snippetStartX + node.getX() - startingX, snippetStartY + node.getY() - startingY);
        });
    };
    function asDeserializationCallback(callback) {
        return function(icons) {
            var nodes = icons.map(Node.deserialize);
            var connections = Node.deserializeConnections(icons, Node.toMap(nodes));
            callback.call(null, nodes, connections);
        };
    }
    function getStartPositionNode(nodes) {
        var candidates = nodes.filter(function(node) {
            return Def.NODE_TYPE_START == node.getType();
        });
        if (candidates.length == 0) {
            candidates = nodes;
        }
        if (candidates.length > 1) {
            return candidates.reduce(function(node1, node2) {
                if (node1.getX() == node2.getX()) {
                    return node1.getY() < node2.getY() ? node1 : node2;
                } else {
                    return node1.getX() < node2.getX() ? node1 : node2;
                }
            });
        } else {
            return candidates[0];
        }
    }
    AGN.Lib.WM.Snippets = Snippets;
})();

(function() {
    var Def = AGN.Lib.WM.Definitions, Node = AGN.Lib.WM.Node;
    var SELECTOR = ".js-draggable-button";
    function hasCollision(occupiedAreas, ui) {
        var newNodeBox = Node.getCollisionBox(ui.helper);
        return occupiedAreas.some(function(box) {
            return Node.detectBoxCollision(newNodeBox, box);
        });
    }
    function DraggableButtons(options) {
        this.enabled = !!options.enabled;
        this.$buttons = $(SELECTOR);
        var self = this;
        this.$buttons.each(function() {
            var $button = $(this);
            var type = $button.data("type");
            var occupiedAreas = [];
            $button.draggable({
                revert: true,
                revertDuration: 0,
                zIndex: Def.Z_INDEX_DRAGGABLE_BUTTON,
                disabled: !self.enabled,
                cursorAt: function() {
                    var rect = this.helper[0].getBoundingClientRect();
                    return [ rect.width / 2 - 1, rect.height / 2 ];
                },
                appendTo: "#canvas",
                helper: function() {
                    return Node.createDraggable$(type);
                },
                start: function() {
                    occupiedAreas = options.getOccupiesAreas.call(self);
                    options.onStart.call(self);
                },
                stop: function() {
                    options.onStop.call(self);
                },
                drag: function(event, ui) {
                    var scale = options.getZoom.call(self);
                    ui.position.left = Math.round(ui.position.left / scale / Def.CANVAS_GRID_SIZE) * Def.CANVAS_GRID_SIZE;
                    ui.position.top = Math.round(ui.position.top / scale / Def.CANVAS_GRID_SIZE) * Def.CANVAS_GRID_SIZE;
                    ui.helper.toggleClass("js-collision-detected", hasCollision(occupiedAreas, ui, scale));
                }
            }).on("dblclick", function() {
                if (self.enabled) {
                    options.onDrop.call(self, type);
                }
            });
        });
        $("#viewPort").droppable({
            accept: SELECTOR,
            tolerance: "fit",
            drop: function(event, ui) {
                if (ui.helper.hasClass("js-collision-detected")) {
                    return;
                }
                var scale = options.getZoom.call(self);
                var containerOffset = $("#canvas").offset();
                var x = Math.round((ui.offset.left - containerOffset.left) / scale);
                var y = Math.round((ui.offset.top - containerOffset.top) / scale);
                options.onDrop.call(self, ui.helper.data("type"), {
                    x: Math.round(x / Def.CANVAS_GRID_SIZE),
                    y: Math.round(y / Def.CANVAS_GRID_SIZE)
                });
            }
        });
    }
    DraggableButtons.prototype.setEnabled = function(isEnabled) {
        this.enabled = !!isEnabled;
        this.$buttons.draggable("option", "disabled", !isEnabled);
    };
    AGN.Lib.WM.DraggableButtons = DraggableButtons;
})();

(function() {
    var Def = AGN.Lib.WM.Definitions, Vertex = AGN.Lib.WM.Vertex, VertexGroup = AGN.Lib.WM.VertexGroup;
    function PreAlignedGroup(layers, height) {
        this.layers = layers;
        this.height = height;
    }
    PreAlignedGroup.fromVertexGroup = function(vertexGroup) {
        var layers = [];
        var visitedIds = {};
        var layer = Vertex.filterUnvisited(vertexGroup.getStartingVertices(), visitedIds);
        var height = 0;
        while (layer.length) {
            height = Math.max(height, layer.length);
            layers.push(layer);
            layer = _.flatMap(layer, function(vertex) {
                return Vertex.filterUnvisited(vertex.rightSiblingsOrdered(), visitedIds);
            });
        }
        return new PreAlignedGroup(layers, height);
    };
    PreAlignedGroup.prototype.align = function(startX, maxHeight) {
        var previousLayer = null;
        this.layers.forEach(function(layer) {
            var startY = Math.max(Math.round(Def.AUTO_ALIGN_STEP_Y * (maxHeight - layer.length) / 2), 1);
            if (previousLayer) {
                var nodesNumberDelta = Math.abs(previousLayer.length - layer.length);
                if (nodesNumberDelta > 1) {
                    startX += Math.round(Def.AUTO_ALIGN_EXTRA_STEP_X * nodesNumberDelta);
                }
            }
            layer.forEach(function(vertex) {
                vertex.node.setCoordinates(startX, startY);
                startY += Def.AUTO_ALIGN_STEP_Y;
            });
            startX += Def.AUTO_ALIGN_STEP_X;
            previousLayer = layer;
        });
        return startX;
    };
    function align(vertices) {
        var preAlignedGroups = VertexGroup.detectGroups(vertices).map(function(vertexGroup) {
            return PreAlignedGroup.fromVertexGroup(vertexGroup);
        });
        var maxHeight = 0;
        preAlignedGroups.forEach(function(group) {
            maxHeight = Math.max(maxHeight, group.height);
        });
        var startX = 1;
        preAlignedGroups.forEach(function(group) {
            startX = group.align(startX, maxHeight);
            startX += Def.AUTO_ALIGN_STEP_BETWEEN_GROUPS;
        });
    }
    AGN.Lib.WM.AutoAlignment = {
        align: align
    };
})();

(function() {
    var Def = AGN.Lib.WM.Definitions, Node = AGN.Lib.WM.Node;
    function UndoStack(maxLength) {
        this.maxLength = maxLength;
        this._undoStack = [];
        this._transactionStack = [];
        this._transaction = false;
    }
    UndoStack.prototype.add = function(stack) {
        while (this._undoStack.length >= this.maxLength) {
            this._undoStack.shift();
        }
        this._undoStack.push(stack);
    };
    UndoStack.prototype.pop = function() {
        return this._undoStack.pop();
    };
    UndoStack.prototype.addOperation = function(operation) {
        this._transactionStack.push(operation);
    };
    UndoStack.prototype.isEmpty = function() {
        return _.isEmpty(this._undoStack);
    };
    UndoStack.prototype.startTransaction = function() {
        this._transaction = true;
    };
    UndoStack.prototype.endTransaction = function() {
        this.flush();
        this._transaction = false;
    };
    UndoStack.prototype.flush = function() {
        if (!_.isEmpty(this._transactionStack)) {
            this.add(this._transactionStack);
        }
        this._transactionStack = [];
    };
    UndoStack.prototype.isTransactionStarted = function() {
        return this._transaction === true;
    };
    function UndoManager(editor, options) {
        this.editor = editor;
        this.undoOperations = {
            nodeAdded: this.undoAddNode,
            nodeDeleted: this.undoDeleteNode,
            nodeMoved: this.undoMoveNode,
            nodeDataUpdated: this.undoSaveNodeData,
            connectionCreated: this.undoCreateConnection,
            connectionDeleted: this.undoDeleteConnection
        };
        this.manualStart = false;
        this.undoStack = new UndoStack(Def.MAX_UNDO_STEP);
        this.onChange = _.isFunction(options.onChange) ? options.onChange : _.noop;
    }
    UndoManager.prototype.undoAddNode = function(node) {
        this.editor.deleteNode(node);
    };
    UndoManager.prototype.undoDeleteNode = function(node) {
        if (node instanceof Node) {
            this.editor.add(Node.restore(node));
        } else {
            this.editor.add(Node.get(node));
        }
    };
    UndoManager.prototype.undoCreateConnection = function(connection) {
        this.editor.deleteConnectionBetween(connection.source, connection.target);
    };
    UndoManager.prototype.undoDeleteConnection = function(connection) {
        this.editor.connect(Node.get(connection.source), Node.get(connection.target));
    };
    UndoManager.prototype.undoMoveNode = function(movingData) {
        var scale = this.editor.getZoom();
        var self = this;
        movingData.forEach(function(data) {
            data.node.setTitleEnabled(false);
        });
        this.editor.batch(function() {
            movingData.forEach(function(data) {
                var coordinates = data.coordinates;
                var node = data.node;
                if (self.editor.getCurrentDragMode() !== data.dragMode) {
                    self.editor.convertCoordinates(coordinates);
                }
                node.setCoordinates(coordinates.x, coordinates.y);
                node.updateCoordinates(scale);
            });
            self.editor.updateOverlays();
            self.editor.positionTitles();
            self.editor.updateMinimap();
        });
        movingData.forEach(function(data) {
            data.node.setTitleEnabled(true);
        });
    };
    UndoManager.prototype.undoSaveNodeData = function(node, undoNode) {
        undoNode = undoNode instanceof Node ? undoNode : Node.get(undoNode);
        node = node instanceof Node ? node : Node.get(node);
        node.setTitle(undoNode.getTitle());
        node.setOverlayTitle(undoNode.getOverlayTitle());
        node.setOverlayImage(undoNode.getOverlayImage());
        node.setComment(undoNode.getComment());
        node.setFilled(undoNode.isFilled());
        node.setDependent(undoNode.isDependent());
        node.setInRecipientsChain(undoNode.isInRecipientsChain());
        node.setData(undoNode.getData());
        this.editor.positionTitles();
    };
    UndoManager.prototype.canUndo = function() {
        return !this.undoStack.isEmpty();
    };
    UndoManager.prototype.startTransaction = function() {
        this.manualStart = true;
        this.undoStack.startTransaction();
    };
    UndoManager.prototype.endTransaction = function() {
        this.undoStack.endTransaction();
        this.onChange();
        this.manualStart = false;
    };
    UndoManager.prototype.transaction = function(targetFunc) {
        if (_.isFunction(targetFunc)) {
            if (!this.undoStack.isTransactionStarted()) {
                this.manualStart = false;
                this.undoStack.startTransaction();
            }
            targetFunc.call();
            if (!this.manualStart) {
                this.undoStack.endTransaction();
            }
            this.onChange();
        }
    };
    UndoManager.prototype.operation = function(operation) {
        if (this.undoStack.isTransactionStarted()) {
            var args = [].slice.call(arguments);
            args.shift();
            this.undoStack.addOperation({
                operation: operation,
                args: args
            });
        }
    };
    UndoManager.prototype.undo = function() {
        if (this.canUndo()) {
            var operations = this.undoStack.pop();
            var compareFn = function(op1, op2) {
                var o1 = op1.operation;
                var o2 = op2.operation;
                var nodeChanges = [ "nodeAdded", "nodeDeleted", "nodeDataUpdated" ];
                var connectionChanges = [ "connectionCreated", "connectionDeleted" ];
                if (connectionChanges.includes(o1) && nodeChanges.includes(o2)) {
                    return 1;
                }
                if (nodeChanges.includes(o1) && connectionChanges.includes(o2)) {
                    return -1;
                }
                return 0;
            };
            var self = this;
            this.editor.batch(function() {
                operations.sort(compareFn).forEach(function(operation) {
                    var undoFunc = self.undoOperations[operation.operation];
                    if (undoFunc) {
                        undoFunc.apply(self, operation.args);
                    }
                });
            });
            this.onChange();
        }
    };
    AGN.Lib.WM.UndoManager = UndoManager;
})();

(function() {
    var Def = AGN.Lib.WM.Definitions, Select = AGN.Lib.Select;
    var EditorsHelper = function() {
        var options = {};
        this.editors = [];
        this.curEditor;
        this.curEditingNode;
        this.getCurrentNode = function() {
            return this.curEditingNode;
        };
        this.getCurrentNodeId = function() {
            return this.curEditingNode.getId();
        };
        this.getCurrentNodeAnchorsInUse = function() {
            if (options.getNodeAnchorsInUse) {
                return options.getNodeAnchorsInUse(this.curEditingNode);
            }
            return {};
        };
        this.getCurrentEditor = function() {
            return this.curEditor;
        };
        this.assignOptions = function(newOptions) {
            $.extend(options, newOptions);
        };
        this.registerEditor = function(name, editor) {
            return this.editors[name] = editor;
        };
        this.isPausedWorkflow = function() {
            return $("#workflow-status").val() === Def.constants.statusPaused;
        };
        this._notAllowedToChangeDuringPause = function(node) {
            return this.isPausedWorkflow() && !_.union(Def.NODE_TYPES_MAILING, [ Def.NODE_TYPE_STOP ]).includes(node.getType());
        };
        this.showEditDialog = function(node, isActivatedWorkflow) {
            var self = this;
            var nodeType = node.getType();
            this.curEditingNode = node;
            this.curEditor = this.editors[nodeType];
            this.curEditor.fillEditor(node);
            this.getEditorPanel(nodeType).dialog({
                open: function(event) {
                    var $panel = $(this);
                    var title = $panel.parent().find(".ui-dialog-title");
                    title.empty();
                    title.append($('<span class="dialog-title-image">' + self.curEditor.getTitle() + "</span>"));
                    title.find(".dialog-title-image").attr("data-type", nodeType);
                    if (nodeType == Def.NODE_TYPE_RECIPIENT) {
                        $panel.parent().find(".recipient-editor-select").prop("disabled", node.isDependent() || node.isInRecipientsChain());
                    }
                    $(event.target).find(".js-datepicker").each(function(index, element) {
                        var $datepicker = $(element).pickadate("picker");
                        $datepicker.set("select", $datepicker.get("select"));
                    });
                    if (isActivatedWorkflow || self._notAllowedToChangeDuringPause(self.curEditingNode)) {
                        disableDialogItems($(event.target));
                    }
                },
                close: function() {
                    if (self.curEditor.closeEditor) {
                        self.curEditor.closeEditor();
                    }
                },
                width: 650,
                height: "auto",
                minHeight: "auto",
                modal: true,
                resizable: false
            });
        };
        this.showIconCommentDialog = function(node) {
            var self = this;
            this.curEditingNode = node;
            this.curEditor = this.editors["icon-comment"];
            this.curEditor.fillEditor(node);
            this.getEditorPanel("icon-comment").dialog({
                open: function() {
                    self.getEditorPanel("icon-comment").parent().find(".ui-dialog-titlebar").hide();
                },
                width: 300,
                height: "auto",
                minHeight: "auto",
                modal: true,
                resizable: false,
                fluid: true,
                position: {
                    my: "left top",
                    at: "left bottom",
                    of: node.get$()
                }
            });
        };
        this.saveIconComment = function(iconComment) {
            var self = this;
            options.getUndoManager().transaction(function() {
                var node = self.curEditingNode;
                options.getUndoManager().operation("nodeDataUpdated", node, _.cloneDeep(node));
                node.setComment(iconComment);
                options.onChange(node);
            });
        };
        this.saveCurrentEditorWithUndo = function(leaveOpen, mailingEditorBase) {
            var self = this;
            _.defer(function() {
                options.getUndoManager().startTransaction();
                self.saveCurrentEditor(leaveOpen, mailingEditorBase, function() {
                    options.getUndoManager().endTransaction();
                });
            });
        };
        this.saveCurrentEditor = function(leaveOpen, mailingEditorBase, undoCallback) {
            undoCallback = _.isFunction(undoCallback) ? undoCallback : _.noop;
            var self = this;
            var node = this.curEditingNode;
            options.getUndoManager().operation("nodeDataUpdated", node, _.cloneDeep(node), self.curEditor);
            var editorData = self.curEditor.saveEditor();
            if (!leaveOpen) {
                self.cancelEditor();
            }
            if (self.isNodeIsMailing(node)) {
                var mailingId = editorData.mailingId;
                if (mailingEditorBase) {
                    mailingEditorBase.checkDifferentMailingLists(mailingId, function(mailingContent) {
                        self.mailingSpecificSave(leaveOpen, mailingContent, editorData, mailingEditorBase);
                        undoCallback();
                    }, function(mailingContent) {
                        self.curEditor.storedMailingContent = mailingContent;
                        self.curEditor.storedMailingId = mailingId;
                        self.curEditor.storedLeaveOpen = leaveOpen;
                        self.curEditor.storedEditorData = editorData;
                        mailingEditorBase.initOneMailinglistWarningDialog(mailingEditorBase);
                        undoCallback();
                    });
                }
            } else {
                $.extend(node.getData(), editorData);
                if (!node.isFilled()) {
                    node.setFilled(true);
                }
                if (node.isFilled() && _.isFunction(self.curEditor.isSetFilledAllowed)) {
                    if (!self.curEditor.isSetFilledAllowed()) {
                        node.setFilled(false);
                    }
                }
                if (options.supplement) {
                    options.supplement(node);
                }
                if (options.onChange) {
                    options.onChange(node);
                }
                undoCallback();
            }
        };
        this.resave = function(node) {
            var bkpNode = this.curEditingNode;
            var exEditor = this.curEditor;
            try {
                this.curEditingNode = node;
                this.curEditor = this.editors[node.getType()];
                this.curEditor.fillEditor(node);
                this.saveCurrentEditor();
            } finally {
                this.curEditingNode = bkpNode;
                this.curEditor = exEditor;
            }
        };
        this.modify = function(node, callback) {
            options.getUndoManager().operation("nodeDataUpdated", node, _.cloneDeep(node));
            callback(node);
            if (options.onChange) {
                options.onChange(node);
            }
        };
        this.isNodeIsMailing = function(node) {
            return Def.NODE_TYPES_MAILING.includes(node.getType());
        };
        this.mailingSpecificSave = function(leaveOpen, mailingContent, editorData, mailingEditorBase) {
            var self = this;
            var node = this.curEditingNode;
            var data = node.getData();
            $.extend(data, editorData);
            if (node.isFilled() && _.isFunction(self.curEditor.isSetFilledAllowed)) {
                if (!self.curEditor.isSetFilledAllowed()) {
                    node.setFilled(false);
                }
            }
            if (options.supplement) {
                options.supplement(node, mailingEditorBase, mailingContent);
            }
            if (options.onChange) {
                options.onChange(node);
            }
        };
        this.mailingSpecificSaveAfterMailinglistCheckModal = function(mailingEditorBase) {
            this.curEditor.storedMailingContent.mailinglistId = mailingEditorBase.configuredMailingData.mailinglistId;
            this.mailingSpecificSave(this.curEditor.storedLeaveOpen, this.curEditor.storedMailingContent, this.curEditor.storedEditorData, mailingEditorBase);
        };
        this.cancelEditor = function() {
            var nodeType = this.curEditingNode.getType();
            var $panel = this.getEditorPanel(nodeType);
            if ($panel.dialog("instance")) {
                $panel.dialog("close");
            }
        };
        this.getEditorPanel = function(type) {
            var editorType = type == "stop" ? "start" : type;
            return $("#" + editorType + "-editor");
        };
        this.formToObject = function(formName) {
            var formData = $('form[name="' + formName + '"]').serializeArray();
            var result = {};
            $.each(formData, function() {
                if (this.name.indexOf("[") != -1) {
                    var arrName = this.name.substring(0, this.name.indexOf("["));
                    if (result[arrName] == undefined) {
                        result[arrName] = [];
                    }
                    var index = this.name.substring(this.name.indexOf("[") + 1, this.name.indexOf("]"));
                    if (result[arrName][index] == undefined) {
                        result[arrName][index] = {};
                    }
                    if (this.name.indexOf(".") != -1) {
                        var propName = this.name.substring(this.name.indexOf(".") + 1);
                        result[arrName][index][propName] = this.value;
                    } else {
                        result[arrName][index] = this.value;
                    }
                } else {
                    result[this.name] = this.value || "";
                }
            });
            $('form[name="' + formName + '"] [type="checkbox"]').each(function() {
                result[this.name] = $(this).prop("checked");
            });
            return result;
        };
        this.fillFormFromObject = function(formName, data, namePrefix, defaultData) {
            if (typeof data === "string") {
                this.fillFormFromObjectItem(formName, namePrefix, namePrefix, data || defaultData);
            } else {
                for (var nameKey in data) {
                    if (data.hasOwnProperty(nameKey)) {
                        var value = data[nameKey];
                        if (!value && defaultData && defaultData[nameKey]) {
                            value = defaultData[nameKey];
                        }
                        this.fillFormFromObjectItem(formName, namePrefix, nameKey, value);
                    }
                }
            }
        };
        this.fillFormFromObjectItem = function(formName, namePrefix, name, val) {
            if (Object.prototype.toString.call(val) === "[object Array]") {
                for (var i = 0; i < val.length; i++) {
                    this.fillFormFromObject(formName, val[i], name + "[" + i + "]" + ".");
                }
            } else {
                var $el = $('form[name="' + formName + '"] [name="' + namePrefix + name + '"]');
                var type = $el.attr("type");
                switch (type) {
                  case "checkbox":
                    $el.prop("checked", Boolean(val));
                    break;

                  case "radio":
                    $el.filter('[value="' + val + '"]').prop("checked", true);
                    break;

                  default:
                    var tagName = $el.prop("tagName");
                    switch (tagName) {
                      case "SELECT":
                        $el.val(val);
                        this.initSelectWithValueOrChooseFirst($el, val);
                        break;

                      default:
                        $el.val(val);
                    }
                }
            }
        };
        this.processForward = function(forwardName, elementId, submitFn, extraForwardParams) {
            var forwardParams = [];
            forwardParams.push("nodeId=" + this.curEditingNode.getId());
            forwardParams.push("elementId=" + encodeURIComponent(elementId));
            if (!!extraForwardParams) {
                forwardParams.push(extraForwardParams);
            }
            var options = {
                forwardName: forwardName,
                forwardParams: forwardParams.join(";")
            };
            if (this.curEditor.safeToSave) {
                this.saveCurrentEditor();
            }
            submitFn(false, options);
        };
        this.getFirstOptionValue = function($el) {
            return Select.get($el).getFirstValue();
        };
        this.resetSelect = function($el) {
            Select.get($el).clear();
        };
        this.initSelectWithFirstValue = function($el) {
            Select.get($el).selectFirstValue();
        };
        this.initSelectWithValueOrChooseFirst = function($el, selectedValue) {
            Select.get($el).selectValueOrSelectFirst(selectedValue);
        };
        this.getNodesByTypes = function(types) {
            if (options.getNodesByTypes) {
                return options.getNodesByTypes(types);
            }
            return [];
        };
        this.getNodesByType = function(type) {
            return this.getNodesByTypes([ type ]);
        };
        this.getNodesByIncomingConnections = function(node) {
            if (options.getNodesByIncomingConnections) {
                return options.getNodesByIncomingConnections(node);
            }
            return [];
        };
        this.getNodesByOutgoingConnections = function(node) {
            if (options.getNodesByOutgoingConnections) {
                return options.getNodesByOutgoingConnections(node);
            }
            return [];
        };
        this.getFirstIncomingChain = function() {
            if (this.curEditingNode && options.getFirstIncomingChain) {
                return options.getFirstIncomingChain(this.curEditingNode);
            }
            return [];
        };
        this.forEachPreviousNode = function(callback) {
            var self = this;
            if (this.curEditingNode && options.forEachPreviousNode) {
                return options.forEachPreviousNode(this.curEditingNode, function(node) {
                    return callback.call(self, node);
                });
            }
            return [];
        };
        this.deleteNode = function(nodeId) {
            if (options.deleteNodeById) {
                options.deleteNodeById(nodeId);
            }
        };
        this.openNode = function(node, needCheckActivation) {
            if (options.editNode) {
                options.editNode(node, needCheckActivation);
            }
        };
    };
    function disableDialogItems($target) {
        $target.find(".disable-for-active").each(function(index, element) {
            $(element).attr("disabled", true);
        });
        $target.find(".hide-for-active").each(function(index, element) {
            $(element).hide();
        });
        $target.find(':input:enabled[type!="hidden"]').not(":button, .select2, .js-select, .js-datepicker").each(function(index, element) {
            if ($(element).prop("type") == "radio" || $(element).prop("type") == "checkbox") {
                $(element).attr("disabled", true);
            } else {
                $(element).attr("readonly", true);
            }
        });
        $target.find(":input:enabled.select2, :input:enabled.js-select, .select2-container").not(".disabled, :disabled").each(function(index, element) {
            if ($(element).prop("type") == "text" || $(element).is("input, select")) {
                $(element).attr("disabled", true);
            } else {
                $(element).select2("disable");
            }
        });
        $target.find(".js-datepicker").each(function(index, element) {
            $(element).attr("disabled", true);
        });
    }
    AGN.Lib.WM.EditorsHelper = new EditorsHelper();
})();

(function() {
    var Def = AGN.Lib.WM.Definitions, Node = AGN.Lib.WM.Node, EditorsHelper = AGN.Lib.WM.EditorsHelper, Utils = AGN.Lib.WM.Utils, Dialogs = AGN.Lib.WM.Dialogs;
    var MailingEditorHelper = function(data, submitWorkflowForm) {
        this.MAILING_TYPE_ACTIONBASED = 1;
        this.MAILING_TYPE_DATEBASED = 2;
        this.MAILING_TYPE_FOLLOWUP = 3;
        this.node = {};
        this.mailingsStatus = "all";
        this.defaultMailingsSort = data.defaultMailingsSort;
        this.defaultMailingsOrder = data.defaultMailingsOrder;
        this.mailingsSort = this.defaultMailingsSort;
        this.mailingsOrder = this.defaultMailingsOrder;
        this.formNameJId = 'form[name="' + data.form + '"]';
        this.containerId = data.container;
        this.mailingType = data.mailingType;
        this.mediaType = data.mediaType;
        this.mediatypes = data.mediatypes;
        this.mailingTypesForLoading = data.mailingTypesForLoading;
        this.statusName = data.mailingStatus;
        this.selectName = data.selectName;
        this.selectNameJId = "select[name=" + data.selectName + "]";
        this.mailingId = 0;
        this.showCreateEditLinks = data.showCreateEditLinks;
        this.$dropdown = null;
        if (data.$dropdown) {
            this.$dropdown = data.$dropdown;
        }
        this.isChangeDecisionOptions = data.isFollowUpBaseMailing;
        this.followUpContainer = data.followUpContainer;
        this.advertisingAdditionalOptions = data.advertisingAdditionalOptions;
        this.nodesChain = [];
        this.mailingData = {};
        this.configuredMailingData = null;
        var self = this;
        this.fillEditorBase = function(node) {
            this.node = node;
            if (Utils.checkActivation()) {
                this.mailingsStatus = "all";
            } else {
                this.mailingsStatus = $(this.formNameJId).find("input[checked=checked]").val() || "all";
            }
            this.mailingsSort = this.defaultMailingsSort;
            this.mailingsOrder = this.defaultMailingsOrder;
            this.cleanOptions();
            this.hideSendSettings();
            this.changeDecisionOptionsSet($(this.containerId), this.isChangeDecisionOptions);
        };
        this.cleanOptions = function() {
            this.setDefaultSortOptions();
            $(this.containerId + " #" + this.statusName + "_all").attr("checked", "checked");
            this.activateInputs();
            this.setSelectMailingOptions(this.node.data[this.selectName]);
            this.getMailingsByWorkStatus(this.mailingsStatus, this.mailingsSort, this.mailingsOrder, this.node.data.mailingId);
        };
        this.setDefaultSortOptions = function() {
            this.mailingsSort = this.defaultMailingsSort;
            this.mailingsOrder = this.defaultMailingsOrder;
            $(this.containerId + " .arrowUp").hide();
            $(this.containerId + " .arrowDown").hide();
            $(this.containerId + " #shortname_sort").attr("press", 1);
            $(this.containerId + " #change_date_sort").attr("press", 2);
            if (this.mailingType == this.MAILING_TYPE_ACTIONBASED || this.mailingType == this.MAILING_TYPE_DATEBASED) {
                $(this.containerId + " #shortname_sort .arrowUp").show();
            } else {
                $(this.containerId + " #change_date_sort .arrowDown").show();
            }
        };
        this.onMailingsStatusChange = function(val) {
            this.setSelectMailingOptions(0);
            this.getMailingsByWorkStatus(val, this.mailingsSort, this.mailingsOrder);
            this.changeDecisionOptionsSet($(this.containerId), this.isChangeDecisionOptions);
        };
        this.onMailingSelectChange = function(val) {
            this.setSelectMailingOptions(val);
            this.changeDecisionOptionsSet($(this.containerId), this.isChangeDecisionOptions);
        };
        this.changeDecisionOptionsSet = function(scope, isChangeDecisionOptions) {
            if (isChangeDecisionOptions) {
                var selectedMailingId = this.mailingId;
                var followUpSelect = $(scope.find(this.followUpContainer));
                var additionalOptions = this.advertisingAdditionalOptions;
                $(followUpSelect.find(".advertisingOption")).remove();
                if (selectedMailingId) {
                    $.ajax({
                        type: "POST",
                        url: AGN.url("/mailing/ajax/" + selectedMailingId + "/isAdvertisingContentType.action")
                    }).done(function(resp) {
                        if (resp && resp.success) {
                            var options = AGN.Lib.Template.text("followupAdvertisingOptions", {
                                items: additionalOptions
                            });
                            followUpSelect.append(options);
                        }
                    });
                }
            }
        };
        this.onMailingSortClick = function(id, val) {
            $(this.containerId + " .arrowUp").hide();
            $(this.containerId + " .arrowDown").hide();
            var sortElements = $(this.containerId + " .sort");
            var sortId = this.containerId + " #" + id + "_sort";
            var sortEl = $(sortId);
            var upSortEl = $(sortId + " .arrowUp");
            var downSortEl = $(sortId + " .arrowDown");
            var press = sortEl.attr("press");
            var selectedMailValue = $(this.formNameJId + " " + this.selectNameJId).val();
            if (!press) {
                sortElements.attr("press", 2);
                sortEl.attr("press", 2);
                upSortEl.show();
                this.mailingsOrder = "ASC";
            } else {
                switch (press) {
                  case "1":
                    sortEl.attr("press", 2);
                    downSortEl.show();
                    this.mailingsOrder = "DESC";
                    break;

                  case "2":
                    sortEl.attr("press", 1);
                    upSortEl.show();
                    this.mailingsOrder = "ASC";
                    break;
                }
            }
            this.getMailingsByWorkStatus(this.mailingsStatus, val, this.mailingsOrder, selectedMailValue);
        };
        this.setMailingId = function(mailingId) {
            this.mailingId = mailingId;
            if (this.$dropdown) {
                if (this.mailingId > 0) {
                    this.$dropdown.show();
                } else {
                    this.$dropdown.hide();
                }
            }
        };
        this.setSelectMailingOptions = function(mailingId) {
            this.setMailingId(mailingId);
            if (this.showCreateEditLinks) {
                this.setMailingLinks(mailingId);
            }
        };
        this.setMailingLinks = function(mailingId) {
            var mailLink = "";
            if (mailingId != "0") {
                if (!Utils.checkActivation()) {
                    mailLink = '<a href="#" data-action="mailing-editor-edit">' + t("workflow.mailing.edit_mailing_link") + "</a> ";
                } else {
                    const mailingUrl = AGN.url("/mailing/" + mailingId + "/settings.action");
                    mailLink = '<a href="' + mailingUrl + '">' + t("workflow.mailing.edit_mailing_link") + "</a>";
                }
            } else {
                mailLink = "" + '<a href="#" class="setting-mailing-left" data-action="mailing-editor-new"> ' + t("workflow.mailing.new") + "</a>";
            }
            var mailingLinkContainer = $(this.containerId + " #mailing_create_edit_link");
            mailingLinkContainer.html("");
            mailingLinkContainer.append(mailLink);
        };
        this.showSecurityQuestion = function() {
            this.setSecurityQuestion();
            this.setIsUsedInCMAttr();
            if (this.isSentMailing(this.mailingIsSent) || this.mailingIsUsedInCM) {
                var selectedOption = this.getSelectedMailingOption();
                $(this.containerId + "-security-dialog").dialog({
                    title: '<span class="dialog-fat-title">' + selectedOption.html() + "</span>",
                    dialogClass: "no-close",
                    open: function(event, ui) {},
                    width: 650,
                    modal: true,
                    resizable: false
                });
                return false;
            }
            return true;
        };
        this.isSentMailing = function(status) {
            return status == "mailing.status.sent" || status == "mailing.status.scheduled" || status == "mailing.status.norecipients";
        };
        this.cancelSecurityDialog = function() {
            $(this.containerId + "-security-dialog").dialog("close");
        };
        this.getMailingsByWorkStatus = function(status, sort, order, selectedMailingValue) {
            var mailingEditorBase = this;
            var $mailings = $(this.formNameJId + " " + this.selectNameJId);
            $mailings.attr("readonly", "readonly");
            $.ajax({
                type: "POST",
                url: AGN.url("/workflow/getMailingsByWorkStatus.action"),
                data: {
                    mailingTypes: this.mailingTypesForLoading.join(","),
                    mediatypes: this.mediatypes ? this.mediatypes.join(",") : "",
                    status: status,
                    sort: sort,
                    order: order
                },
                success: function(data) {
                    $mailings.empty();
                    $mailings.append($("<option></option>", {
                        value: 0,
                        text: t("workflow.defaults.no_mailing")
                    }));
                    data.forEach(function(d) {
                        var $option = $("<option></option>", {
                            value: d.MAILING_ID,
                            text: d.SHORTNAME,
                            selected: selectedMailingValue == d.MAILING_ID
                        });
                        if (mailingEditorBase.isSentMailing(d.WORK_STATUS)) {
                            $option.css("color", "#808080");
                        }
                        $option.attr({
                            status: d.WORK_STATUS,
                            senddate: d.SENDDATE
                        });
                        $option.data({
                            status: d.WORK_STATUS,
                            "send-date": d.SENDDATE,
                            "dependent-campaigns": d.USEDINWORKFLOWS || ""
                        });
                        $mailings.append($option);
                    });
                    $mailings.removeAttr("readonly");
                    mailingEditorBase.mailingsStatus = status;
                    mailingEditorBase.mailingsSort = sort;
                    mailingEditorBase.mailingsOrder = order;
                    $mailings.val(mailingEditorBase.mailingId);
                    EditorsHelper.initSelectWithValueOrChooseFirst($mailings, mailingEditorBase.mailingId);
                }
            });
        };
        this.disableInputs = function() {
            $(this.containerId + ' [name="' + this.statusName + '"]').attr("disabled", "disabled");
        };
        this.activateInputs = function() {
            $(this.containerId + ' [name="' + this.statusName + '"]').removeAttr("disabled");
        };
        this.setNodeFields = function() {
            this.node.setFilled(parseInt(this.mailingId, 10) > 0);
        };
        this.setSecurityQuestion = function() {
            var selectedMailingOption = this.getSelectedMailingOption();
            this.mailingIsSent = "";
            if (parseInt(this.mailingId, 10) > 0) {
                this.mailingIsSent = selectedMailingOption.data("status");
            }
        };
        this.setIsUsedInCMAttr = function() {
            var selectedMailingOption = this.getSelectedMailingOption();
            var dependentCampaign = selectedMailingOption.data("dependent-campaigns");
            var mailingId = selectedMailingOption.val();
            this.mailingIsUsedInCM = false;
            if (parseInt(this.mailingId, 10) > 0 && mailingId == this.mailingId && dependentCampaign) {
                var workflowId = Def.workflowId || 0;
                if (dependentCampaign > 0) {
                    if (workflowId > 0) {
                        this.mailingIsUsedInCM = workflowId !== dependentCampaign;
                    } else {
                        this.mailingIsUsedInCM = true;
                    }
                }
            }
        };
        this.getSelectedMailingOption = function() {
            return $(this.formNameJId + " " + this.selectNameJId + " option[value=" + this.mailingId + "]");
        };
        this.getSelectedDecisionOption = function() {
            var selector = "decisionCriterion";
            var val = $(this.formNameJId + ' select[name="' + selector + '"]').val();
            return $(this.formNameJId + ' select[name="' + selector + '"] option[value=' + val + "]");
        };
        this.createNewMailing = function(forwardName) {
            hasMailingIconMailingList({
                node: this.node,
                successCallback: checkMailingListAndDoProcessForward,
                forwardName: forwardName,
                mailingEditorBase: this
            });
        };
        var checkMailingListAndDoProcessForward = function(data, forwardName, self) {
            if (!data.hasMailingList) {
                $(self.containerId + " .editor-error-messages").html(t("error.workflow.notAddedMailingList"));
                $(self.containerId + " .editor-error-messages").css("display", "block");
            } else {
                var additionalParams = [];
                additionalParams.push("mailingType=" + self.mailingType);
                if (self.mediaType) {
                    additionalParams.push("mediaType=" + self.mediaType);
                }
                if (self.mailingType == self.MAILING_TYPE_FOLLOWUP) {
                    additionalParams.push("workflowFollowUpParentMailing=" + self.node.data.baseMailingId);
                    additionalParams.push("workflowFollowUpDecisionCriterion=" + self.node.data.decisionCriterion);
                }
                EditorsHelper.processForward(forwardName, self.formNameJId + " " + self.selectNameJId, submitWorkflowForm, additionalParams.join(";"));
            }
        };
        this.processCopyAndEditMailingForward = function(mailingId, forwardName, formNameJId, selectNameJId) {
            $("#forwardTargetItemId").val(mailingId);
            var additionalParams = [];
            if (this.mailingType == this.MAILING_TYPE_FOLLOWUP) {
                additionalParams.push("workflowFollowUpParentMailing=" + this.node.data.baseMailingId);
                additionalParams.push("workflowFollowUpDecisionCriterion=" + this.node.data.decisionCriterion);
            }
            if (additionalParams.length > 0) {
                EditorsHelper.processForward(forwardName, formNameJId + " " + selectNameJId, submitWorkflowForm, additionalParams.join(";"));
            } else {
                EditorsHelper.processForward(forwardName, formNameJId + " " + selectNameJId, submitWorkflowForm);
            }
        };
        this.editMailing = function(forwardName) {
            this.processCopyAndEditMailingForward(this.mailingId, forwardName, this.formNameJId, this.selectNameJId);
        };
        this.copyMailing = function(forwardName) {
            this.processCopyAndEditMailingForward(this.mailingId, forwardName, this.formNameJId, this.selectNameJId);
        };
        this.trySupplementChain = function(chain, mailingContent, successCallback) {
            if (chain.length > 0) {
                this.configuredMailingData = collectIncomingMailingData(chain);
                this.nodesChain = chain;
                this.mailingData = mailingContent;
                var paramsToAsk = getMailingParams(self, true);
                if (paramsToAsk.length) {
                    Dialogs.confirmMailingDataTransfer(paramsToAsk).done(function(checkedParams) {
                        self.transferMailingData(checkedParams);
                        self.supplementChain(successCallback);
                    }).fail(function() {
                        self.transferMailingData();
                        self.supplementChain(successCallback);
                    });
                } else {
                    self.supplementChain(successCallback);
                }
            }
        };
        this.checkDifferentMailingLists = function(mailingId, successCallback, failedCallback) {
            var mailingEditorBase = this;
            getMailingContent(mailingId).then(function(mailingContent) {
                var chain = EditorsHelper.getFirstIncomingChain();
                mailingEditorBase.configuredMailingData = collectIncomingMailingData(chain);
                mailingEditorBase.nodesChain = chain;
                mailingEditorBase.mailingData = mailingContent;
                var mailingIconsCount = 0;
                chain.forEach(function(node) {
                    if (node.getType() == Def.NODE_TYPE_MAILING) {
                        mailingIconsCount++;
                    }
                });
                var mailinglistId = mailingEditorBase.configuredMailingData.mailinglistId;
                if (mailingIconsCount > 1 && mailinglistId != 0 && mailinglistId != mailingContent.mailinglistId) {
                    failedCallback(mailingContent);
                } else {
                    successCallback(mailingContent);
                }
            });
        };
        var collectIncomingMailingData = function(chain) {
            var data = {
                parameterValue: 0,
                campaignId: 0,
                mailinglistId: 0,
                targets: [],
                date: null
            };
            for (var nodeIndex = chain.length - 1; nodeIndex >= 0; nodeIndex--) {
                var node = chain[nodeIndex];
                var nodeData = node.getData();
                switch (node.getType()) {
                  case Def.NODE_TYPE_PARAMETER:
                    data.parameterValue = nodeData.value;
                    break;

                  case Def.NODE_TYPE_ARCHIVE:
                    data.campaignId = nodeData.campaignId;
                    break;

                  case Def.NODE_TYPE_RECIPIENT:
                    if (data.mailinglistId == 0) {
                        data.mailinglistId = nodeData.mailinglistId;
                    }
                    if (nodeData.targets !== null) {
                        nodeData.targets.forEach(function(target) {
                            if (!data.targets.includes(target)) {
                                data.targets.push(parseInt(target));
                            }
                        });
                    }
                    break;

                  case Def.NODE_TYPE_START:
                    if (nodeData.date) {
                        data.date = excludeTime(nodeData.date);
                        data.date.setHours(nodeData.hour);
                        data.date.setMinutes(nodeData.minute);
                    } else {
                        data.date = null;
                    }
                    break;

                  case Def.NODE_TYPE_DEADLINE:
                    if (nodeData.deadlineType == Def.constants.deadlineTypeFixedDeadline) {
                        if (nodeData.date) {
                            data.date = excludeTime(nodeData.date);
                            data.date.setHours(nodeData.hour);
                            data.date.setMinutes(nodeData.minute);
                        } else {
                            data.date = null;
                        }
                    } else if (nodeData.deadlineType == Def.constants.deadlineTypeDelay) {
                        if (data.date != null) {
                            if (nodeData.timeUnit == Def.constants.deadlineTimeUnitMinute) {
                                data.date.setMinutes(data.date.getMinutes() + parseInt(nodeData.delayValue));
                            } else if (nodeData.timeUnit == Def.constants.deadlineTimeUnitHour) {
                                data.date.setHours(data.date.getHours() + parseInt(nodeData.delayValue));
                            } else if (nodeData.timeUnit == Def.constants.deadlineTimeUnitDay) {
                                data.date.setDate(data.date.getDate() + parseInt(nodeData.delayValue));
                                if (nodeData.useTime || nodeData.useTime == "true") {
                                    data.date.setMinutes(data.date.getMinutes() + parseInt(nodeData.minute));
                                    data.date.setHours(data.date.getHours() + parseInt(nodeData.hour));
                                }
                            }
                        }
                    }
                    break;
                }
            }
            return data;
        };
        var getMailingParams = function(mailingEditorBase, askAmbiguous) {
            var configuredMailingData = mailingEditorBase.configuredMailingData;
            var mailingData = mailingEditorBase.mailingData;
            var paramsToBeTransferred = [];
            var paramsToBeAsked = [];
            var paramsToBeOverridden = [];
            if (mailingData.mailinglistId == 0) {
                paramsToBeOverridden.push(Def.MAILING_PARAM_MAILING_LIST);
            } else {
                if (configuredMailingData.mailinglistId == 0) {
                    paramsToBeTransferred.push(Def.MAILING_PARAM_MAILING_LIST);
                } else {
                    if (configuredMailingData.mailinglistId != mailingData.mailinglistId) {
                        if (askAmbiguous) {
                            paramsToBeAsked.push(Def.MAILING_PARAM_MAILING_LIST);
                        } else {
                            paramsToBeTransferred.push(Def.MAILING_PARAM_MAILING_LIST);
                        }
                    }
                }
            }
            var configuredTargets = configuredMailingData.targets;
            var mailingTargets = mailingData.targetGroupIds;
            if (mailingTargets == null || mailingTargets.length == 0) {
                paramsToBeOverridden.push(Def.MAILING_PARAM_TARGET_GROUPS);
            } else {
                if (configuredTargets == null || configuredTargets.length == 0) {
                    paramsToBeTransferred.push(Def.MAILING_PARAM_TARGET_GROUPS);
                } else {
                    if (!equalTargetGroups(configuredMailingData, mailingData)) {
                        if (askAmbiguous) {
                            paramsToBeAsked.push(Def.MAILING_PARAM_TARGET_GROUPS);
                        } else {
                            paramsToBeTransferred.push(Def.MAILING_PARAM_TARGET_GROUPS);
                        }
                    }
                }
            }
            if (Def.constants.isAltgExtended) {
                var configuredAltgs = configuredMailingData.altgs;
                var mailingAltgs = mailingData.altgIds;
                if (mailingAltgs == null || mailingAltgs.length == 0) {
                    paramsToBeOverridden.push(Def.MAILING_PARAM_ALTGS);
                } else {
                    if (configuredAltgs == null || configuredAltgs.length == 0) {
                        paramsToBeTransferred.push(Def.MAILING_PARAM_ALTGS);
                    } else {
                        if (!equalAltgs(configuredMailingData, mailingData)) {
                            if (askAmbiguous) {
                                paramsToBeAsked.push(Def.MAILING_PARAM_TARGET_GROUPS);
                            } else {
                                paramsToBeTransferred.push(Def.MAILING_PARAM_TARGET_GROUPS);
                            }
                        }
                    }
                }
            }
            var parameterValue = mailingEditorBase.getParameterValue(mailingData.splitBase, mailingData.splitPart);
            if (parameterValue == null) {
                paramsToBeOverridden.push(Def.MAILING_PARAM_LIST_SPLIT);
            } else {
                if (configuredMailingData.parameterValue == 0) {
                    paramsToBeTransferred.push(Def.MAILING_PARAM_LIST_SPLIT);
                } else {
                    if (configuredMailingData.parameterValue != parameterValue) {
                        if (askAmbiguous) {
                            paramsToBeAsked.push(Def.MAILING_PARAM_LIST_SPLIT);
                        } else {
                            paramsToBeTransferred.push(Def.MAILING_PARAM_LIST_SPLIT);
                        }
                    }
                }
            }
            if (mailingData.campaignId == 0) {
                paramsToBeOverridden.push(Def.MAILING_PARAM_ARCHIVE);
            } else {
                if (configuredMailingData.campaignId == 0) {
                    paramsToBeTransferred.push(Def.MAILING_PARAM_ARCHIVE);
                } else {
                    if (configuredMailingData.campaignId != mailingData.campaignId) {
                        if (askAmbiguous) {
                            paramsToBeAsked.push(Def.MAILING_PARAM_ARCHIVE);
                        } else {
                            paramsToBeTransferred.push(Def.MAILING_PARAM_ARCHIVE);
                        }
                    }
                }
            }
            var configuredDate = configuredMailingData.date;
            var mailingPlannedDate = extractMailingPlannedDate(mailingData);
            var mailingSendDate = extractMailingSendDate(mailingData);
            if (mailingPlannedDate == null && mailingSendDate == null) {
                paramsToBeOverridden.push(Def.MAILING_PARAM_PLANNED_DATE);
            } else {
                if (configuredDate == null) {
                    if (mailingPlannedDate != null) {
                        paramsToBeTransferred.push(Def.MAILING_PARAM_PLANNED_DATE);
                    } else {
                        paramsToBeTransferred.push(Def.MAILING_PARAM_SEND_DATE);
                    }
                } else {
                    if (excludeTime(mailingPlannedDate) > excludeTime(configuredDate)) {
                        if (askAmbiguous) {
                            paramsToBeAsked.push(Def.MAILING_PARAM_PLANNED_DATE);
                        } else {
                            paramsToBeTransferred.push(Def.MAILING_PARAM_PLANNED_DATE);
                        }
                    } else if (mailingPlannedDate && excludeTime(mailingPlannedDate) < excludeTime(configuredDate)) {
                        paramsToBeOverridden.push(Def.MAILING_PARAM_PLANNED_DATE);
                    }
                    if (mailingSendDate > configuredDate) {
                        if (askAmbiguous) {
                            paramsToBeAsked.push(Def.MAILING_PARAM_SEND_DATE);
                        } else {
                            paramsToBeTransferred.push(Def.MAILING_PARAM_SEND_DATE);
                        }
                    } else if (mailingSendDate && mailingSendDate < configuredDate) {
                        paramsToBeOverridden.push(Def.MAILING_PARAM_SEND_DATE);
                    }
                }
            }
            overrideMailingData(mailingEditorBase, paramsToBeOverridden);
            return askAmbiguous ? paramsToBeAsked : paramsToBeTransferred;
        };
        var overrideMailingData = function(mailingEditorBase, paramsToBeOverridden) {
            var configuredMailingData = mailingEditorBase.configuredMailingData;
            var mailingData = mailingEditorBase.mailingData;
            for (var i = 0; i < paramsToBeOverridden.length; i++) {
                switch (paramsToBeOverridden[i]) {
                  case Def.MAILING_PARAM_MAILING_LIST:
                    mailingData.mailinglistId = configuredMailingData.mailinglistId;
                    break;

                  case Def.MAILING_PARAM_TARGET_GROUPS:
                    mailingData.targetGroupIds = configuredMailingData.targets;
                    break;

                  case Def.MAILING_PARAM_ALTGS:
                    mailingData.altgIds = configuredMailingData.altgs;
                    break;

                  case Def.MAILING_PARAM_ARCHIVE:
                    mailingData.campaignId = configuredMailingData.campaignId;
                    break;

                  case Def.MAILING_PARAM_LIST_SPLIT:
                    mailingData.splitBase = "";
                    mailingData.splitPart = "";
                    break;

                  case Def.MAILING_PARAM_PLANNED_DATE:
                    var campaignDate = excludeTime(configuredMailingData.date);
                    if (campaignDate) {
                        mailingData.planDate = campaignDate.getTime();
                    } else {
                        mailingData.planDate = 0;
                    }
                    break;

                  case Def.MAILING_PARAM_SEND_DATE:
                    mailingData.sendDate = excludeTime(configuredMailingData.date);
                    if (configuredMailingData.date) {
                        mailingData.sendHour = configuredMailingData.date.getHours();
                        mailingData.sendMinute = configuredMailingData.date.getMinutes();
                    }
                    break;
                }
            }
        };
        var getMailingContent = function(mailingId) {
            return new Promise(function(resolve) {
                _.defer(function() {
                    $.ajax({
                        type: "POST",
                        url: AGN.url("/workflow/getMailingContent.action"),
                        data: {
                            mailingId: mailingId
                        },
                        success: function(data) {
                            resolve(data);
                        }
                    });
                });
            });
        };
        var hasMailingIconMailingList = function(options) {
            var node = options.node || EditorsHelper.curEditingNode;
            var successCallback = options.successCallback;
            var forwardName = options.forwardName;
            function checkHasMailinglist(node) {
                var mailinglistId = 0;
                EditorsHelper.curEditingNode = node;
                EditorsHelper.forEachPreviousNode(function(prevNode) {
                    if (prevNode.type === Def.NODE_TYPE_RECIPIENT) {
                        mailinglistId = prevNode.data.mailinglistId;
                        return false;
                    }
                });
                return mailinglistId > 0;
            }
            successCallback({
                hasMailingList: checkHasMailinglist(node)
            }, forwardName, options.mailingEditorBase);
        };
        this.transferMailingData = function(checkedParams) {
            if (checkedParams) {
                overrideMailingData(self, checkedParams);
            } else {
                overrideMailingData(self, getMailingParams(self, true));
            }
        };
        this.supplementChain = function(successCallback) {
            var paramsToTransfer = getMailingParams(this, false);
            var mailingData = this.mailingData;
            var configuredMailingData = this.configuredMailingData;
            var chain = this.nodesChain;
            var isStartNodeSupplemented = false;
            var isBetweenMailings = false;
            for (var i = 1; i < chain.length; i++) {
                if (Def.NODE_TYPES_MAILING.includes(chain[i].getType())) {
                    chain.splice(i + 1);
                    isBetweenMailings = true;
                    break;
                }
            }
            if (!isBetweenMailings) {
                if (paramsToTransfer.includes(Def.MAILING_PARAM_PLANNED_DATE) || paramsToTransfer.includes(Def.MAILING_PARAM_SEND_DATE)) {
                    if (Def.NODE_TYPE_START == chain[chain.length - 1].getType()) {
                        isStartNodeSupplemented = true;
                    } else {
                        var allStartNodes = EditorsHelper.getNodesByType(Def.NODE_TYPE_START);
                        if (allStartNodes.length == 0 && mailingData.mailingType != this.MAILING_TYPE_ACTIONBASED && mailingData.mailingType != this.MAILING_TYPE_DATEBASED) {
                            isStartNodeSupplemented = true;
                        }
                    }
                    if (isStartNodeSupplemented) {
                        this.supplementSingleNode(Def.NODE_TYPE_START, function(node) {
                            var data = node.getData();
                            if (paramsToTransfer.includes(Def.MAILING_PARAM_PLANNED_DATE)) {
                                data.date = extractMailingPlannedDate(mailingData);
                                var configuredDate = configuredMailingData.date;
                                if (configuredDate) {
                                    data.hour = configuredDate.getHours();
                                    data.minute = configuredDate.getMinutes();
                                }
                                EditorsHelper.resave(node);
                            } else if (paramsToTransfer.includes(Def.MAILING_PARAM_SEND_DATE)) {
                                data.date = extractMailingSendDate(mailingData);
                                data.hour = data.date.getHours();
                                data.minute = data.date.getMinutes();
                            }
                        });
                    }
                }
            }
            if (paramsToTransfer.includes(Def.MAILING_PARAM_LIST_SPLIT)) {
                this.supplementSingleNode(Def.NODE_TYPE_PARAMETER, function(node) {
                    var data = node.getData();
                    data.value = self.getParameterValue(mailingData.splitBase, mailingData.splitPart);
                });
            }
            if (paramsToTransfer.includes(Def.MAILING_PARAM_ARCHIVE)) {
                this.supplementSingleNode(Def.NODE_TYPE_ARCHIVE, function(node) {
                    var data = node.getData();
                    data.campaignId = mailingData.campaignId;
                });
            }
            if (paramsToTransfer.includes(Def.MAILING_PARAM_MAILING_LIST) || paramsToTransfer.includes(Def.MAILING_PARAM_TARGET_GROUPS)) {
                this.supplementSingleNode(Def.NODE_TYPE_RECIPIENT, function(node) {
                    var data = node.getData();
                    if (paramsToTransfer.includes(Def.MAILING_PARAM_MAILING_LIST)) {
                        data.mailinglistId = mailingData.mailinglistId;
                        node.setDependent(true);
                    }
                    if (paramsToTransfer.includes(Def.MAILING_PARAM_TARGET_GROUPS)) {
                        data.targets = mailingData.targetGroupIds;
                        if (Def.constants.isAltgExtended) {
                            data.targetsOption = "ONE_TARGET_REQUIRED";
                        } else {
                            data.targetsOption = Def.constants.accessLimitTargetId > 0 ? "ALL_TARGETS_REQUIRED" : "ONE_TARGET_REQUIRED";
                        }
                    }
                    if (Def.constants.isAltgExtended) {
                        if (paramsToTransfer.includes(Def.MAILING_PARAM_ALTGS)) {
                            data.altgs = mailingData.altgIds;
                        }
                    }
                });
            }
            if (!isStartNodeSupplemented && (paramsToTransfer.includes(Def.MAILING_PARAM_PLANNED_DATE) || paramsToTransfer.includes(Def.MAILING_PARAM_SEND_DATE))) {
                this.supplementSingleNode(Def.NODE_TYPE_DEADLINE, function(node) {
                    var data = node.getData();
                    if (paramsToTransfer.includes(Def.MAILING_PARAM_PLANNED_DATE)) {
                        data.date = extractMailingPlannedDate(mailingData);
                        var configuredDate = configuredMailingData.date;
                        if (configuredDate) {
                            data.date.setHours(configuredDate.getHours());
                            data.date.setMinutes(configuredDate.getMinutes());
                        }
                    } else if (paramsToTransfer.includes(Def.MAILING_PARAM_SEND_DATE)) {
                        data.date = extractMailingSendDate(mailingData);
                    }
                    data.deadlineType = Def.constants.deadlineTypeFixedDeadline;
                    data.hour = data.date.getHours();
                    data.minute = data.date.getMinutes();
                });
            }
            successCallback(chain);
        };
        this.supplementSingleNode = function(nodeType, callback) {
            var availableTypesAfter;
            switch (nodeType) {
              case Def.NODE_TYPE_START:
                availableTypesAfter = false;
                break;

              case Def.NODE_TYPE_PARAMETER:
                availableTypesAfter = [];
                break;

              case Def.NODE_TYPE_ARCHIVE:
                availableTypesAfter = [ Def.NODE_TYPE_PARAMETER ];
                break;

              case Def.NODE_TYPE_RECIPIENT:
                availableTypesAfter = [ Def.NODE_TYPE_PARAMETER, Def.NODE_TYPE_ARCHIVE ];
                break;

              case Def.NODE_TYPE_DEADLINE:
                availableTypesAfter = [ Def.NODE_TYPE_PARAMETER, Def.NODE_TYPE_ARCHIVE, Def.NODE_TYPE_RECIPIENT ];
                break;

              default:
                console.error("Unexpected supplement node type: " + nodeType);
                return;
            }
            if (!supplementExistingNode(nodeType, callback)) {
                supplementAddNode(nodeType, availableTypesAfter, callback);
            }
        };
        var supplementExistingNode = function(nodeType, callback) {
            var chain = self.nodesChain;
            for (var i = 1; i < chain.length; i++) {
                var node = chain[i];
                if (nodeType == node.getType()) {
                    callback(node);
                    EditorsHelper.resave(node);
                    return true;
                }
            }
            return false;
        };
        var supplementAddNode = function(nodeType, availableTypesAfter, callback) {
            var chain = self.nodesChain;
            var newNode = Node.create(nodeType);
            callback(newNode);
            if (availableTypesAfter === false) {
                chain.push(newNode);
            } else {
                for (var index = 1; index < chain.length; index++) {
                    var previousNode = chain[index];
                    if (!availableTypesAfter.includes(previousNode.getType())) {
                        chain.splice(index, 0, newNode);
                        return;
                    }
                }
                chain.push(newNode);
            }
        };
        this.closeOneMailinglistWarningDialog = function() {
            $(this.containerId + "-oneMailinglistWarning-dialog").dialog("close");
        };
        this.acceptOneMailinglistPerCampaign = function() {
            this.closeOneMailinglistWarningDialog();
            EditorsHelper.mailingSpecificSaveAfterMailinglistCheckModal(self);
        };
        this.validateEditor = function(save) {
            var $errors = $(this.containerId + " .editor-error-messages");
            $errors.html("");
            $errors.css("display", "none");
            var errorsFound = false;
            if ($(this.containerId + " .delivery-settings").length) {
                var maxRecipients = $(this.containerId + ' [name="maxRecipients"]').val();
                if (parseInt(maxRecipients) != maxRecipients) {
                    $errors.html(t("error.workflow.wrongMaxRecipientsFormat"));
                    errorsFound = true;
                } else if (parseInt(maxRecipients) < 0) {
                    $errors.html(t("error.workflow.maxRecipientsLessThanZero"));
                    errorsFound = true;
                } else if (parseInt(maxRecipients) > 1e9) {
                    $errors.html(t("error.workflow.maxRecipientsTooBig"));
                    errorsFound = true;
                }
            }
            var mailingSelector = $(this.formNameJId + " " + this.selectNameJId);
            if (mailingSelector.val() <= 0) {
                if ($errors.html() != "") {
                    $errors.html($errors.html() + "<br>");
                }
                $errors.html($errors.html() + t("error.workflow.noMailing"));
                errorsFound = true;
            }
            if (!errorsFound) {
                if (save) {
                    save();
                } else {
                    EditorsHelper.saveCurrentEditor();
                }
            } else {
                $errors.css("display", "block");
            }
        };
        this.toggleSendSettings = function(editorId) {
            if ($("#sendSettings_" + editorId).css("display") == "none") {
                $("#sendSettingsToggle_" + editorId).removeClass("toggle_closed");
                $("#sendSettingsToggle_" + editorId).addClass("toggle_open");
            } else {
                $("#sendSettingsToggle_" + editorId).removeClass("toggle_open");
                $("#sendSettingsToggle_" + editorId).addClass("toggle_closed");
            }
            $("#sendSettings_" + editorId).toggle("blind", 200);
        };
        this.hideSendSettings = function() {
            $(".wm-mailing-send-settings-link").removeClass("toggle_open");
            $(".wm-mailing-send-settings-link").addClass("toggle_closed");
            $(".wm-mailing-send-settings").css("display", "none");
        };
        this.getParameterValue = function(splitBase, splitPart) {
            if (splitBase.length > 4) {
                for (var i = 0; i < splitBase.length / 2; i++) {
                    if (i + 1 == splitPart) {
                        return splitBase.substring(i * 2, (i + 1) * 2);
                    }
                }
            } else {
                for (var i = 0; i < splitBase.length / 2; i++) {
                    if (splitBase.substring(i * 2, (i + 1) * 2) == splitPart) {
                        return splitBase.substring(i * 2, (i + 1) * 2);
                    }
                }
            }
            return null;
        };
        this.initOneMailinglistWarningDialog = function(self) {
            $(self.containerId + "-oneMailinglistWarning-dialog").dialog({
                title: '<span class="dialog-fat-title">' + self.getSelectedMailingOption().html() + "</span>",
                dialogClass: "no-close",
                width: 350,
                modal: true,
                resizable: false
            });
        };
        var containsMailingSendDate = function(mailingData) {
            return mailingData.sendDate != undefined && mailingData.sendDate != null && mailingData.sendHour != null && mailingData.sendMinute != null;
        };
        var containsMailingPlannedDate = function(mailingData) {
            return mailingData.planDate > 0;
        };
        var extractMailingSendDate = function(mailingData) {
            if (containsMailingSendDate(mailingData)) {
                return new Date(mailingData.sendDate + "T" + mailingData.sendHour + ":" + mailingData.sendMinute + ":00");
            }
            return null;
        };
        var extractMailingPlannedDate = function(mailingData) {
            if (containsMailingPlannedDate(mailingData)) {
                return new Date(mailingData.planDate);
            }
            return null;
        };
        var excludeTime = function(date) {
            if (date == null) {
                return null;
            } else {
                return new Date(date.getFullYear(), date.getMonth(), date.getDate());
            }
        };
        var equalTargetGroups = function(configuredMailingData, mailingData) {
            var configuredTargets = configuredMailingData.targets;
            var mailingTargets = mailingData.targetGroupIds;
            if (configuredTargets == null && mailingTargets == null) {
                return true;
            }
            if (configuredTargets.length != mailingTargets.length) {
                return false;
            }
            for (var i = 0; i < mailingTargets.length; i++) {
                if (!contains(configuredTargets, mailingTargets[i])) {
                    return false;
                }
            }
            return true;
        };
        var equalAltgs = function(configuredMailingData, mailingData) {
            var configuredAltgs = configuredMailingData.altgs;
            var mailingAltgs = mailingData.altgIds;
            if (configuredAltgs == null && mailingAltgs == null) {
                return true;
            }
            if (configuredAltgs.length != mailingAltgs.length) {
                return false;
            }
            for (var i = 0; i < mailingAltgs.length; i++) {
                if (!contains(configuredAltgs, mailingAltgs[i])) {
                    return false;
                }
            }
            return true;
        };
        var contains = function(array, item) {
            return array.indexOf(item) != -1;
        };
    };
    AGN.Lib.WM.MailingEditorHelper = MailingEditorHelper;
})();

(function() {
    var EditorsHelper = AGN.Lib.WM.EditorsHelper;
    AGN.Lib.WM.MailingSelector = function(form, container, selectName, noMailingOption) {
        this.formNameJId = 'form[name="' + form + '"]';
        this.container = container;
        this.selectNameJId = "select[name=" + selectName + "]";
        this.defaultSortField = "date";
        this.mailingId = 0;
        this.noMailingOption = noMailingOption;
        this.cleanOptions = function(defaultSortOrder) {
            if (defaultSortOrder == undefined) {
                defaultSortOrder = 0;
            }
            $(this.container + " .sort").prop("press", defaultSortOrder);
            this.onMailingSortClick(this.defaultSortField);
        };
        this.onMailingSelectChange = function(value) {};
        this.onMailingSortClick = function(field) {
            $(this.container + " .arrowUp").hide();
            $(this.container + " .arrowDown").hide();
            var sortElements = $(this.container + " .sort");
            var sortId = this.container + " #" + field + "_sort";
            var sortElement = $(sortId);
            var arrowUpElement = $(sortId + " .arrowUp");
            var arrowDownElement = $(sortId + " .arrowDown");
            var press = parseInt(sortElement.prop("press"));
            var sortDirection = "asc";
            sortElements.prop("press", 0);
            switch (press) {
              case 0:
                sortElement.prop("press", 1);
                arrowUpElement.show();
                sortDirection = "asc";
                break;

              case 1:
                sortElement.attr("press", 2);
                arrowDownElement.show();
                sortDirection = "desc";
                break;

              case 2:
                sortElement.prop("press", 1);
                arrowUpElement.show();
                sortDirection = "asc";
                break;
            }
            this.getAllMailingSorted(field, sortDirection);
        };
        this.setMailingId = function(mailingId) {
            this.mailingId = mailingId;
        };
        this.getAllMailingSorted = function(field, direction) {
            var self = this;
            var mailingsList = $(this.formNameJId + " " + this.selectNameJId);
            var mailingsListValue = mailingsList.val();
            if (mailingsListValue != null) {
                self.mailingId = mailingsListValue;
            }
            mailingsList.attr("readonly", "readonly");
            $.ajax({
                type: "GET",
                url: AGN.url("/workflow/getAllMailingSorted.action"),
                data: {
                    sortField: field,
                    sortDirection: direction
                },
                success: function(data) {
                    mailingsList.html("");
                    if (self.noMailingOption) {
                        mailingsList.append('<option value="0">' + t("workflow.defaults.no_mailing") + "</option>");
                    }
                    for (var i = 0; i < data.length; i++) {
                        mailingsList.append("<option " + ' value="' + data[i].mailingID + '">' + data[i].shortname + "</option>");
                    }
                    mailingsList.removeAttr("readonly");
                    if (self.mailingId == 0 && self.noMailingOption == false && data.length > 0) {
                        mailingsList.val(data[0].mailingID);
                    } else {
                        mailingsList.val(self.mailingId);
                    }
                    EditorsHelper.initSelectWithValueOrChooseFirst(mailingsList, mailingsList.val());
                }
            });
        };
        this.getSelectedMailingOption = function() {
            return $(this.formNameJId + " " + this.selectNameJId + " option[value=" + this.mailingId + "]");
        };
    };
})();

(function() {
    var Def = AGN.Lib.WM.Definitions, Node = AGN.Lib.WM.Node, Vertex = AGN.Lib.WM.Vertex, VertexGroup = AGN.Lib.WM.VertexGroup, NodeTitleHelper = AGN.Lib.WM.NodeTitleHelper, Canvas = AGN.Lib.WM.Canvas, ConnectionConstraints = AGN.Lib.WM.ConnectionConstraints, DraggableButtons = AGN.Lib.WM.DraggableButtons, AutoAlignment = AGN.Lib.WM.AutoAlignment, UndoManager = AGN.Lib.WM.UndoManager, EditorsHelper = AGN.Lib.WM.EditorsHelper, Dialogs = AGN.Lib.WM.Dialogs, Snippets = AGN.Lib.WM.Snippets, ContextMenu = AGN.Lib.ContextMenu, Helpers = AGN.Lib.Helpers, Utils = AGN.Lib.WM.Utils;
    var Ui = {
        blurInputFields: function() {
            if (document.activeElement && $(document.activeElement).is("input, textarea")) {
                document.activeElement.blur();
            }
        },
        setConnectionLabel: function(connection, text) {
            if (text) {
                var label = connection.origin.getOverlay("label");
                if (label) {
                    label.setLabel(text);
                    label.show();
                } else {
                    connection.origin.addOverlay([ "Label", {
                        location: .5,
                        id: "label",
                        cssClass: "connection-label",
                        label: text
                    } ]);
                }
            } else {
                connection.origin.hideOverlay("label");
            }
        },
        setDeleteButtonEnabled: function(isEnabled) {
            $("#deleteButton").toggleClass("disabled", !isEnabled);
            $("#deleteItem").prop("disabled", !isEnabled);
        },
        setUndoButtonEnabled: function(isEnabled) {
            $("#undoButton").toggleClass("disabled", !isEnabled);
            $("#undoItem").prop("disabled", !isEnabled);
        }
    };
    function Editor(isEditable, isContextMenuEnabled, isFootnotesEnabled) {
        this.$viewport = $("#viewPort");
        this.$gridBackground = $("#grid-background");
        this.$container = $("#canvas");
        this.$titlesContainer = this.$container.find("#icon-titles-container");
        this.canvas = new Canvas(this.$container);
        this.canvasZoomHandler = null;
        this.instance = jsPlumb.getInstance(Editor.defaults(this.$container));
        this.editable = !!isEditable;
        this.lastAllocatedId = 0;
        this.drag = null;
        this.chainModeEnabled = false;
        this.multiConnectionEnabled = false;
        this.scale = 1;
        this.dragMode = Def.DEFAULT_DRAG_MODE;
        var self = this;
        this.updateBackgroundCellSize(this.scale);
        this.canvas.setOnZoom(function(scale) {
            self.instance.setZoom(scale);
            if (self.canvasZoomHandler) {
                self.canvasZoomHandler.call(null, scale);
            }
        });
        this.canvas.setOnMove(function(position) {
            self.moveGridBackground(position);
        });
        this.draggableButtons = new DraggableButtons({
            enabled: !!isEditable,
            getZoom: function() {
                return self.getZoom();
            },
            getOccupiesAreas: function() {
                return self.getNodes$().get().map(function(node) {
                    return Node.getCollisionBox($(node));
                });
            },
            onStart: function() {},
            onStop: function() {},
            onDrop: function(type, position) {
                self.newNode(type, position);
            }
        });
        this.$viewport.selectable({
            filter: ".node",
            distance: 10,
            disabled: !this.editable,
            start: function() {
                $("#selection-backdrop").show();
            },
            stop: function() {
                $("#selection-backdrop").hide();
            },
            selected: function(event, ui) {
                self.instance.addToDragSelection(ui.selected);
                self.onSelectionChanged();
            },
            unselected: function(event, ui) {
                self.instance.removeFromDragSelection(ui.unselected);
                self.onSelectionChanged();
            }
        });
        this.$viewport.on("mousedown", function(event) {
            if ([ "canvas", "viewPort", "icon-titles-container" ].includes(event.target.id) || $.contains(self.$titlesContainer[0], event.target)) {
                self.deselectAll();
            }
            Ui.blurInputFields();
        });
        this.instance.bind("connection", function(connection) {
            self.undoManager.operation("connectionCreated", connection);
            self.autofillStopNodesIfPossible();
            self.autoConvertMailingNodesTypeIfPossible();
            self.updateOverlays();
            self.positionTitles();
            self.processRecipientsChains();
        });
        this.instance.bind("connectionDetached", function(connection) {
            self.undoManager.operation("connectionDeleted", connection);
            self.autofillStopNodesIfPossible();
            self.autoConvertMailingNodesTypeIfPossible();
            self.updateOverlays();
            self.positionTitles();
            self.processRecipientsChains();
        });
        this.instance.bind("mousedown", function(connection, event) {
            if (self.editable && event.button === Def.MOUSE_BUTTON_MIDDLE) {
                _.defer(function() {
                    self.undoManager.transaction(function() {
                        self.deleteConnection(connection);
                    });
                });
            }
            Ui.blurInputFields();
        });
        this.instance.bind("beforeDrag", function() {
            self.undoManager.startTransaction();
        });
        this.instance.bind("connectionDragStop", function() {
            self.undoManager.endTransaction();
        });
        this.instance.bind("connectionDrag", function(connection) {
            self.deselectAll();
            if (connection.source) {
                var $source = $(connection.source);
                self.setNodeSelected($source, true);
                if (self.isChainMode()) {
                    Node.setChainSource($source, true);
                }
            }
        });
        this.instance.bind("beforeDrop", function(params) {
            var source = Node.get(document.getElementById(params.sourceId));
            var target = Node.get(document.getElementById(params.targetId));
            var result = self.connect(source, target, true);
            if (result) {
                return true;
            }
            if (result === false) {
                workflowNotAllowedConnectionDialogHandler.showDialog();
            }
            return false;
        });
        this.$footnotesContainer = $("#footnotes-container ol");
        this.isFootnotesEnabled = isFootnotesEnabled;
        this.undoManager = new UndoManager(this, {
            onChange: function() {
                Ui.setUndoButtonEnabled(this.canUndo());
                self.processRecipientsChains();
                self.autofillStopNodesIfPossible();
                self.autoConvertMailingNodesTypeIfPossible();
            }
        });
        EditorsHelper.assignOptions({
            getUndoManager: function() {
                return self.getUndoManager();
            },
            getNodesByTypes: function(types) {
                return self.getNodesByTypes(types);
            },
            getNodesByIncomingConnections: function(node) {
                return self.getNodeIncomingConnections(node).map(function(connection) {
                    return connection.source;
                });
            },
            getNodesByOutgoingConnections: function(node) {
                return self.getNodeOutgoingConnections(node).map(function(connection) {
                    return connection.target;
                });
            },
            getFirstIncomingChain: function(node) {
                return self.getFirstIncomingChain(node);
            },
            forEachPreviousNode: function(node, callback) {
                return self.forEachPreviousNode(node, callback);
            },
            getNodeAnchorsInUse: function(node) {
                return self.getAnchorsInUse(node);
            },
            onChange: function(node) {
                self.updateNodeTitle(node, true);
                self.updateFootnotes();
                self.updateMinimap();
            },
            supplement: function(node) {
                self.supplement.apply(self, arguments);
            },
            editNode: function(node, needCheckActivation) {
                alert("Missing editorsHelper.editNode");
            },
            deleteNodeById: function(id) {
                alert("Missing editorsHelper.deleteNodeById");
            }
        });
        if (isContextMenuEnabled) {
            ContextMenu.create(Editor.contextMenuOptions(self));
        }
    }
    Editor.defaults = function($container) {
        return {
            Container: $container,
            Anchor: [ [ 0, .5, -1, 0 ], [ .5, 0, 0, -1 ], [ 1, .5, 1, 0 ], [ .5, 1, 0, 1 ] ],
            DragOptions: {
                cursor: "pointer",
                zIndex: Def.Z_INDEX_JSPLUMB_DRAG_OPTIONS
            },
            Endpoint: "Blank",
            Connector: [ "FixedBezierConnector" ],
            PaintStyle: {
                stroke: Def.CONNECTION_COLOR,
                strokeWidth: Def.CONNECTION_THICKNESS,
                outlineStroke: Def.CONNECTION_OUTLINE_COLOR,
                outlineWidth: Def.CONNECTION_OUTLINE_WIDTH
            },
            HoverPaintStyle: {
                stroke: Def.CONNECTION_HOVER_COLOR,
                strokeWidth: Def.CONNECTION_THICKNESS,
                outlineStroke: Def.CONNECTION_OUTLINE_COLOR,
                outlineWidth: Def.CONNECTION_OUTLINE_WIDTH
            },
            ConnectionOverlays: [ [ "Arrow", {
                id: "arrow",
                visible: true,
                location: 1,
                width: Def.CONNECTION_ARROW_SIZE,
                length: Def.CONNECTION_ARROW_SIZE
            } ] ]
        };
    };
    Editor.contextMenuOptions = function(self) {
        return {
            ".jtk-connector": {
                shown: function() {
                    return self.editable;
                },
                items: {
                    delete: {
                        name: t("workflow.defaults.delete"),
                        icon: "delete",
                        disabled: function($connection) {
                            return !self.canDeleteConnection(self.getConnectionByConnector$($connection));
                        },
                        clicked: function($connection) {
                            self.undoManager.transaction(function() {
                                var connection = self.getConnectionByConnector$($connection);
                                self.deleteConnection(connection.origin);
                            });
                        }
                    }
                }
            },
            ".node": {
                shown: function() {
                    return true;
                },
                items: {
                    connect: {
                        name: t("workflow.connect"),
                        icon: "connect",
                        shown: function() {
                            return self.editable && self.getSelectionSize() > 1;
                        },
                        clicked: function() {
                            self.undoManager.transaction(function() {
                                if (self.getSelectionSize() == 2 && self.multiConnectionEnabled) {
                                    self.connectBetweenSelected();
                                } else {
                                    self.connectSelected();
                                }
                            });
                        }
                    },
                    disconnect: {
                        name: t("workflow.disconnect"),
                        icon: "disconnect",
                        shown: function() {
                            return self.editable && self.getSelectionSize() > 1;
                        },
                        clicked: function() {
                            self.undoManager.transaction(function() {
                                self.disconnectSelected();
                            });
                        }
                    },
                    edit: {
                        name: t("workflow.defaults.edit"),
                        icon: "edit",
                        shown: function() {
                            return self.getSelectionSize() <= 1;
                        },
                        clicked: function($element) {
                            self.editIcon(Node.get($element));
                        },
                        disabled: function($element) {
                            return !Node.get($element).isEditable();
                        }
                    },
                    delete: {
                        name: t("workflow.defaults.delete"),
                        icon: "delete",
                        clicked: function() {
                            self.undoManager.transaction(function() {
                                self.deleteSelected();
                            });
                        },
                        disabled: function() {
                            return !self.editable;
                        }
                    },
                    comment: {
                        name: t("workflow.defaults.comment"),
                        icon: "comment",
                        clicked: function($element) {
                            self.editIconComment(Node.get($element));
                        },
                        disabled: function() {
                            return !self.editable;
                        }
                    }
                }
            }
        };
    };
    Editor.prototype.updateFootnotes = _.throttle(function() {
        this.forEachNode(function(node) {
            node.setFootnote(-1);
        });
        this.$footnotesContainer.html("");
        if (this.isFootnotesEnabled) {
            var self = this;
            var index = 1;
            this.forEachNode(function(node) {
                if (Node.isCommented(node)) {
                    self.$footnotesContainer.append('<li id="#fn:' + index + '">' + node.getComment() + "</li>");
                    node.setFootnote(index);
                    index++;
                }
            });
        }
    }, 150);
    Editor.prototype.moveGridBackground = function(canvasPosition) {
        const deltaX = this.calculateBackgroundOffsetDelta(canvasPosition.x);
        const deltaY = this.calculateBackgroundOffsetDelta(canvasPosition.y);
        this.$gridBackground.css({
            left: "-" + deltaX + "px",
            top: "-" + deltaY + "px",
            width: "calc(100% + " + deltaX + "px)",
            height: "calc(100% + " + deltaY + "px)"
        });
    };
    Editor.prototype.calculateBackgroundOffsetDelta = function(positionValue) {
        if (positionValue <= 0) {
            return positionValue * -1;
        }
        const cellSize = Def.NODE_SIZE * this.scale;
        const partCellSize = positionValue / cellSize % 1;
        return cellSize - cellSize * partCellSize;
    };
    Editor.prototype.isActionBasedWorkflow = function() {
        return this.getNodes().some(function(node) {
            return node.getType() === Def.NODE_TYPE_ACTION_BASED_MAILING;
        });
    };
    Editor.prototype.isDateBasedWorkflow = function() {
        return this.getNodes().some(function(node) {
            return node.getType() === Def.NODE_TYPE_DATE_BASED_MAILING;
        });
    };
    Editor.prototype.isNormalWorkflow = function() {
        return !this.isActionBasedWorkflow() && !this.isDateBasedWorkflow();
    };
    Editor.prototype.getNodes$ = function() {
        return this.$container.find(".node");
    };
    Editor.prototype.getNodes = function() {
        return this.getNodes$().get().map(function($node) {
            return Node.get($node);
        });
    };
    Editor.prototype.getVertices = function() {
        return Vertex.verticesFrom(this.getNodes(), this.instance.getAllConnections());
    };
    Editor.prototype.getNodesByTypes = function(types) {
        return this.getNodes().filter(function(node) {
            return types.includes(node.type);
        });
    };
    Editor.prototype.forEachNode$ = function(callback) {
        var $nodes = this.getNodes$();
        var self = this;
        $nodes.each(function() {
            callback.call(self, $(this));
        });
    };
    Editor.prototype.forEachNode = function(callback) {
        var self = this;
        this.forEachNode$(function($node) {
            callback.call(self, Node.get($node));
        });
    };
    Editor.prototype.forEachPreviousNode = function(target, callback) {
        var connections = this.getConnections();
        var layer = connections.filter(function(connection) {
            return connection.target === target;
        }).map(function(connection) {
            return connection.source;
        });
        var visitedIds = {};
        while (layer.length) {
            for (var i = 0; i < layer.length; i++) {
                var node = layer[i];
                var nodeId = node.getId();
                var result = callback.call(this, node);
                if (result === false) {
                    return;
                }
                visitedIds[nodeId] = true;
            }
            layer = connections.filter(function(connection) {
                if (layer.includes(connection.target)) {
                    var nodeId = connection.source.getId();
                    if (visitedIds[nodeId]) {
                        return false;
                    } else {
                        visitedIds[nodeId] = true;
                        return true;
                    }
                } else {
                    return false;
                }
            }).map(function(connection) {
                return connection.source;
            });
        }
    };
    Editor.prototype.getNodeIncomingChains = function(node) {
        var vertices = this.getVertices();
        var target = vertices.find(function(vertex) {
            return vertex.node == node;
        });
        var chains = [];
        if (target) {
            return Vertex.getIncomingChains(target);
        }
        return chains;
    };
    Editor.prototype.getNodeOutgoingChains = function(node) {
        var vertices = this.getVertices();
        var target = vertices.find(function(vertex) {
            return vertex.node == node;
        });
        var chains = [];
        if (target) {
            return Vertex.getOutgoingChains(target);
        }
        return chains;
    };
    Editor.prototype.getFirstOutgoingChain = function(node) {
        const chains = this.getNodeOutgoingChains(node);
        if (chains.length) {
            return chains[0];
        }
        return [];
    };
    Editor.prototype.getFirstIncomingChain = function(node) {
        var chains = this.getNodeIncomingChains(node);
        if (chains.length) {
            return chains[0];
        }
        return [];
    };
    Editor.prototype.getNodeIncomingConnections = function(node) {
        return this.getConnections(function(connection) {
            return Node.get(connection.target) === node;
        });
    };
    Editor.prototype.getNodeOutgoingConnections = function(node) {
        return this.getConnections(function(connection) {
            return Node.get(connection.source) === node;
        });
    };
    Editor.prototype.getNodeConnections = function(node) {
        return this.getConnections(function(connection) {
            return Node.get(connection.source) === node || Node.get(connection.target) === node;
        });
    };
    Editor.prototype.hasNodeIncomingConnections = function(node) {
        return this.instance.getAllConnections().some(function(connection) {
            return Node.get(connection.target) === node;
        });
    };
    Editor.prototype.hasNodeOutgoingConnections = function(node) {
        return this.instance.getAllConnections().some(function(connection) {
            return Node.get(connection.source) === node;
        });
    };
    Editor.prototype.hasConnection = function(predicate) {
        return this.instance.getAllConnections().some(function(connection) {
            return predicate.call(null, {
                origin: connection,
                source: Node.get(connection.source),
                target: Node.get(connection.target)
            });
        });
    };
    Editor.prototype.getConnections = function(filter) {
        var connections = this.instance.getAllConnections();
        if (filter) {
            connections = connections.filter(filter);
        }
        return connections.map(function(connection) {
            return {
                origin: connection,
                source: Node.get(connection.source),
                target: Node.get(connection.target)
            };
        });
    };
    Editor.prototype.getConnectionByConnector$ = function($connector) {
        return this.getConnections(function(connection) {
            return connection.canvas == $connector[0];
        })[0];
    };
    Editor.prototype.getConnectionBetween = function($source, $target) {
        return this.getConnections(function(connection) {
            return $(connection.source).is($source) && $(connection.target).is($target);
        })[0];
    };
    Editor.prototype.recycle = function() {
        this.instance.reset();
        this.$container.empty();
    };
    Editor.prototype.batch = function() {
        this.instance.batch.apply(this.instance, arguments);
    };
    Editor.prototype.newNode = function(type, position) {
        var self = this;
        if (this.editable) {
            if (Node.isExpandableType(type)) {
                switch (type) {
                  case Def.NODE_TYPE_SC_ABTEST:
                  case Def.NODE_TYPE_SC_BIRTHDAY:
                  case Def.NODE_TYPE_SC_DOI:
                    if (Def.workflowId === 0 && this._isInInitialState()) {
                        this.deleteAllNodes();
                    }
                    this.newSnippetFromSample(type, position);
                    break;

                  case Def.NODE_TYPE_OWN_WORKFLOW:
                    Dialogs.confirmOwnWorkflowExpanding().done(function(params) {
                        if (Def.workflowId === 0 && self._isInInitialState()) {
                            self.deleteAllNodes();
                        }
                        self.newSnippetFromOwnWorkflow(params.workflowId, params.copyContent, position);
                    });
                    break;
                }
            } else {
                var node = Node.create(type);
                var animation = Def.NODE_ANIMATION_DROPPED;
                if (!position) {
                    position = this.pickNewNodePosition();
                    animation = Def.NODE_ANIMATION_AUTO_DROPPED;
                }
                node.setCoordinates(position.x, position.y);
                this.undoManager.transaction(function() {
                    self.add(node, animation);
                    self.supplement(node);
                });
            }
        }
    };
    Editor.prototype._isInInitialState = function() {
        return Def.intialSchema === this.serializeIcons();
    };
    Editor.prototype.newSnippetFromSample = function(type, position) {
        var self = this;
        Snippets.loadSample(type, this.isGridDisplayed(), function(nodes, connections) {
            self.newSnippet(nodes, connections, position);
        });
    };
    Editor.prototype.newSnippetFromOwnWorkflow = function(workflowId, copyContent, position) {
        var self = this;
        Snippets.loadOwnWorkflow(workflowId, copyContent, function(nodes, connections) {
            if (self.isGridDisplayed()) {
                nodes.forEach(function(node) {
                    self.convertNodeCoordinates(node);
                });
            }
            self.newSnippet(nodes, connections, position);
        });
    };
    Editor.prototype.newSnippet = function(nodes, connections, position) {
        var self = this;
        var animation = position ? Def.NODE_ANIMATION_DROPPED : Def.NODE_ANIMATION_AUTO_DROPPED;
        var removeStart = this.getNodesByTypes([ Def.NODE_TYPE_START ]).length > 0;
        var removeStop = this.getNodesByTypes([ Def.NODE_TYPE_STOP ]).length > 0;
        Snippets.removeStartStop(nodes, connections, removeStart, removeStop);
        if (position) {
            Snippets.adjustPositions(nodes, position.x, position.y, true);
        } else {
            position = this.getCenterPosition();
            Snippets.adjustPositions(nodes, position.x, position.y, false);
        }
        this.undoManager.transaction(function() {
            self.batch(function() {
                var allocatedIds = self.allocateIds(nodes.length);
                self.allocateSpaceForSnippet(nodes);
                nodes.forEach(function(node, nodeIndex) {
                    node.setId(allocatedIds[nodeIndex]);
                    self.add(node, animation);
                });
                connections.forEach(function(connection) {
                    self.connect(connection.source, connection.target);
                });
            });
        });
    };
    Editor.prototype.allocateId = function() {
        return this.allocateIds(1)[0];
    };
    Editor.prototype.allocateIds = function(count) {
        var newIds = [];
        var ids = {};
        this.forEachNode(function(node) {
            ids[node.getId()] = true;
        });
        while (count > 0) {
            do {
                this.lastAllocatedId++;
            } while (ids[this.lastAllocatedId]);
            newIds.push(this.lastAllocatedId);
            count--;
        }
        return newIds;
    };
    Editor.prototype._findMaxNodeId = function() {
        var maxId = 0;
        this.forEachNode(function(node) {
            if (node.getId() > maxId) {
                maxId = node.getId();
            }
        });
        return maxId;
    };
    Editor.prototype.pickNewNodePosition = function() {
        var area = this.canvas.getVisibleArea();
        var areaMinY = Math.ceil(area.minY / Def.CANVAS_GRID_SIZE);
        var areaMaxY = Math.floor(area.maxY / Def.CANVAS_GRID_SIZE) - (Def.AUTO_DROP_STEP_Y >> 1);
        var positionRangesInUse = [];
        var result;
        this.forEachNode(function(node) {
            var coordinates = node.getCoordinates();
            positionRangesInUse.push({
                minX: coordinates.x - Def.AUTO_DROP_STEP_X + 1,
                minY: coordinates.y - Def.AUTO_DROP_STEP_Y + 1,
                maxX: coordinates.x + Def.AUTO_DROP_STEP_X - 1,
                maxY: coordinates.y + Def.AUTO_DROP_STEP_Y - 1
            });
        });
        var testOne = function(posX, posY) {
            if (posY < areaMinY || posY > areaMaxY) {
                return false;
            }
            var empty = !positionRangesInUse.some(function(ranges) {
                return !(posX < ranges.minX || posX > ranges.maxX || posY < ranges.minY || posY > ranges.maxY);
            });
            if (empty) {
                return {
                    x: posX,
                    y: posY
                };
            }
            return false;
        };
        var test = function() {
            for (var index = 0; index + 1 < arguments.length; index += 2) {
                var res = testOne(arguments[index], arguments[index + 1]);
                if (res) {
                    return res;
                }
            }
            return false;
        };
        var centerX = Math.round((area.minX + area.maxX - Def.NODE_SIZE) / 2 / Def.CANVAS_GRID_SIZE);
        var centerY = Math.round((area.minY + area.maxY - Def.NODE_SIZE) / 2 / Def.CANVAS_GRID_SIZE);
        result = test(centerX, centerY);
        if (result) {
            return result;
        }
        var minX = centerX;
        var maxX = centerX;
        var minY = centerY;
        var maxY = centerY;
        var step = 0;
        while (true) {
            result = test(minX - Def.AUTO_DROP_STEP_X, centerY, centerX, minY - Def.AUTO_DROP_STEP_Y, centerX, maxY + Def.AUTO_DROP_STEP_Y, maxX + Def.AUTO_DROP_STEP_X, centerY);
            if (result) {
                return result;
            }
            for (var n = 1; n <= step; n++) {
                var nX = n * Def.AUTO_DROP_STEP_X;
                var nY = n * Def.AUTO_DROP_STEP_Y;
                result = test(minX - Def.AUTO_DROP_STEP_X, centerY - nY, minX - Def.AUTO_DROP_STEP_X, centerY + nY, centerX - nX, minY - Def.AUTO_DROP_STEP_Y, centerX + nX, minY - Def.AUTO_DROP_STEP_Y, centerX - nX, maxY + Def.AUTO_DROP_STEP_Y, centerX + nX, maxY + Def.AUTO_DROP_STEP_Y, maxX + Def.AUTO_DROP_STEP_X, centerY - nY, maxX + Def.AUTO_DROP_STEP_X, centerY + nY);
                if (result) {
                    return result;
                }
            }
            result = test(minX - Def.AUTO_DROP_STEP_X, minY - Def.AUTO_DROP_STEP_Y, minX - Def.AUTO_DROP_STEP_X, maxY + Def.AUTO_DROP_STEP_Y, maxX + Def.AUTO_DROP_STEP_X, minY - Def.AUTO_DROP_STEP_Y, maxX + Def.AUTO_DROP_STEP_X, maxY + Def.AUTO_DROP_STEP_Y);
            if (result) {
                return result;
            }
            minX -= Def.AUTO_DROP_STEP_X;
            maxX += Def.AUTO_DROP_STEP_X;
            minY -= Def.AUTO_DROP_STEP_Y;
            maxY += Def.AUTO_DROP_STEP_Y;
            step++;
        }
    };
    Editor.prototype.getCenterPosition = function() {
        var area = this.canvas.getVisibleArea();
        var centerX = Math.round((area.minX + area.maxX - Def.NODE_SIZE) / 2 / Def.CANVAS_GRID_SIZE);
        var centerY = Math.round((area.minY + area.maxY - Def.NODE_SIZE) / 2 / Def.CANVAS_GRID_SIZE);
        return {
            x: centerX,
            y: centerY
        };
    };
    Editor.prototype.getLinkedFilledStartNodes = function(node) {
        return _.compact(this.getNodeIncomingChains(node).map(function(chain) {
            return _.find(chain, function(node) {
                return node.getType() === Def.NODE_TYPE_START;
            });
        })).filter(function(startNode) {
            return startNode.isFilled();
        });
    };
    Editor.prototype.isAutoOptimizationDecisionAllowed = function(node) {
        const filledStartNodes = this.getLinkedFilledStartNodes(node);
        if (filledStartNodes.length === 0) {
            return true;
        }
        return filledStartNodes.every(function(startNode) {
            return Def.constants.startTypeEvent !== startNode.data.startType;
        });
    };
    Editor.prototype.isAllLinkedFilledStartsHasDateType = function(node) {
        const filledStartNodes = this.getLinkedFilledStartNodes(node);
        return !!filledStartNodes.length && filledStartNodes.every(function(startNode) {
            return Def.constants.startTypeDate === startNode.data.startType;
        });
    };
    Editor.prototype.autofillStopNodesIfPossible = function() {
        const self = this;
        this.getNodesByTypes([ Def.NODE_TYPE_STOP ]).forEach(function(stopNode) {
            self.autofillAutomaticEndIfPossible(stopNode);
        });
    };
    Editor.prototype.autofillAutomaticEndIfPossible = function(stopNode) {
        if (!this.isAllLinkedFilledStartsHasDateType(stopNode)) {
            return;
        }
        stopNode.data.endType = Def.constants.endTypeAutomatic;
        stopNode.setFilled(true);
        this.updateNodeTitle(stopNode, true);
    };
    Editor.prototype._possibleToAutoConvertMailingsTypeToActionBased = function(mailingNode) {
        const filledStartNodes = this.getLinkedFilledStartNodes(mailingNode);
        return !!filledStartNodes.length && filledStartNodes.every(function(startNode) {
            return Def.constants.startTypeEvent === startNode.data.startType && "EVENT_REACTION" === startNode.data.event;
        });
    };
    Editor.prototype._possibleToAutoConvertMailingsTypeToDateBased = function(mailingNode) {
        const filledStartNodes = this.getLinkedFilledStartNodes(mailingNode);
        return !!filledStartNodes.length && filledStartNodes.every(function(startNode) {
            return Def.constants.startTypeEvent === startNode.data.startType && "EVENT_DATE" === startNode.data.event;
        });
    };
    Editor.prototype.autoConvertMailingNodesTypeIfPossible = function() {
        const self = this;
        const mailingNodes = [ Def.NODE_TYPE_MAILING, Def.NODE_TYPE_ACTION_BASED_MAILING, Def.NODE_TYPE_DATE_BASED_MAILING ];
        this.getNodesByTypes(mailingNodes).forEach(function(mailingNode) {
            const newType = self._getAutoConvertedMailingTypeIfPossible(mailingNode);
            if (mailingNode.type === newType) {
                return;
            }
            mailingNode.type = newType;
            if (mailingNode.isFilled()) {
                mailingNode.data.mailingId = 0;
                mailingNode.setFilled(false);
                self.updateNodeTitle(mailingNode, true);
            }
            self._updateNodeImages(mailingNode);
        });
    };
    Editor.prototype._getAutoConvertedMailingTypeIfPossible = function(mailingNode) {
        if (this.isAllLinkedFilledStartsHasDateType(mailingNode)) {
            return Def.NODE_TYPE_MAILING;
        }
        if (this._possibleToAutoConvertMailingsTypeToActionBased(mailingNode)) {
            return Def.NODE_TYPE_ACTION_BASED_MAILING;
        }
        if (this._possibleToAutoConvertMailingsTypeToDateBased(mailingNode)) {
            return Def.NODE_TYPE_DATE_BASED_MAILING;
        }
        return mailingNode.type;
    };
    Editor.prototype.allocateSpaceForSnippet = function(snippetNodes) {
        var self = this;
        function detectCollision(node1, node2) {
            var a = node1.getCoordinates();
            var b = node2.getCoordinates();
            return Math.abs(a.x - b.x) < Def.AUTO_DROP_STEP_X && Math.abs(a.y - b.y) < Def.AUTO_DROP_STEP_Y;
        }
        function detectGroupsCollision(group1, group2) {
            return group1.some(function(node1) {
                return group2.some(function(node2) {
                    return detectCollision(node1, node2);
                });
            });
        }
        function getGroupCenterPosition(group) {
            var minX = 0, maxX = 0, minY = 0, maxY = 0;
            group.forEach(function(node) {
                minX = Math.min(minX, node.getX());
                maxX = Math.max(maxX, node.getX());
                minY = Math.min(minY, node.getY());
                maxY = Math.max(maxY, node.getY());
            });
            return {
                x: (maxX - minX) / 2,
                y: (maxY - minY) / 2
            };
        }
        function getMoveDirection(currentPosition, relativeTo) {
            if (Math.abs(currentPosition.x - relativeTo.x) >= Math.abs(currentPosition.y - relativeTo.y)) {
                return currentPosition.x < relativeTo.x ? {
                    x: -Def.AUTO_DROP_STEP_X,
                    y: 0
                } : {
                    x: Def.AUTO_DROP_STEP_X,
                    y: 0
                };
            } else {
                return currentPosition.y < relativeTo.y ? {
                    x: 0,
                    y: -Def.AUTO_DROP_STEP_Y
                } : {
                    x: 0,
                    y: Def.AUTO_DROP_STEP_Y
                };
            }
        }
        function moveNodes(nodes, direction) {
            nodes.forEach(function(node) {
                var coordinates = node.getCoordinates();
                node.setCoordinates(coordinates.x + direction.x, coordinates.y + direction.y);
            });
        }
        if (snippetNodes.length) {
            var allExistingNodes = this.getNodes();
            var nodesMovedLog = allExistingNodes.map(function(node) {
                return {
                    node: node,
                    coordinates: node.getCoordinates(),
                    dragMode: self.getCurrentDragMode()
                };
            });
            var snippetCenterPosition = getGroupCenterPosition(snippetNodes);
            var allExistingGroups = VertexGroup.detectGroups(this.getVertices()).map(function(group) {
                var nodes = group.getNodes();
                return {
                    nodes: nodes,
                    moveDirection: getMoveDirection(getGroupCenterPosition(nodes), snippetCenterPosition)
                };
            });
            allExistingGroups.forEach(function(group) {
                if (detectGroupsCollision(group.nodes, snippetNodes)) {
                    var direction = group.moveDirection;
                    var nodesToMove = group.nodes.slice(0);
                    var nodesToKeep = snippetNodes.slice(0);
                    var otherGroups = allExistingGroups.filter(function(g) {
                        return g !== group;
                    });
                    do {
                        moveNodes(nodesToMove, direction);
                        var jointGroupDetected;
                        do {
                            jointGroupDetected = false;
                            otherGroups = otherGroups.filter(function(otherGroup) {
                                if (detectGroupsCollision(nodesToMove, otherGroup.nodes)) {
                                    if (otherGroup.moveDirection.x == direction.x && otherGroup.moveDirection.y == direction.y) {
                                        moveNodes(otherGroup.nodes, direction);
                                        Array.prototype.push.apply(nodesToMove, otherGroup.nodes);
                                        jointGroupDetected = true;
                                    } else {
                                        Array.prototype.push.apply(nodesToKeep, otherGroup.nodes);
                                    }
                                    return false;
                                } else {
                                    return true;
                                }
                            });
                        } while (jointGroupDetected);
                    } while (detectGroupsCollision(nodesToMove, nodesToKeep));
                }
            });
            nodesMovedLog = nodesMovedLog.filter(function(entry) {
                var newCoordinates = entry.node.getCoordinates();
                var oldCoordinates = entry.coordinates;
                return newCoordinates.x != oldCoordinates.x || newCoordinates.y != oldCoordinates.y;
            });
            if (nodesMovedLog.length) {
                this.undoManager.operation("nodeMoved", nodesMovedLog);
            }
        }
    };
    Editor.prototype.allocateSpaceForSupplement = function(node, direction) {
        var positionRangesInUse = [];
        var test = function(posX, posY) {
            return !positionRangesInUse.some(function(ranges) {
                return !(posX < ranges.minX || posX > ranges.maxX || posY < ranges.minY || posY > ranges.maxY);
            });
        };
        this.forEachNode(function(node) {
            var coordinates = node.getCoordinates();
            positionRangesInUse.push({
                minX: coordinates.x - Def.AUTO_DROP_STEP_X + 1,
                minY: coordinates.y - Def.AUTO_DROP_STEP_Y + 1,
                maxX: coordinates.x + Def.AUTO_DROP_STEP_X - 1,
                maxY: coordinates.y + Def.AUTO_DROP_STEP_Y - 1
            });
        });
        var deltaX = 0;
        var deltaY = 0;
        switch (direction) {
          case Def.LEFT:
          default:
            deltaX = -1;
            break;

          case Def.RIGHT:
            deltaX = +1;
            break;

          case Def.TOP:
            deltaY = -1;
            break;

          case Def.BOTTOM:
            deltaY = +1;
            break;
        }
        var newX = node.getX() + Def.AUTO_DROP_STEP_X * deltaX;
        var newY = node.getY() + Def.AUTO_DROP_STEP_Y * deltaY;
        while (!test(newX, newY)) {
            newX += deltaX;
            newY += deltaY;
        }
        return {
            x: newX,
            y: newY
        };
    };
    Editor.prototype.allocateSpaceForIncomingSupplement = function(target) {
        var anchorsInUse = this.getAnchorsInUse(target);
        var direction = Def.LEFT;
        if (!anchorsInUse[Def.LEFT] && anchorsInUse[Def.TOP]) {
            direction = Def.TOP;
        }
        return this.allocateSpaceForSupplement(target, direction);
    };
    Editor.prototype.allocateSpaceForOutgoingSupplement = function(source) {
        var anchorsInUse = this.getAnchorsInUse(source);
        var direction = Def.RIGHT;
        if (!anchorsInUse[Def.RIGHT] && anchorsInUse[Def.BOTTOM]) {
            direction = Def.BOTTOM;
        }
        return this.allocateSpaceForSupplement(source, direction);
    };
    Editor.prototype.add = function(node, animation) {
        var self = this;
        var $node = node.get$();
        if (!node.getId()) {
            node.setId(this.allocateId());
        }
        node.appendTo(this.$container, this.$titlesContainer, animation);
        node.setInteractionEnabled(this.editable);
        node.updateCommentLabels();
        this.instance.makeTarget($node, {
            anchor: node.getAnchors()
        });
        this.instance.makeSource($node, {
            anchor: node.getAnchors(),
            filter: ".node-connect-button img"
        });
        this.initDraggableOptions($node);
        var wasSelected;
        $node.on({
            mousedown: function(event) {
                if (event.button === Def.MOUSE_BUTTON_MIDDLE) {
                    if (self.editable) {
                        self.undoManager.transaction(function() {
                            self.deleteNode($node);
                        });
                    }
                } else {
                    node.wasDragging = false;
                    wasSelected = Node.isSelected($node);
                    if (!wasSelected) {
                        if (self.isChainMode()) {
                            if (!self.isChainSourceSelected()) {
                                self.setNodeSelected($node, true);
                                Node.setChainSource($node, true);
                            } else {
                                var source = self.getChainSource();
                                _.defer(function() {
                                    self.undoManager.transaction(function() {
                                        var connected = self.connect(Node.get(source), node);
                                        if (connected) {
                                            self.deselectAll();
                                            self.setNodeSelected($node, true);
                                            Node.setChainSource($node, true);
                                        } else if (connected === false) {
                                            workflowNotAllowedConnectionDialogHandler.showDialog();
                                        }
                                    });
                                });
                            }
                        } else if (!event.shiftKey && !event.ctrlKey) {
                            self.deselectAll();
                            self.setNodeSelected($node, true);
                        } else {
                            self.setNodeSelected($node, true);
                        }
                    }
                }
                Ui.blurInputFields();
            },
            mouseup: function(event) {
                if (wasSelected && !node.wasDragging) {
                    if (self.isChainMode()) {
                        self.setNodeSelected($node, false);
                        Node.setChainSource($node, false);
                    } else if (event.shiftKey || event.ctrlKey) {
                        self.setNodeSelected($node, false);
                    } else {
                        self.deselectAll();
                        self.setNodeSelected($node, true);
                    }
                }
            },
            dblclick: function() {
                self.editIcon(node);
            },
            mouseenter: function() {
                node.setHovered(true);
            },
            mouseleave: function() {
                node.setHovered(false);
            }
        });
        this.undoManager.operation("nodeAdded", node);
        this.updateMinimap();
        this.updateFootnotes();
    };
    Editor.prototype.supplement = function(node, mailingEditorBase, mailingContent) {
        var self = this;
        if (node.isFilled()) {
            if (Def.NODE_TYPES_MAILING.includes(node.getType()) && !EditorsHelper.isPausedWorkflow()) {
                const finalParameterNode = this._findFinalParameterNode(node);
                if (finalParameterNode) {
                    this._fillOptimizationFinalMailingIfPossible(finalParameterNode);
                }
                mailingEditorBase.trySupplementChain(this.getFirstIncomingChain(node), mailingContent, function(chain) {
                    self.batch(function() {
                        var target = chain[0];
                        for (var i = 1; i < chain.length; i++) {
                            var previousNode = chain[i];
                            if (previousNode.isAppended()) {
                                target = previousNode;
                            } else {
                                for (var j = i; j < chain.length; j++) {
                                    var sourceCandidate = chain[j];
                                    if (sourceCandidate.isAppended()) {
                                        self.deleteConnectionBetween(sourceCandidate.get$(), target.get$());
                                        target = sourceCandidate;
                                        i = j;
                                        break;
                                    }
                                }
                            }
                        }
                        for (var i = 1; i < chain.length; i++) {
                            var previousNode = chain[i];
                            if (!previousNode.isAppended()) {
                                var nextNode = chain[i - 1];
                                var position = self.allocateSpaceForIncomingSupplement(nextNode);
                                previousNode.setCoordinates(position.x, position.y);
                                self.add(previousNode);
                                self.connect(previousNode, nextNode);
                                if (i + 1 < chain.length && chain[i + 1].isAppended()) {
                                    self.connect(chain[i + 1], previousNode);
                                }
                                EditorsHelper.resave(previousNode);
                            }
                        }
                    });
                });
                this.autoConvertMailingNodesTypeIfPossible();
            } else if (Def.NODE_TYPE_RECIPIENT == node.getType()) {
                this.processRecipientsChains();
            } else if (Def.NODE_TYPE_PARAMETER === node.getType()) {
                const finalParameterNode = self._findFinalParameterNode(node);
                if (finalParameterNode) {
                    const optimizationParameterNodes = self._findTestMailingsParamsNodes(finalParameterNode);
                    const parameterValue = node.getData().value;
                    self._setParameterNodesValue(optimizationParameterNodes, parameterValue);
                    const parametersSum = parameterValue * optimizationParameterNodes.length;
                    EditorsHelper.modify(finalParameterNode, function(n) {
                        n.setFilled(true);
                        n.setEditable(false);
                        n.getData().value = 100 - parametersSum;
                    });
                }
            } else if (Def.NODE_TYPE_START == node.getType()) {
                this.autofillStopNodesIfPossible();
                this.autoConvertMailingNodesTypeIfPossible();
            }
        } else {
            if (Def.NODE_TYPE_IMPORT == node.getType()) {
                var isDeadlineMissing = !this.hasNodeOutgoingConnections(node);
                if (isDeadlineMissing) {
                    var deadline = Node.create(Def.NODE_TYPE_DEADLINE);
                    var position = this.allocateSpaceForOutgoingSupplement(node);
                    deadline.setCoordinates(position.x, position.y);
                    this.add(deadline);
                    this.connect(node, deadline);
                }
            }
        }
    };
    Editor.prototype.isAutoOptimizationWorkflow = function(startNode) {
        const finalParameterNode = this._findFinalParameterNode(startNode);
        if (!finalParameterNode) {
            return false;
        }
        const finalMailingNode = this._findOptimizationFinalMailingNode(finalParameterNode);
        if (!finalMailingNode) {
            return false;
        }
        const decisionNode = this.getFirstIncomingChain(finalParameterNode).find(function(node) {
            return node.getType() === Def.NODE_TYPE_DECISION;
        });
        return !!decisionNode && decisionNode.data.decisionType === Def.constants.decisionTypeAutoOptimization;
    };
    Editor.prototype.getParametersOptions = function(node) {
        const finalParameterNode = this._findFinalParameterNode(node);
        var splitValues = Def.SPLIT_DEFAULT_PARAMETERS;
        if (finalParameterNode) {
            const optimizationParameterNodes = this._findTestMailingsParamsNodes(finalParameterNode);
            const paramsNodesCount = optimizationParameterNodes.length + 1;
            const maxSplitValue = Math.floor(100 / paramsNodesCount);
            splitValues = splitValues.filter(function(value) {
                return value <= maxSplitValue;
            });
        }
        return splitValues.map(function(value) {
            return {
                id: value,
                text: value
            };
        });
    };
    Editor.prototype._fillOptimizationFinalMailingIfPossible = function(finalParameterNode) {
        if (!this._isAllOptimizationTestMailingsFilled(finalParameterNode)) {
            return;
        }
        const finalMailingNode = this._findOptimizationFinalMailingNode(finalParameterNode);
        const title = finalMailingNode.getTitle();
        EditorsHelper.modify(finalMailingNode, function(n) {
            n.setFilled(true);
        });
        finalMailingNode.setTitle(title);
    };
    Editor.prototype._findFinalParameterNode = function(node) {
        const outgoingChains = this.getNodeOutgoingChains(node);
        for (var i = 0; i < outgoingChains.length; i++) {
            const chain = outgoingChains[i];
            const finalParameterNode = chain.find(function(_node, index) {
                return index > 0 && Def.NODE_TYPE_PARAMETER === _node.getType();
            });
            if (finalParameterNode) {
                return finalParameterNode;
            }
        }
        return null;
    };
    Editor.prototype._findTestMailingsParamsNodes = function(finalParameterNode) {
        const optimizationParameterNodes = [];
        this.getNodeIncomingChains(finalParameterNode).forEach(function(incomingChain) {
            const optimizationParameterNode = incomingChain.find(function(node, index) {
                return index > 0 && Def.NODE_TYPE_PARAMETER === node.getType();
            });
            if (optimizationParameterNode) {
                optimizationParameterNodes.push(optimizationParameterNode);
            }
        });
        return optimizationParameterNodes;
    };
    Editor.prototype._findOptimizationFinalMailingNode = function(finalParameterNode) {
        const outgoingChain = this.getFirstOutgoingChain(finalParameterNode);
        return outgoingChain.find(function(node) {
            return node.getType() === Def.NODE_TYPE_MAILING && !node.isEditable();
        });
    };
    Editor.prototype._isAllOptimizationTestMailingsFilled = function(finalParameterNode) {
        const testMailingParametersNodes = this._findTestMailingsParamsNodes(finalParameterNode);
        for (var i = 0; i < testMailingParametersNodes.length; i++) {
            const parameterNode = testMailingParametersNodes[i];
            const outgoingChain = this.getFirstOutgoingChain(parameterNode);
            if (outgoingChain.length <= 1) {
                return false;
            }
            const nextNode = outgoingChain[1];
            if (nextNode.getType() !== Def.NODE_TYPE_MAILING || !nextNode.isFilled() || !nextNode.isEditable()) {
                return false;
            }
        }
        return true;
    };
    Editor.prototype._setParameterNodesValue = function(parameterNodes, value) {
        parameterNodes.forEach(function(optimizationNode) {
            EditorsHelper.modify(optimizationNode, function(node) {
                node.setFilled(true);
                node.getData().value = value;
            });
        });
    };
    Editor.prototype.processRecipientsChains = _.debounce(function() {
        var initialRecipientsNodes = this._findInitialRecipientsNodes();
        var selfEditor = this;
        initialRecipientsNodes.forEach(function(initNode) {
            initNode.setInRecipientsChain(false);
            selfEditor.updateNodeTitle(initNode);
            var chains = selfEditor.getNodeOutgoingChains(initNode);
            chains.forEach(function(chain) {
                var nodeIndex = 1;
                for (;nodeIndex < chain.length; ++nodeIndex) {
                    var node = chain[nodeIndex];
                    if (node.type != Def.NODE_TYPE_RECIPIENT) {
                        break;
                    }
                    node.data.mailinglistId = initNode.data.mailinglistId;
                    node.setInRecipientsChain(true);
                    selfEditor.updateNodeTitle(node);
                }
            });
        });
    }, 150);
    Editor.prototype._findInitialRecipientsNodes = function() {
        var recipientNodes = this.getNodesByTypes([ Def.NODE_TYPE_RECIPIENT ]);
        var connections = this.getConnections();
        var connectionsTargetsId = [];
        connections.filter(function(connection) {
            return connection.target.type == Def.NODE_TYPE_RECIPIENT && connection.source.type == Def.NODE_TYPE_RECIPIENT;
        }).forEach(function(connection) {
            connectionsTargetsId.push(connection.target.id);
        });
        return recipientNodes.filter(function(node) {
            return !connectionsTargetsId.includes(node.id);
        });
    };
    Editor.prototype.getAnchorsInUse = function(node) {
        var $node = node.get$();
        return Node.getAnchorsInUse(this.instance.getEndpoints($node[0]));
    };
    Editor.prototype.positionTitle = function(node) {
        NodeTitleHelper.positionTitle(node, this.getAnchorsInUse(node));
    };
    Editor.prototype.updateNodeTitle = function(node, forceUpdate) {
        var isNormalWorkflow = this.isNormalWorkflow();
        NodeTitleHelper.updateTitle(node, isNormalWorkflow, forceUpdate);
        this.positionTitle(node);
    };
    Editor.prototype.updateNodeTitles = _.throttle(function(forceUpdate) {
        var self = this;
        var isNormalWorkflow = this.isNormalWorkflow();
        this.forEachNode(function(node) {
            NodeTitleHelper.updateTitle(node, isNormalWorkflow, forceUpdate);
            self.positionTitle(node);
        });
    }, 150);
    Editor.prototype.positionTitles = _.throttle(function() {
        var self = this;
        this.forEachNode(function(node) {
            self.positionTitle(node);
        });
    }, 150);
    Editor.prototype.setMinimapEnabled = function(isEnabled) {
        this.canvas.setMinimapEnabled(isEnabled);
    };
    Editor.prototype.updateMinimap = _.debounce(function() {
        this.canvas.updateMinimap();
    }, 100);
    Editor.prototype.isChainSourceSelected = function() {
        return this.$container.find(".node.chain-mode-source").exists();
    };
    Editor.prototype.getChainSource = function() {
        return this.$container.find(".node.chain-mode-source");
    };
    Editor.prototype.setNodeSelected = function($node, isSelected) {
        if (isSelected) {
            this.instance.addToDragSelection($node);
        } else {
            this.instance.removeFromDragSelection($node);
        }
        Node.setSelected($node, !!isSelected);
        this.onSelectionChanged();
    };
    Editor.prototype.isConnectionPossible = function(source, target) {
        if (source instanceof Node && target instanceof Node) {
            if (source === target) {
                return false;
            }
            return !this.hasConnection(function(connection) {
                return connection.source === source && connection.target === target || connection.source === target && connection.target === source;
            });
        }
        return false;
    };
    Editor.prototype._updateNodeImages = function(node) {
        const nodeIcons = Def.ICONS_CONFIG[node.type].icons;
        node.get$().find(".active-node-image").attr("src", Def.constants.imagePath + nodeIcons.active);
        node.get$().find(".inactive-node-image").attr("src", Def.constants.imagePath + nodeIcons.inactive);
    };
    Editor.prototype.isConnectionAllowed = function(sourceNode, targetNode) {
        var constraints = new ConnectionConstraints(Def.CONNECTION_CONSTRAINTS);
        var self = this;
        var source = {
            node: sourceNode,
            type: sourceNode.getType(),
            connections: {}
        };
        var target = {
            node: targetNode,
            type: targetNode.getType(),
            connections: {}
        };
        Object.defineProperty(source.connections, "incoming", {
            get: Helpers.caching(self.getNodeIncomingConnections, self, sourceNode)
        });
        Object.defineProperty(source.connections, "outgoing", {
            get: Helpers.caching(self.getNodeOutgoingConnections, self, sourceNode)
        });
        Object.defineProperty(target.connections, "incoming", {
            get: Helpers.caching(self.getNodeIncomingConnections, self, targetNode)
        });
        Object.defineProperty(target.connections, "outgoing", {
            get: Helpers.caching(self.getNodeOutgoingConnections, self, targetNode)
        });
        if (source.type == Def.NODE_TYPE_STOP && !this.hasNodeIncomingConnections(sourceNode)) {
            source.type = Def.NODE_TYPE_START;
            source.node.type = Def.NODE_TYPE_START;
            self._updateNodeImages(source.node);
        }
        if (target.type == Def.NODE_TYPE_START && !this.hasNodeOutgoingConnections(targetNode)) {
            target.type = Def.NODE_TYPE_STOP;
            target.node.type = Def.NODE_TYPE_STOP;
            self._updateNodeImages(target.node);
        }
        return constraints.check(source, target);
    };
    Editor.prototype.connect = function(source, target, isUserDriven) {
        if (this.isConnectionPossible(source, target)) {
            if (!this.isConnectionAllowed(source, target)) {
                return false;
            }
            if (source.getType() === Def.NODE_TYPE_STOP) {
                source.setType(Def.NODE_TYPE_START);
            }
            if (target.getType() === Def.NODE_TYPE_START) {
                target.setType(Def.NODE_TYPE_STOP);
            }
            if (isUserDriven !== true) {
                this.instance.connect({
                    source: source.get$(),
                    target: target.get$()
                });
            }
            return true;
        } else {
            return null;
        }
    };
    Editor.prototype.deselectAll = function() {
        this.$container.find(".node.ui-selected").removeClass("ui-selected");
        this.instance.clearDragSelection();
        this.clearSelectedSource();
        this.onSelectionChanged();
    };
    Editor.prototype.clearSelectedSource = function() {
        this.$container.find(".node.chain-mode-source").removeClass("chain-mode-source");
    };
    Editor.prototype.alignAll = function() {
        var self = this;
        var nodes = this.getNodes();
        var oldCoordinatesMap = {};
        nodes.forEach(function(node) {
            oldCoordinatesMap[node.getId()] = node.getCoordinates();
        });
        this.batch(function() {
            AutoAlignment.align(self.getVertices());
        });
        var changes = nodes.filter(function(node) {
            var oldCoordinates = oldCoordinatesMap[node.getId()];
            return oldCoordinates.x != node.getX() || oldCoordinates.y != node.getY();
        }).map(function(node) {
            return {
                node: node,
                coordinates: oldCoordinatesMap[node.getId()],
                dragMode: self.getCurrentDragMode()
            };
        });
        if (changes.length) {
            self.undoManager.transaction(function() {
                self.undoManager.operation("nodeMoved", changes);
            });
            this.positionTitles();
            this.updateMinimap();
        }
    };
    Editor.prototype.deleteSelected = function() {
        this.deleteNodes(this.getSelectedNodes());
    };
    Editor.prototype.deleteNode = function(nodeToDelete) {
        var self = this;
        if (nodeToDelete instanceof Node) {} else {
            nodeToDelete = Node.get(nodeToDelete);
        }
        if (nodeToDelete.isAppended()) {
            var nodesToDelete = [ nodeToDelete ];
            switch (nodeToDelete.getType()) {
              case Def.NODE_TYPE_IMPORT:
                this.getNodeOutgoingConnections(nodeToDelete).forEach(function(connection) {
                    if (Def.NODE_TYPE_DEADLINE == connection.target.getType()) {
                        nodesToDelete.push(connection.target);
                    }
                });
                break;

              case Def.NODE_TYPE_DEADLINE:
                this.getNodeIncomingConnections(nodeToDelete).forEach(function(connection) {
                    if (Def.NODE_TYPE_IMPORT == connection.source.getType()) {
                        nodesToDelete.push(connection.source);
                    }
                });
                break;
            }
            nodesToDelete.forEach(function(node) {
                self.undoManager.operation("nodeDeleted", node);
                self.instance.remove(node.get$());
                node.remove();
            });
            this.onSelectionChanged();
            this.positionTitles();
            this.updateFootnotes();
            this.updateMinimap();
        }
    };
    Editor.prototype.deleteAllNodes = function() {
        this.deleteNodes(this.getNodes());
    };
    Editor.prototype.deleteNodes = function(nodes) {
        var self = this;
        this.undoManager.transaction(function() {
            self.batch(function() {
                nodes.forEach(function(node) {
                    self.deleteNode(node);
                });
            });
        });
    };
    Editor.prototype.disconnectSelected = function() {
        this.disconnectNodes(this.getSelectedNodes());
    };
    Editor.prototype.disconnectNode = function(node) {
        var self = this;
        this.getNodeConnections(node).forEach(function(connection) {
            self.deleteConnection(connection);
        });
    };
    Editor.prototype.disconnectNodes = function(nodes) {
        var self = this;
        this.batch(function() {
            nodes.forEach(function(node) {
                self.disconnectNode(node);
            });
        });
    };
    Editor.prototype.canDeleteConnection = function(connection) {
        var source, target;
        if (connection.origin) {
            source = connection.source;
            target = connection.target;
        } else {
            source = Node.get(connection.source);
            target = Node.get(connection.target);
        }
        return !(Def.NODE_TYPE_IMPORT == source.getType() && Def.NODE_TYPE_DEADLINE == target.getType());
    };
    Editor.prototype.deleteConnection = function(connection) {
        if (this.canDeleteConnection(connection)) {
            if (connection.origin) {
                this.instance.deleteConnection(connection.origin);
            } else {
                this.instance.deleteConnection(connection);
            }
            return true;
        }
        return false;
    };
    Editor.prototype.deleteConnectionBetween = function($source, $target) {
        var connection = this.getConnectionBetween($source, $target);
        if (connection) {
            this.deleteConnection(connection);
        }
    };
    Editor.prototype.connectSelected = function() {
        return this.connectNodes(this.getSelectedNodes());
    };
    Editor.prototype.connectBetweenSelected = function() {
        var $nodes = this.getSelectedNodes$();
        if ($nodes.length >= 2) {
            return this.connectNodes(this.getNodesBetweenSelected($nodes[0], $nodes[1]));
        } else {
            return false;
        }
    };
    Editor.prototype.getNodesBetweenSelected = function($source, $target) {
        var firstBox = Node.getBox($source);
        var lastBox = Node.getBox($target);
        var regionBox = {
            minX: Math.min(firstBox.minX, lastBox.minX),
            maxX: Math.max(firstBox.maxX, lastBox.maxX),
            minY: Math.min(firstBox.minY, lastBox.minY),
            maxY: Math.max(firstBox.maxY, lastBox.maxY)
        };
        return this.getNodes().filter(function(node) {
            return Node.isInRegion(node.get$(), regionBox);
        });
    };
    Editor.prototype.connectNodes = function(nodes) {
        var self = this;
        var sortedNodes = nodes.sort(function(node1, node2) {
            return node1.getX() < node2.getX() ? -1 : node1.getX() > node2.getX() ? 1 : node1.getY() < node2.getY() ? -1 : node1.getY() > node2.getY() ? 1 : 0;
        });
        var connected = false;
        this.undoManager.transaction(function() {
            self.batch(function() {
                for (var i = 0; i < sortedNodes.length - 1; i++) {
                    if (self.connect(sortedNodes[i], sortedNodes[i + 1])) {
                        connected = true;
                    }
                }
            });
        });
        return connected;
    };
    Editor.prototype.getSelectedNodes$ = function() {
        var $elements = [];
        this.$container.find(".node.ui-selected").each(function(index, element) {
            $elements.push($(element));
        });
        return $elements;
    };
    Editor.prototype.getSelectedNodes = function() {
        return this.getSelectedNodes$().map(function($node) {
            return Node.get($node);
        });
    };
    Editor.prototype.getSelectionSize = function() {
        return this.$container.find(".node.ui-selected").length;
    };
    Editor.prototype.onSelectionChanged = function() {
        Ui.setDeleteButtonEnabled(this.getSelectionSize() > 0);
    };
    Editor.prototype.setOnInitialized = function(handler) {
        const selfEditor = this;
        const _handler = function() {
            handler.apply(this);
            selfEditor.lastAllocatedId = selfEditor._findMaxNodeId();
        };
        this.instance.ready(_handler);
    };
    Editor.prototype.setOnZoom = function(handler) {
        this.canvasZoomHandler = handler;
    };
    Editor.prototype.setEditable = function(isEditable) {
        isEditable = !!isEditable;
        if (this.editable !== isEditable) {
            this.editable = isEditable;
            this.draggableButtons.setEnabled(isEditable);
            this.$viewport.selectable(isEditable ? "enable" : "disable");
            this.forEachNode(function(node) {
                node.setInteractionEnabled(isEditable);
            });
        }
    };
    Editor.prototype.getZoom = function() {
        return this.instance.getZoom();
    };
    Editor.prototype.setZoom = function(scale) {
        this.scale = scale;
        this.canvas.setZoom(scale);
        this.instance.setZoom(scale);
        this.updateBackgroundCellSize(scale);
        this.moveGridBackground(this.canvas.getPosition());
    };
    Editor.prototype.toggleGrid = function() {
        this.changeGridBackgroundVisibility();
        this.dragMode = this.isGridDisplayed() ? Def.GRID_CELL_DRAG_MODE : Def.DEFAULT_DRAG_MODE;
        this.adaptToNewDragMode();
    };
    Editor.prototype.changeGridBackgroundVisibility = function() {
        this.$gridBackground.toggleClass("hidden");
    };
    Editor.prototype.convertNodeCoordinates = function(node) {
        const coordinates = node.getCoordinates();
        this.convertCoordinates(coordinates);
        node.setCoordinates(coordinates.x, coordinates.y);
    };
    Editor.prototype.convertCoordinates = function(coordinates) {
        const scale = Def.NODE_SIZE / Def.CANVAS_DEFAULT_GRID_SIZE;
        if (this.getCurrentDragMode() === Def.GRID_CELL_DRAG_MODE) {
            coordinates.x = coordinates.x / scale;
            coordinates.y = coordinates.y / scale;
        } else {
            coordinates.x = coordinates.x * scale;
            coordinates.y = coordinates.y * scale;
        }
    };
    Editor.prototype.adaptToNewDragMode = function() {
        this.adaptPropertiesToDragMode();
        const self = this;
        this.getNodes$().each(function() {
            self.instance.destroyDraggable(this);
            self.initDraggableOptions($(this));
        });
        this.forEachNode(function(node) {
            self.convertNodeCoordinates(node);
        });
    };
    Editor.prototype.adaptPropertiesToDragMode = function() {
        if (this.getCurrentDragMode() === Def.GRID_CELL_DRAG_MODE) {
            Def.CANVAS_GRID_SIZE = Def.NODE_SIZE;
            Def.AUTO_ALIGN_STEP_X = Def.GRID_AUTO_ALIGN_STEP_X;
            Def.AUTO_ALIGN_STEP_Y = Def.GRID_AUTO_ALIGN_STEP_Y;
        } else {
            Def.CANVAS_GRID_SIZE = Def.CANVAS_DEFAULT_GRID_SIZE;
            Def.AUTO_ALIGN_STEP_X = Def.DEFAULT_AUTO_ALIGN_STEP_X;
            Def.AUTO_ALIGN_STEP_Y = Def.DEFAULT_AUTO_ALIGN_STEP_Y;
        }
    };
    Editor.prototype.initDraggableOptions = function($node) {
        const self = this;
        const node = Node.get($($node));
        this.instance.draggable($node, {
            distance: Def.CANVAS_GRID_SIZE / 2,
            grid: [ Def.CANVAS_GRID_SIZE, Def.CANVAS_GRID_SIZE ],
            rightButtonCanDrag: false,
            canDrag: function() {
                return self.editable;
            },
            start: function() {
                node.wasDragging = true;
                if (self.drag == null) {
                    var selected = [];
                    var unselected = [];
                    node.setPopoverEnabled(false);
                    self.forEachNode$(function($n) {
                        if (Node.isSelected($n)) {
                            selected.push($n);
                            Node.get($n).setTitleEnabled(false);
                        } else {
                            unselected.push(Node.getCollisionBox($n));
                        }
                    });
                    self.drag = {
                        lead: $node,
                        selected: selected,
                        unselected: unselected
                    };
                }
            },
            stop: function() {
                self.drag.lead.removeClass("js-no-drop");
                self.drag.selected.forEach(function($n) {
                    Node.get($n).setTitleEnabled(true);
                    $n.removeClass("js-collision-detected");
                });
                node.setPopoverEnabled(true);
            },
            drag: function() {
                if (self.drag && $node == self.drag.lead) {
                    var hasAnyCollision = false;
                    self.drag.selected.forEach(function($n) {
                        var thisBox = Node.getCollisionBox($n);
                        var hasCollision = self.drag.unselected.some(function(box) {
                            return Node.detectBoxCollision(box, thisBox);
                        });
                        $n.toggleClass("js-collision-detected", hasCollision);
                        if (hasCollision) {
                            hasAnyCollision = true;
                        }
                    });
                    self.drag.lead.toggleClass("js-no-drop", hasAnyCollision);
                }
            },
            revert: function() {
                if (self.drag) {
                    var hasCollision = false;
                    self.undoManager.transaction(function() {
                        var scale = self.getZoom();
                        hasCollision = self.drag.selected.some(function($n) {
                            var thisBox = Node.getCollisionBox($n);
                            return self.drag.unselected.some(function(box) {
                                return Node.detectBoxCollision(box, thisBox);
                            });
                        });
                        if (!hasCollision) {
                            self.undoManager.operation("nodeMoved", self.drag.selected.map(function($n) {
                                var _node = Node.get($n);
                                return {
                                    node: _node,
                                    coordinates: _node.getCoordinates(),
                                    dragMode: self.getCurrentDragMode()
                                };
                            }));
                            self.drag.selected.forEach(function($n) {
                                Node.get($n).updateCoordinates(scale);
                            });
                        }
                        self.drag = null;
                        self.updateOverlays();
                        self.positionTitles();
                        self.updateMinimap();
                    });
                    return hasCollision;
                } else {
                    return false;
                }
            }
        });
    };
    Editor.prototype.getCurrentDragMode = function() {
        return this.dragMode;
    };
    Editor.prototype.isGridDisplayed = function() {
        return !this.$gridBackground.hasClass("hidden");
    };
    Editor.prototype.updateBackgroundCellSize = function(scale) {
        const cellSize = Def.NODE_SIZE * scale;
        this.$gridBackground.css("background-size", cellSize + "px " + cellSize + "px");
    };
    Editor.prototype.setPanningEnabled = function(isEnabled) {
        this.canvas.setPanningEnabled(isEnabled);
        this.$viewport.toggleClass("js-panning", !!isEnabled);
        if (isEnabled) {
            this.$viewport.selectable("disable");
        } else if (this.editable) {
            this.$viewport.selectable("enable");
        }
    };
    Editor.prototype.setMouseWheelZoomEnabled = function(isEnabled) {
        this.canvas.setMouseWheelZoomEnabled(isEnabled);
    };
    Editor.prototype.setMultiConnectionEnabled = function(isEnabled) {
        this.multiConnectionEnabled = isEnabled;
    };
    Editor.prototype.setChainModeEnabled = function(isEnabled) {
        this.chainModeEnabled = isEnabled;
        this.clearSelectedSource();
        if (isEnabled) {
            var source = this.getSelection().shift();
            if (source) {
                this.deselectAll();
                this.setNodeSelected(source, true);
                Node.setChainSource(source, true);
            }
        }
    };
    Editor.prototype.isChainMode = function() {
        return this.chainModeEnabled === true;
    };
    Editor.prototype.updateOverlays = _.debounce(function() {
        this.forEachNode(function(node) {
            if (Node.isDecisionNode(node)) {
                this.updateDecisionBranchesOverlays(node);
            }
        });
    }, 100);
    Editor.prototype.updateDecisionBranchesOverlays = function(node) {
        var connections = this.getNodeOutgoingConnections(node);
        if (Node.isBranchingDecisionNode(node)) {
            var branches = Node.getDecisionBranches(connections);
            if (branches) {
                var titles = NodeTitleHelper.getDecisionBranchesLabels();
                Ui.setConnectionLabel(branches.positive, titles.positive);
                Ui.setConnectionLabel(branches.negative, titles.negative);
            } else {
                connections.forEach(function(connection) {
                    Ui.setConnectionLabel(connection, "?");
                });
            }
        } else {
            connections.forEach(function(connection) {
                Ui.setConnectionLabel(connection, false);
            });
        }
    };
    Editor.prototype.editIcon = function(node) {
        if (this.drag == null) {
            if (node) {
                if (node.editable) {
                    this.deselectAll();
                    EditorsHelper.showEditDialog(node, Utils.checkActivation(!Node.isMailingNode(node)));
                }
            } else {
                var $nodes = this.getSelection();
                if ($nodes.length == 1) {
                    this.deselectAll();
                    const node = Node.get($nodes[0]);
                    EditorsHelper.showEditDialog(node, Utils.checkActivation(!Node.isMailingNode(node)));
                }
            }
        }
    };
    Editor.prototype.editIconComment = function(node) {
        EditorsHelper.showIconCommentDialog(node);
    };
    Editor.prototype.serializeIcons = function() {
        var icons = this.getNodes().map(function(node) {
            return node.serialize();
        });
        var connectionsBySourceId = {};
        this.getConnections().forEach(function(connection) {
            var nodeConnections = connectionsBySourceId[connection.source.id];
            if (!nodeConnections) {
                nodeConnections = [];
            }
            nodeConnections.push(connection);
            connectionsBySourceId[connection.source.id] = nodeConnections;
        });
        icons.forEach(function(icon) {
            var nodeConnections = connectionsBySourceId[icon.id];
            if (nodeConnections) {
                icon.connections = nodeConnections.map(function(connection) {
                    return {
                        targetIconId: connection.target.id
                    };
                });
            } else {
                icon.connections = [];
            }
        });
        return JSON.stringify(icons);
    };
    Editor.prototype.undo = function() {
        this.undoManager.undo();
    };
    Editor.prototype.getUndoManager = function() {
        return this.undoManager;
    };
    Editor.prototype.enlargeEditor = function(positiveCallback, negativeCallback) {
        var self = this;
        var done = _.isFunction(positiveCallback) ? positiveCallback : _.noop;
        var fail = _.isFunction(negativeCallback) ? negativeCallback : _.noop;
        var promise = AGN.Lib.Confirm.createFromTemplate({}, "enlarged-editor-template");
        $("#modalCampaignEditorContainer").append($("#campaignEditorBody"));
        self.$viewport.selectable("option", "appendTo", "#modalCampaignEditorContainer");
        promise.done(done).fail(fail).always(function() {
            $("#pageCampaignEditorContainer").append($("#campaignEditorBody"));
            self.$viewport.selectable("option", "appendTo", "body");
        });
    };
    Editor.prototype.hasUnsavedChanges = function() {
        return this.getUndoManager().canUndo();
    };
    Editor.prototype.fitPdfPage = function() {
        this.canvas.fitPdfPage(Def.PDF_SIZE, Def.PDF_ORIENTATION);
    };
    AGN.Lib.WM.Editor = Editor;
})();

agGrid.BaseFilter.prototype.generateTemplate = function() {
    var translate = this.translate.bind(this);
    var mainConditionBody = this.createConditionBody(0);
    var bodyWithBooleanLogic = !this.acceptsBooleanLogic() ? mainConditionBody : this.wrapCondition(mainConditionBody);
    return "<div>\n                    <div class='ag-filter-body-wrapper'>" + bodyWithBooleanLogic + '</div>\n                    <div class="ag-filter-apply-panel" id="applyPanel">\n                        <a href="#" id="clearButton">' + translate("clearFilter") + '</a>\n                        <button type="button" id="applyButton">' + translate("applyFilter") + "</button>\n                    </div>\n                </div>";
};

agGrid.BaseFilter.prototype.createConditionTemplate = function(type) {
    return '<div class="ag-filter-condition">\n            <div class="ag-filter-condition-type radio"><label class="" for="andId"><input id="andId" type="radio" class="and" name="booleanLogic" value="AND" checked="checked" /> AND</label>\n            <label  class="" for="orId"><input id="orId" type="radio" class="or" name="booleanLogic" value="OR" /> OR</label></div>\n            <div>' + this.createConditionBody(type) + "</div>\n        </div>";
};

agGrid.TextFilter.prototype.bodyTemplate = function(type) {
    var translate = this.translate.bind(this);
    var fieldId = type == 0 ? "filterText" : "filterConditionText";
    return '<div class="ag-filter-body">\n            <input class="ag-filter-filter form-control" id=' + fieldId + ' type="text" placeholder="' + translate("filterOoo", "Filter...") + '"/>\n        </div>';
};

agGrid.TextFilter.prototype.generateFilterHeader = function(type) {
    var _this = this;
    var defaultFilterTypes = this.getApplicableFilterTypes();
    var restrictedFilterTypes = this.filterParams.filterOptions;
    var actualFilterTypes = restrictedFilterTypes ? restrictedFilterTypes : defaultFilterTypes;
    var optionsHtml = actualFilterTypes.map(function(filterType) {
        var localeFilterName = _this.translate(filterType);
        return '<option value="' + filterType + '">' + localeFilterName + "</option>";
    });
    var readOnly = optionsHtml.length == 1 ? "disabled" : "";
    var id = type == 0 ? "filterType" : "filterConditionType";
    return optionsHtml.length <= 0 ? "" : '<div>\n                <select class="ag-filter-select form-control" id="' + id + '" ' + readOnly + ">\n                    " + optionsHtml.join("") + "\n                </select>\n            </div>";
};

agGrid.NumberFilter.prototype.bodyTemplate = function(type) {
    var translate = this.translate.bind(this);
    var fieldId = type == 0 ? "filterText" : "filterConditionText";
    var filterNumberToPanelId = type == 0 ? "filterNumberToPanel" : "filterNumberToPanelCondition";
    var fieldToId = type == 0 ? "filterToText" : "filterToConditionText";
    return '<div class="ag-filter-body">\n            <div>\n                <input class="ag-filter-filter form-control" id="' + fieldId + '" type="text" placeholder="' + translate("filterOoo") + '"/>\n            </div>\n             <div class="ag-filter-number-to" id="' + filterNumberToPanelId + '">\n                <input class="ag-filter-filter form-control" id="' + fieldToId + '" type="text" placeholder="' + translate("filterOoo") + '"/>\n            </div>\n        </div>';
};

agGrid.NumberFilter.prototype.generateFilterHeader = agGrid.TextFilter.prototype.generateFilterHeader;

agGrid.TextFilter.prototype.createConditionTemplate = function(type) {
    return '<div class="ag-filter-condition">\n            <div class="ag-filter-condition-type radio"><label class="" for="andId"><input id="andId" type="radio" class="and" name="booleanLogic" value="AND" checked="checked" /> AND</label>\n            <label  class="" for="orId"><input id="orId" type="radio" class="or" name="booleanLogic" value="OR" /> OR</label></div>\n            <div>' + this.createConditionBody(type) + "</div>\n        </div>";
};

(function() {
    function compare(valueA, valueB) {
        if (typeof valueA === "string" && typeof valueB === "string") {
            return valueA.toLowerCase().localeCompare(valueB.toLowerCase());
        }
        return valueA.localeCompare(valueB);
    }
    AGN.Lib.TableCaseInsensitiveComparator = compare;
})();

(function() {
    var DateCellRenderer = function() {};
    function getFormattedValue(params, format) {
        if (params.value) {
            if (!params.valueFormatted) {
                params.valueFormatted = moment(params.value).format(format);
            }
            return params.valueFormatted;
        } else {
            return "";
        }
    }
    DateCellRenderer.prototype.init = function(params) {
        this.eGui = AGN.Lib.TableCellWrapper(params.data.show);
        if (params.optionDateFormat) {
            this.format = params.optionDateFormat;
        } else {
            this.format = "DD.MM.YYYY";
            if (params.optionShowTime) {
                if (params.optionShowSeconds) {
                    this.format += " HH:mm:ss";
                } else {
                    this.format += " HH:mm";
                }
            }
        }
        this.eGui.innerHTML = getFormattedValue(params, this.format);
    };
    DateCellRenderer.prototype.getGui = function() {
        return this.eGui;
    };
    DateCellRenderer.prototype.refresh = function(params) {
        this.eGui.innerHTML = getFormattedValue(params, this.format);
        return true;
    };
    DateCellRenderer.prototype.destroy = function() {};
    AGN.Opt.TableCellRenderers["DateCellRenderer"] = DateCellRenderer;
})();

(function() {
    var DateFilter = function() {};
    DateFilter.prototype.init = function(params) {
        this.eGui = document.createElement("div");
        this.eGui.innerHTML = '<div class="ag-filter">' + "  <div>" + '    <div class="ag-filter-body-wrapper">' + '      <div class="ag-filter-body">' + '        <label class="">' + t("tables.from") + "</label>" + '        <input class="ag-filter-filter form-control js-datepicker js-datepicker-right" id="filterBegin" type="text" placeholder="">' + "      </div>" + '      <div class="ag-filter-body">' + '        <label class="">' + t("tables.till") + "</label>" + '        <input class="ag-filter-filter form-control js-datepicker js-datepicker-right" id="filterEnd" type="text" placeholder="">' + "      </div>" + "    </div>" + '    <div class="ag-filter-apply-panel" id="applyPanel">' + '      <a href="#" id="clearFilter" class="">' + t("tables.clearFilter") + "</a>" + "    </div>" + "  </div>" + "</div>";
        this.filterBegin = $(this.eGui).find("#filterBegin");
        this.filterEnd = $(this.eGui).find("#filterEnd");
        this.beginDate = undefined;
        this.endDate = undefined;
        this.clearFilter = $(this.eGui).find("#clearFilter");
        this.filterBegin.on("change", this.filterBeginChanged.bind(this));
        this.filterEnd.on("change", this.filterEndChanged.bind(this));
        this.clearFilter.on("click", this.filterClear.bind(this));
        AGN.Lib.CoreInitializer.run("pickadate", $(this.eGui));
        this.filterActive = false;
        this.filterChangedCallback = params.filterChangedCallback;
        this.valueGetter = params.valueGetter;
    };
    DateFilter.prototype.afterGuiAttached = function() {};
    DateFilter.prototype.destroy = function() {
        this.filterBegin.off("change", this.filterBeginChanged.bind(this));
        this.filterEnd.off("change", this.filterEndChanged.bind(this));
        this.clearFilter.off("click", this.filterClear.bind(this));
    };
    DateFilter.prototype.filterBeginChanged = function() {
        var apiMax = this.filterEnd.data("pickadate");
        apiMax.set("min", this.filterBegin.val());
        this.beginDate = this.filterBegin.data("pickadate").get("select").pick;
        this.filterActive = this.beginDate || this.endDate;
        this.filterChangedCallback();
    };
    DateFilter.prototype.filterEndChanged = function() {
        var apiMin = this.filterBegin.data("pickadate");
        apiMin.set("max", this.filterEnd.val());
        this.endDate = this.filterEnd.data("pickadate").get("select").pick;
        this.filterActive = this.beginDate || this.endDate;
        this.filterChangedCallback();
    };
    DateFilter.prototype.filterClear = function() {
        var apiMin, apiMax;
        this.filterEnd.val(undefined);
        this.filterBegin.val(undefined);
        this.beginDate = undefined;
        this.endDate = undefined;
        apiMax = this.filterEnd.data("pickadate");
        apiMax.set("min", false);
        apiMin = this.filterBegin.data("pickadate");
        apiMin.set("max", false);
        this.filterActive = false;
        this.filterChangedCallback();
    };
    DateFilter.prototype.getGui = function() {
        return this.eGui;
    };
    DateFilter.prototype.doesFilterPass = function(params) {
        var date = this.valueGetter(params.node);
        if (!this.beginDate && !this.endDate) {
            return true;
        }
        if (!date) {
            return false;
        }
        if (this.beginDate && this.endDate) {
            return date >= this.beginDate && date <= this.endDate;
        }
        if (this.beginDate) {
            return date >= this.beginDate;
        }
        if (this.endDate) {
            return date <= this.endDate;
        }
    };
    DateFilter.prototype.parseDate = function(date) {
        if (!date) {
            return;
        }
        return moment(date, t("date.format").toUpperCase()).valueOf();
    };
    DateFilter.prototype.isFilterActive = function() {
        return this.filterActive;
    };
    DateFilter.prototype.getModel = function() {};
    DateFilter.prototype.setModel = function() {};
    AGN.Lib.TableDateFilter = DateFilter;
})();

(function() {
    var Table = AGN.Lib.Table, Confirm = AGN.Lib.Confirm, Page = AGN.Lib.Page, Tooltip = AGN.Lib.Tooltip, DeleteCellRenderer = function() {};
    function getValue(params) {
        return params.valueFormatted ? params.valueFormatted : params.value;
    }
    DeleteCellRenderer.prototype.init = function(params) {
        params.eGridCell.classList.add("ag-cell-table-actions");
        this.eGui = document.createElement("div");
        this.eGui.innerHTML = '<button type="button" class="btn btn-regular btn-alert"><i class="icon icon-trash-o"></i></button>';
        this.eButton = this.eGui.querySelector(".btn");
        if (params.colDef["button-tooltip"]) {
            Tooltip.createTip($(this.eButton), params.colDef["button-tooltip"]);
        }
        var value = getValue(params);
        if (value) {
            this.eButton.setAttribute("href", value);
        } else {
            this.eGui.style.visibility = "hidden";
        }
        this.eventListener = function(e) {
            var self = this;
            $.get(getValue(params)).done(function(resp) {
                var $resp = $(resp), $modal;
                $modal = $resp.all(".modal");
                if ($modal.length == 1) {
                    Confirm.create(resp).done(function(positiveResp) {
                        var $positiveResp = $(positiveResp);
                        Table.get($(self)).api.updateRowData({
                            remove: [ params.data ]
                        });
                        AGN.Lib.RenderMessages($positiveResp);
                    });
                } else {
                    Page.render(resp);
                }
            });
            e.preventDefault();
            return false;
        };
        this.eButton.addEventListener("click", this.eventListener);
    };
    DeleteCellRenderer.prototype.getGui = function() {
        return this.eGui;
    };
    DeleteCellRenderer.prototype.refresh = function(params) {
        var value = getValue(params);
        this.eGui.style.visibility = value ? "visible" : "hidden";
        this.eButton.dataset.url = value;
        return true;
    };
    DeleteCellRenderer.prototype.destroy = function() {
        this.eButton.removeEventListener("click", this.eventListener);
    };
    AGN.Opt.TableCellRenderers["DeleteCellRenderer"] = DeleteCellRenderer;
})();

var cachedTemplates = [];

(function() {
    var Template = AGN.Lib.Template;
    var MustacheTemplateCellRender = function() {};
    MustacheTemplateCellRender.prototype.init = function(params) {
        this.eGui = AGN.Lib.TableCellWrapper(params.data.show);
        var preparedTemplate;
        var templateName = params.templateName;
        if (cachedTemplates[templateName]) {
            preparedTemplate = cachedTemplates[templateName];
        } else {
            preparedTemplate = Template.prepare(templateName);
            cachedTemplates[templateName] = preparedTemplate;
        }
        this.eGui.innerHTML = preparedTemplate({
            value: params.value,
            entry: params.data
        });
    };
    MustacheTemplateCellRender.prototype.getGui = function() {
        return this.eGui;
    };
    MustacheTemplateCellRender.prototype.refresh = function() {
        return false;
    };
    MustacheTemplateCellRender.prototype.destroy = function() {};
    AGN.Opt.TableCellRenderers["MustacheTemplateCellRender"] = MustacheTemplateCellRender;
})();

(function() {
    var NoLabelHeader = function() {};
    NoLabelHeader.prototype.init = function(agParams) {
        this.agParams = agParams;
        this.eGui = document.createComment("No label");
    };
    NoLabelHeader.prototype.getGui = function() {
        return this.eGui;
    };
    NoLabelHeader.prototype.destroy = function() {};
    AGN.Opt.TableHeaderComponents["NoLabelHeader"] = NoLabelHeader;
})();

(function() {
    var NotEscapedStringCellRenderer = function() {};
    NotEscapedStringCellRenderer.prototype.init = function(params) {
        this.gui = AGN.Lib.TableCellWrapper(params.data.show);
        var contentDiv = document.createElement("div");
        if (params.value) {
            contentDiv.innerHTML = params.value;
        }
        contentDiv.style.cssText = "text-overflow: ellipsis;" + "overflow: hidden;";
        this.gui.appendChild(contentDiv);
    };
    NotEscapedStringCellRenderer.prototype.getGui = function() {
        return this.gui;
    };
    NotEscapedStringCellRenderer.prototype.refresh = function() {
        return false;
    };
    AGN.Opt.TableCellRenderers["NotEscapedStringCellRenderer"] = NotEscapedStringCellRenderer;
})();

(function() {
    function compare(valueA, valueB, nodeA, nodeB, isInverted) {
        valueA = parseFloat(valueA);
        valueB = parseFloat(valueB);
        if (isNaN(valueA) || isNaN(valueB)) {
            if (!isNaN(valueA)) {
                return isInverted ? +1 : -1;
            }
            if (!isNaN(valueB)) {
                return isInverted ? -1 : +1;
            }
            return 0;
        }
        return valueA - valueB;
    }
    AGN.Lib.TableNumberComparator = compare;
})();

(function() {
    var Table = AGN.Lib.Table, Confirm = AGN.Lib.Confirm, Page = AGN.Lib.Page, RecipientDeliveryInfoRenderer = function() {};
    function getButtonHref(params) {
        if (params.deliveryHistoryEnabled) {
            return AGN.url("/recipient/" + params.recipientId + "/mailing/" + params.data.mailingId + "/deliveryHistory.action");
        } else {
            return "";
        }
    }
    RecipientDeliveryInfoRenderer.prototype.init = function(params) {
        this.eGui = document.createElement("div");
        var href = getButtonHref(params);
        if (!href) {
            this.eGui.innerHTML = params.value;
        } else {
            params.eGridCell.classList.add("ag-cell-table-actions");
            this.eGui.innerHTML = '<button type="button" class="btn btn-regular "><i class="icon icon-share-square-o"></i><span>' + params.value + "</span></button>";
            this.eButton = this.eGui.querySelector(".btn");
            this.eButton.setAttribute("href", href);
            this.eventListener = function(e) {
                var href = getButtonHref(params);
                if (href) {
                    $.get(href).done(function(resp) {
                        var $resp = $(resp), $modal;
                        $modal = $resp.all(".modal");
                        if ($modal.length == 1) {
                            Confirm.create(resp);
                        } else {
                            Page.render(resp);
                        }
                    });
                    e.preventDefault();
                    return false;
                }
            };
            this.eButton.addEventListener("click", this.eventListener);
        }
    };
    RecipientDeliveryInfoRenderer.prototype.getGui = function() {
        return this.eGui;
    };
    RecipientDeliveryInfoRenderer.prototype.refresh = function(params) {
        if (this.eButton) {
            this.eButton.dataset.url = getButtonHref(params);
        }
        return true;
    };
    RecipientDeliveryInfoRenderer.prototype.destroy = function() {
        if (this.eButton) {
            this.eButton.removeEventListener("click", this.eventListener);
        }
    };
    AGN.Opt.TableCellRenderers["RecipientDeliveryInfoRenderer"] = RecipientDeliveryInfoRenderer;
})();

(function() {
    var Confirm = AGN.Lib.Confirm, Page = AGN.Lib.Page, RecipientSuccessDeliveryInfoRenderer = function() {};
    function getButtonHref(params) {
        if (params.deliveryHistoryEnabled) {
            return AGN.url("/recipient/" + params.recipientId + "/mailing/" + params.data.mailingId + "/successfulDeliveryHistory.action");
        } else {
            return "";
        }
    }
    RecipientSuccessDeliveryInfoRenderer.prototype.init = function(params) {
        this.eGui = document.createElement("div");
        var href = getButtonHref(params);
        if (!href) {
            this.eGui.innerHTML = params.value;
        } else {
            params.eGridCell.classList.add("ag-cell-table-actions");
            this.eGui.innerHTML = '<button type="button" class="btn btn-regular "><i class="icon icon-share-square-o"></i><span>' + params.value + "</span></button>";
            this.eButton = this.eGui.querySelector(".btn");
            this.eButton.setAttribute("href", href);
            this.eventListener = function(e) {
                var href = getButtonHref(params);
                if (href) {
                    $.get(href).done(function(resp) {
                        var $resp = $(resp), $modal;
                        $modal = $resp.all(".modal");
                        if ($modal.length == 1) {
                            Confirm.create(resp);
                        } else {
                            Page.render(resp);
                        }
                    });
                    e.preventDefault();
                    return false;
                }
            };
            this.eButton.addEventListener("click", this.eventListener);
        }
    };
    RecipientSuccessDeliveryInfoRenderer.prototype.getGui = function() {
        return this.eGui;
    };
    RecipientSuccessDeliveryInfoRenderer.prototype.refresh = function(params) {
        if (this.eButton) {
            this.eButton.dataset.url = getButtonHref(params);
        }
        return true;
    };
    RecipientSuccessDeliveryInfoRenderer.prototype.destroy = function() {
        if (this.eButton) {
            this.eButton.removeEventListener("click", this.eventListener);
        }
    };
    AGN.Opt.TableCellRenderers["RecipientSuccessDeliveryInfoRenderer"] = RecipientSuccessDeliveryInfoRenderer;
})();

(function() {
    var SetFilter = function() {};
    SetFilter.prototype.init = function(params) {
        this.column = params.colDef.field;
        this.values = _.sortBy(_.uniq(_.map(params.rowModel.rowsToDisplay, function(row) {
            return row.data[params.colDef.field];
        })));
        this.labels = _.extend({}, params.labels);
        this.eGui = document.createElement("div");
        this.eGui.innerHTML = '<div class="ag-filter">' + "  <div>" + '    <div class="ag-filter-body-wrapper">' + this.buildOptions() + "    </div>" + '    <div class="ag-filter-apply-panel" id="applyPanel">' + '      <a href="#" id="clearFilter" class="">' + t("tables.clearFilter") + "</a>" + "    </div>" + "  </div>" + "</div>";
        this.checkBoxes = $(this.eGui).find("input");
        this.checkedBoxes = [];
        this.clearFilter = $(this.eGui).find("#clearFilter");
        this.checkBoxes.on("change", this.checkBoxesChanged.bind(this));
        this.clearFilter.on("click", this.filterClear.bind(this));
        this.filterActive = false;
        this.filterChangedCallback = params.filterChangedCallback;
        this.valueGetter = params.valueGetter;
    };
    SetFilter.prototype.buildOptions = function() {
        var labels = this.labels;
        return _.map(this.values, function(value) {
            var valueLabel = labels.hasOwnProperty(value) ? labels[value] : value;
            return '<div class="ag-filter-body">' + '  <label class="">' + '    <input class="" type="checkbox" value="' + value + '">' + "    " + valueLabel + "  </label>" + "</div>";
        }).join("\n");
    };
    SetFilter.prototype.afterGuiAttached = function() {};
    SetFilter.prototype.destroy = function() {
        this.checkBoxes.off("change", this.checkBoxesChanged.bind(this));
        this.clearFilter.off("click", this.filterClear.bind(this));
    };
    SetFilter.prototype.checkBoxesChanged = function() {
        this.valuesFiltered = _.map(_.filter(this.checkBoxes, {
            checked: true
        }), function(checkbox) {
            return checkbox.value;
        });
        this.filterActive = this.valuesFiltered.length !== 0;
        this.filterChangedCallback();
    };
    SetFilter.prototype.filterClear = function() {
        this.checkBoxes.removeAttr("checked");
        this.valuesFiltered = [];
        this.filterActive = false;
        this.filterChangedCallback();
    };
    SetFilter.prototype.getGui = function() {
        return this.eGui;
    };
    SetFilter.prototype.doesFilterPass = function(params) {
        var value = this.valueGetter(params.node);
        return _.includes(this.valuesFiltered, value);
    };
    SetFilter.prototype.isFilterActive = function() {
        return this.filterActive;
    };
    SetFilter.prototype.getModel = function() {};
    SetFilter.prototype.setModel = function() {};
    AGN.Lib.TableSetFilter = SetFilter;
})();

(function() {
    var StringCellRenderer = function() {};
    StringCellRenderer.prototype.init = function(params) {
        this.gui = AGN.Lib.TableCellWrapper(params.data.show);
        var contentDiv = document.createElement("div");
        if (params.value) {
            contentDiv.appendChild(document.createTextNode(params.value));
        }
        contentDiv.style.cssText = "text-overflow: ellipsis;" + "overflow: hidden;";
        this.gui.appendChild(contentDiv);
    };
    StringCellRenderer.prototype.getGui = function() {
        return this.gui;
    };
    StringCellRenderer.prototype.refresh = function() {
        return false;
    };
    AGN.Opt.TableCellRenderers["StringCellRenderer"] = StringCellRenderer;
})();

(function() {
    AGN.Lib.TableCellWrapper = function(link) {
        if (link) {
            var cell = document.createElement("a");
            cell.href = link;
            cell.style.cssText = "display: block;" + "height: 33px;" + "margin:  -8px -6px;" + "padding: 8px 6px;";
            return cell;
        } else {
            return document.createElement("div");
        }
    };
})();

(function() {
    var WorkflowEndCellRenderer = function() {};
    WorkflowEndCellRenderer.prototype.init = function(params) {
        this.eGui = AGN.Lib.TableCellWrapper(params.data.show);
        var innerHtml = "";
        if (params.value.endTypeId === 1) {
            innerHtml = t("workflow.stop.automatic_end");
        } else if (params.value.endTypeId === 2) {
            innerHtml = params.value.date;
        }
        this.eGui.innerHTML = innerHtml;
    };
    WorkflowEndCellRenderer.prototype.getGui = function() {
        return this.eGui;
    };
    WorkflowEndCellRenderer.prototype.refresh = function(params) {
        return false;
    };
    WorkflowEndCellRenderer.prototype.destroy = function() {};
    AGN.Opt.TableCellRenderers["WorkflowEndCellRenderer"] = WorkflowEndCellRenderer;
})();

(function() {
    var WorkflowStartCellRenderer = function() {};
    WorkflowStartCellRenderer.prototype.init = function(params) {
        this.eGui = AGN.Lib.TableCellWrapper(params.data.show);
        var innerHtml = "";
        if (params.value.startTypeId === 1) {
            innerHtml = ' <span class="badge badge-campaigntype-actionbased">\n' + '              <i class="icon icon-gear"></i>\n' + "              <strong>" + t("workflow.start.action_based") + "</strong>\n" + "         </span>";
        } else if (params.value.startTypeId === 2) {
            innerHtml = '<span class="badge badge-campaigntype-datebased">\n' + '              <i class="icon icon-calendar-o"></i>\n' + "              <strong>" + t("workflow.start.date_based") + "</strong>\n" + "        </span>";
        } else {
            innerHtml = params.value.date;
        }
        this.eGui.innerHTML = innerHtml;
    };
    WorkflowStartCellRenderer.prototype.getGui = function() {
        return this.eGui;
    };
    WorkflowStartCellRenderer.prototype.refresh = function(params) {
        return false;
    };
    WorkflowStartCellRenderer.prototype.destroy = function() {};
    AGN.Opt.TableCellRenderers["WorkflowStartCellRenderer"] = WorkflowStartCellRenderer;
})();

(function() {
    var WorkflowStatusCellRenderer = function() {};
    WorkflowStatusCellRenderer.prototype.init = function(params) {
        this.eGui = AGN.Lib.TableCellWrapper(params.data.show);
        if (params.value) {
            var statusName = params.value.name;
            this.eGui.innerHTML = '<span class="status-badge campaign.status.' + statusName + '"></span> ' + t("workflow.status." + statusName);
        }
    };
    WorkflowStatusCellRenderer.prototype.getGui = function() {
        return this.eGui;
    };
    WorkflowStatusCellRenderer.prototype.refresh = function(params) {
        return false;
    };
    WorkflowStatusCellRenderer.prototype.destroy = function() {};
    AGN.Opt.TableCellRenderers["WorkflowStatusCellRenderer"] = WorkflowStatusCellRenderer;
})();

(function() {
    AGN.Lib.FormBuilder = AGN.Lib.FormBuilder || {};
    AGN.Lib.FormBuilder.Utils = {
        pushControl: function(controls, options) {
            if (!Array.isArray(controls)) {
                return;
            }
            controls.push(function(superControlClass) {
                var NewControl = function(controlClass) {
                    var superConstructor = controlClass.prototype.constructor;
                    function NewControl() {
                        return superConstructor.apply(this, arguments);
                    }
                    NewControl.prototype = Object.create(controlClass && controlClass.prototype, {
                        constructor: {
                            value: NewControl,
                            writable: true,
                            configurable: true
                        }
                    });
                    NewControl.__proto__ = controlClass;
                    if (options.build) {
                        NewControl.prototype.build = options.build;
                    }
                    if (options.onRender) {
                        NewControl.prototype.onRender = options.onRender;
                    }
                    Object.defineProperty(NewControl, "definition", {
                        get: options.definition
                    });
                    return NewControl;
                }(superControlClass);
                superControlClass.register(options.newControlName, NewControl);
                return NewControl;
            });
        }
    };
})();

(function() {
    AGN.Lib.FormBuilder = AGN.Lib.FormBuilder || {};
    AGN.Lib.FormBuilder.EmmControls = {
        mediapool: function(builder) {
            return {
                newControlName: "mediapool",
                build: function() {
                    return {
                        field: this.markup("img", null, {}),
                        layout: "agnMediapool"
                    };
                },
                onRender: function(e) {
                    if (this.preview) {
                        var $label = $(e.target).parents(".form-field").find(".field-label");
                        $label.html(t("userform.formBuilder.mediapoolImage") + ": " + builder.options.mediapoolImages[this.config.image]);
                    }
                    var $el = $(this.element);
                    $el.attr("src", this.config.image).attr("alt", this.config.alt);
                    if (this.config.width) {
                        $el.attr("width", this.config.width);
                    }
                    if (this.config.height) {
                        $el.attr("height", this.config.height);
                    }
                },
                definition: function() {
                    return {
                        i18n: {
                            default: t("userform.formBuilder.mediapoolImage")
                        }
                    };
                }
            };
        },
        nextform: function() {
            return {
                newControlName: "formName",
                build: function() {
                    return {
                        field: this.markup("input", null, {
                            name: "agnFN",
                            type: "hidden"
                        }),
                        layout: "hidden"
                    };
                },
                onRender: function(e) {
                    if (this.preview) {
                        var $label = $(e.target).parents(".form-field").find(".field-label");
                        $label.html(t("userform.formBuilder.nextForm") + ": " + this.config.formName);
                    }
                    $(this.element).attr("value", this.config.formName);
                },
                definition: function() {
                    return {
                        i18n: {
                            default: t("userform.formBuilder.nextForm")
                        }
                    };
                }
            };
        }
    };
})();

(function() {
    AGN.Lib.FormBuilder = AGN.Lib.FormBuilder || {};
    var TOOLTIPS_TEXT = {
        agnCTOKEN: t("userform.formBuilder.tooltips.agnCTOKEN"),
        agnUID: t("userform.formBuilder.tooltips.agnUID")
    };
    const MIN_SELECT_OPTIONS = 2;
    const EMM_FIELDS_DEF_OPTIONS = {
        gender: [ {
            selected: true,
            label: "Gender Male",
            value: 0
        }, {
            selected: false,
            label: "Gender Female",
            value: 1
        } ]
    };
    var DEFAULT_EMM_HIDDEN_FIELDS = [ "agnCTOKEN", "agnUID", "agnMAILINGLIST", "agnSUBSCRIBE" ];
    AGN.Lib.FormBuilder.Templates = {
        default: function() {
            return {
                onRender: defaultOnRender
            };
        },
        hidden: function() {
            return {
                onRender: hiddenOnRender
            };
        },
        dateForRender: function(fieldData) {
            var self = this;
            var classStyle = (this.config.className || "") + " js-datepicker";
            var config = $.extend({}, this.config, {
                "data-datepicker-options": "format: 'yyyy/mm/dd', formatSubmit: 'yyyy/mm/dd'",
                className: classStyle
            });
            return {
                field: self.markup("input", null, config),
                onRender: function(e) {
                    var $formGroup = $(e.target);
                    $formGroup.append('<input type="hidden" name="' + fieldData.name + '_format" value="' + "yyyy/MM/dd" + '">');
                }
            };
        }
    };
    function defaultOnRender(e) {
        var $formField = $(e.target).parents(".form-field"), newEmmField = this.config.emmField, oldEmmField = $formField.data("currentEmmField"), isInit = !oldEmmField, isSelectedNewEmmField = newEmmField !== oldEmmField;
        if (isInit) {
            $formField.data("currentEmmField", newEmmField);
        } else if (isSelectedNewEmmField) {
            $formField.data("currentEmmField", newEmmField);
            changeFieldsBySelectedEmmField($formField, this.config, newEmmField, oldEmmField);
        }
    }
    function hiddenOnRender(e) {
        var name = this.config.id.replace("-preview", "");
        var $eventTarget = $(e.target);
        var $elements = $eventTarget.parents(".form-field").find(".form-elements");
        var $emmFieldWrap = $elements.find(".emmField-wrap");
        if (DEFAULT_EMM_HIDDEN_FIELDS.includes(name)) {
            $emmFieldWrap.hide();
        } else {
            $emmFieldWrap.show();
        }
        if (!DEFAULT_EMM_HIDDEN_FIELDS.includes(name)) {
            defaultOnRender.apply(this, arguments);
        }
        var $tooltipEl = $eventTarget.parents(".form-field").find(".tooltip-element");
        displayTooltipIfExists($tooltipEl, name);
    }
    function displayTooltipIfExists($tooltip, fieldName) {
        var tooltipValue = TOOLTIPS_TEXT[fieldName];
        if (!tooltipValue) {
            $tooltip.hide();
            return;
        }
        $tooltip.attr("tooltip", tooltipValue);
        $tooltip.show();
    }
    function changeFieldsBySelectedEmmField($formField, fieldConfig, newEmmField, oldEmmField) {
        const $formElements = $formField.find(".form-elements"), $valueIpt = $formElements.find('input[name="value"]'), $nameIpt = $formElements.find('input[name="name"]'), fieldSelected = newEmmField !== "none";
        var value = fieldSelected ? "$!customerData." + newEmmField : "", name = fieldSelected ? newEmmField : "";
        $valueIpt.val(value);
        $nameIpt.val(name);
        if (fieldSelected) {
            $nameIpt.prop("disabled", true);
        } else {
            $nameIpt.prop("disabled", false);
        }
        if (fieldConfig.type === "select") {
            updateSelectFieldOptions(newEmmField, oldEmmField, $formField, fieldConfig);
        }
    }
    function updateSelectFieldOptions(newEmmField, oldEmmField, $formField, fieldConfig) {
        const options = getOptionsByEmmField(newEmmField);
        if (options.length >= MIN_SELECT_OPTIONS) {
            const configOptions = {
                values: options,
                name: newEmmField
            };
            replaceField($formField, fieldConfig, configOptions);
        } else if (getOptionsByEmmField(oldEmmField).length > 0) {
            const configOptions = {
                values: [],
                name: newEmmField
            };
            replaceField($formField, fieldConfig, configOptions);
        }
    }
    function replaceField($formField, currentFieldConfig, configOptions) {
        const $builderContainer = $formField.parents(".js-form-builder");
        const formBuilder = $builderContainer.data("formBuilder");
        formBuilder.actions.removeField($formField.prop("id"));
        invokeAfterEventsFinishing(function() {
            const newConfig = _.mergeWith(currentFieldConfig, configOptions, function(a, b) {
                return _.isArray(b) ? b : undefined;
            });
            formBuilder.actions.addField(newConfig, findFieldIndex($formField, $builderContainer));
        });
        invokeAfterEventsFinishing(function() {
            formBuilder.actions.toggleFieldEdit(formBuilder.actions.getCurrentFieldId());
        });
    }
    function findFieldIndex($formField, $builderContainer) {
        var fieldIndex = 0;
        _.each($builderContainer.find(".form-field"), function(el, index) {
            if ($(el).prop("id") === $formField.prop("id")) {
                fieldIndex = index;
            }
        });
        return fieldIndex;
    }
    function invokeAfterEventsFinishing(callback) {
        window.setTimeout(function() {
            callback();
        }, 0);
    }
    function getOptionsByEmmField(fieldName) {
        const options = EMM_FIELDS_DEF_OPTIONS[fieldName];
        return options ? options : [];
    }
})();

(function() {
    var Utils = AGN.Lib.FormBuilder.Utils;
    var EmmControls = AGN.Lib.FormBuilder.EmmControls;
    var Templates = AGN.Lib.FormBuilder.Templates;
    var template = "<html>\n" + "    <head>\n" + '        <script type="text/javascript" src="' + AGN.url("/js/lib/jquery/jquery-3.5.1.js", true) + '"><\/script>\n' + '        <script type="text/javascript" src="' + AGN.url("/assets/js/vendor/pickadate-3.5.6.js", true) + '"><\/script>\n' + '        <script type="text/javascript" src="' + AGN.url("/assets/js/vendor/pickadate-3.5.6.date.js", true) + '"><\/script>\n' + '        <script type="text/javascript" src="' + AGN.url("/js/lib/formbuilder/generated-form.js", true) + '"><\/script>\n' + '        <link rel="stylesheet" href="' + AGN.url("/assets/form.css", true) + '">' + "        {{ if (cssUrl) { }}\n" + '        <link rel="stylesheet" href="{{- cssUrl }}">\n' + "        {{ } }}\n" + "    </head>\n" + "    <body>\n" + '        <div class="container" style="margin-top: 50px;">\n' + '            <form action="form.action">\n' + "                {{= generatedHTML}}\n" + "            </form>\n" + "        </div>\n" + "    </body>\n" + "</html>";
    var Confirm = AGN.Lib.Confirm;
    var FormBuilder;
    var DEFAULT_ATTR = [ "required", "label", "description", "name", "className", "placeholder", "value" ];
    FormBuilder = function(textArea, options) {
        this.options = $.extend({}, options);
        var self = this;
        self.$el = $(textArea);
        self.$target = $(this.$el.data("target"));
        self.initCustomControls();
        self.builder = self.$el.formBuilder(FormBuilder.getBuilderDefaultOptions(self));
        self.defered = $.Deferred();
        if (self.options.data) {
            self.setJson(self.options.data);
        }
        self.builder.promise.then(function() {
            self.builder = self.$el.data("formBuilder");
            self.defered.resolve();
        });
    };
    FormBuilder.getBuilderDefaultOptions = function(builder) {
        return {
            roles: {},
            disabledAttrs: [ "access", "description" ],
            disableFields: [ "file", "autocomplete" ],
            defaultFields: FormBuilder.defaultFields(builder),
            disabledActionButtons: [ "data", "save" ],
            actionButtons: [ {
                id: "downloadHtml",
                className: "btn btn-info",
                label: t("workflow.reaction.download"),
                type: "button",
                events: {
                    click: function() {
                        builder.downloadHtml.bind(builder)();
                    }
                }
            }, {
                id: "generateHtml",
                className: "btn btn-success",
                label: t("userform.formBuilder.generateHtml"),
                type: "button",
                events: {
                    click: function() {
                        builder.generateHtmlToTarget.bind(builder)();
                    }
                }
            } ],
            editOnAdd: true,
            typeUserDisabledAttrs: {
                formName: DEFAULT_ATTR,
                mediapool: DEFAULT_ATTR,
                text: [ "subtype" ],
                textarea: [ "subtype" ]
            },
            typeUserAttrs: getTypeUserAttrs(builder),
            layoutTemplates: {
                agnMediapool: function() {
                    return document.createElement("span");
                }
            },
            fields: [ {
                type: "text"
            }, {
                type: "hidden"
            }, {
                type: "select"
            }, {
                type: "radio-group"
            }, {
                type: "checkbox-group"
            }, {
                type: "number"
            }, {
                type: "textarea"
            }, {
                type: "date"
            } ],
            templates: {
                text: Templates.default,
                hidden: Templates.hidden,
                textarea: Templates.default,
                date: Templates.default,
                select: Templates.default,
                "radio-group": Templates.default,
                "checkbox-group": Templates.default,
                number: Templates.default
            },
            controls: builder.controls,
            i18n: {
                locale: window.adminLocale,
                location: AGN.url("/js/lib/formbuilder/translation/")
            },
            controlOrder: [ "header", "paragraph", "mediapool", "", "text", "date", "textarea", "number", "", "select", "radio-group", "checkbox-group", "", "hidden", "formName", "button" ],
            inputSets: FormBuilder.getDefaultPresetsConfig(builder)
        };
    };
    FormBuilder.defaultFields = function(builder) {
        return [ {
            type: "hidden",
            name: "agnCTOKEN",
            value: builder.options.companyToken
        }, {
            type: "hidden",
            name: "agnUID",
            value: "$!agnUID"
        } ];
    };
    FormBuilder.getDefaultPresetsConfig = function(builder) {
        return [ {
            label: createTemplateName(t("userform.formBuilder.template.subscribe")),
            name: "subscribe",
            fields: [ {
                type: "hidden",
                name: "agnCTOKEN",
                value: builder.options.companyToken,
                label: " "
            }, {
                type: "hidden",
                name: "agnMAILINGLIST",
                value: "",
                label: " "
            }, {
                type: "hidden",
                name: "agnSUBSCRIBE",
                value: "1",
                label: " "
            }, {
                type: "hidden",
                name: "agnUID",
                value: "$!agnUID",
                label: " "
            }, {
                type: "text",
                name: "firstname",
                value: "$!customerData.firstname",
                emmField: "firstname",
                label: "Firstname:"
            }, {
                type: "text",
                name: "lastname",
                value: "$!customerData.lastname",
                emmField: "lastname",
                label: "Lastname:"
            }, {
                type: "text",
                name: "email",
                value: "$!customerData.email",
                emmField: "email",
                label: "Email:"
            }, {
                type: "button",
                subtype: "submit",
                style: "primary",
                label: "Subscribe"
            }, {
                type: "formName",
                label: " "
            } ]
        }, {
            label: createTemplateName(t("userform.formBuilder.template.unsubscribe")),
            name: "unsubscribe",
            fields: [ {
                type: "hidden",
                name: "agnCTOKEN",
                value: builder.options.companyToken,
                label: " "
            }, {
                type: "formName",
                label: " "
            }, {
                type: "hidden",
                name: "agnUID",
                value: "$!agnUID",
                label: " "
            }, {
                type: "button",
                subtype: "submit",
                style: "primary",
                label: "Unsubscribe"
            } ]
        }, {
            label: createTemplateName(t("userform.formBuilder.template.profile_change")),
            name: "profile_change",
            fields: [ {
                type: "hidden",
                name: "agnCTOKEN",
                value: builder.options.companyToken,
                label: " "
            }, {
                type: "hidden",
                name: "agnUID",
                value: "$!agnUID",
                label: " "
            }, {
                type: "formName",
                label: " "
            }, {
                type: "text",
                name: "firstname",
                value: "$!customerData.firstname",
                emmField: "firstname",
                label: "Firstname:"
            }, {
                type: "text",
                name: "lastname",
                value: "$!customerData.lastname",
                emmField: "lastname",
                label: "Lastname:"
            }, {
                type: "text",
                name: "email",
                value: "$!customerData.email",
                emmField: "email",
                label: "Email:"
            }, {
                type: "button",
                subtype: "submit",
                style: "primary",
                label: "Subscribe"
            } ]
        }, {
            label: createTemplateName(t("userform.formBuilder.template.other")),
            name: "other",
            fields: [ {
                type: "hidden",
                name: "agnCTOKEN",
                value: builder.options.companyToken,
                label: " "
            }, {
                type: "hidden",
                name: "agnUID",
                value: "$!agnUID",
                label: " "
            } ]
        } ];
    };
    FormBuilder.get = function(textArea, options) {
        var $el = $(textArea);
        var formBuilder = $el.data("_form-builder");
        if (formBuilder) {
            return formBuilder;
        }
        formBuilder = new FormBuilder(textArea, options);
        $el.data("_form-builder", formBuilder);
        return formBuilder;
    };
    FormBuilder.isCreated = function(textArea) {
        return !!$(textArea).data("_form-builder");
    };
    FormBuilder.prototype.initCustomControls = function() {
        this.controls = [];
        Utils.pushControl(this.controls, EmmControls.mediapool(this));
        Utils.pushControl(this.controls, EmmControls.nextform(this));
    };
    FormBuilder.prototype.generateHtml = function() {
        var formData = this.builder.actions.getData();
        var cssUrl = this.options.cssUrl;
        var $renderContainer = $("<form/>");
        $renderContainer.formRender({
            formData: formData,
            controls: this.controls,
            templates: {
                date: Templates.dateForRender
            }
        });
        var generatedHtml;
        if (template) {
            generatedHtml = _.template(template)({
                generatedHTML: $renderContainer.html(),
                cssUrl: cssUrl
            });
        } else {
            generatedHtml = $renderContainer.html();
        }
        $renderContainer.remove();
        generatedHtml = addNewLinesAfterTags(generatedHtml);
        return generatedHtml;
    };
    FormBuilder.prototype.generateHtmlToTarget = function() {
        var self = this;
        var $target = this.$target;
        if (!$target) {
            return;
        }
        var editor = AGN.Lib.Editor.get($target);
        if (!editor) {
            return;
        }
        var confirmationModal = this.options.confirmationModal;
        if (!confirmationModal || !editor.val()) {
            processHtmlGeneration(self, editor);
            return;
        }
        Confirm.createFromTemplate({}, "warning-html-generation-modal").done(function() {
            processHtmlGeneration(self, editor);
        });
    };
    FormBuilder.prototype.downloadHtml = function() {
        var generatedHtml = this.generateHtml();
        var encodedValue = window.btoa(generatedHtml);
        var fileName = "Generated form.txt";
        if (this.options.formName) {
            fileName = this.options.formName + ".txt";
        }
        var tmpElement = document.createElement("a");
        tmpElement.setAttribute("href", "data:application/octet-stream;charset=utf-8;base64," + encodedValue);
        tmpElement.setAttribute("download", fileName);
        tmpElement.style.display = "none";
        document.body.appendChild(tmpElement);
        tmpElement.click();
        document.body.removeChild(tmpElement);
    };
    FormBuilder.prototype.getJson = function() {
        return this.builder.actions.getData("json", false);
    };
    FormBuilder.prototype.getData = function() {
        return this.builder.actions.getData();
    };
    FormBuilder.prototype.setJson = function(data) {
        var self = this;
        self.defered.done(function() {
            return self.builder.actions.setData(data);
        });
    };
    FormBuilder.prototype.promise = function() {
        return this.defered.promise();
    };
    FormBuilder.prototype.getInitJson = function() {
        return JSON.stringify(this.options.data);
    };
    FormBuilder.prototype.isChanged = function() {
        var self = this;
        if (self.options.data) {
            return self.getInitJson() !== self.getJson();
        } else {
            return _.isEqual(self.getData(), FormBuilder.defaultFields(self));
        }
    };
    function processHtmlGeneration(formBuilder, editor) {
        editor.val(formBuilder.generateHtml());
        AGN.Lib.Messages(t("defaults.success"), t("userform.formBuilder.success.htmlGenerated"), "success");
    }
    function getTypeUserAttrs(builder) {
        var userAttrsByType = {
            formName: {
                formName: {
                    label: t("userform.formBuilder.formName"),
                    options: builder.options.namesJson.reduce(function(map, item) {
                        map[item] = item;
                        return map;
                    }, {})
                }
            },
            mediapool: {
                image: {
                    label: t("userform.formBuilder.mediapoolImage"),
                    options: builder.options.mediapoolImages
                },
                alt: {
                    label: t("userform.formBuilder.imageAlt"),
                    value: ""
                },
                width: {
                    label: t("userform.formBuilder.imageWidth"),
                    value: 0
                },
                height: {
                    label: t("userform.formBuilder.imageHeight"),
                    value: 0
                }
            },
            date: {
                emmField: {
                    label: t("userform.formBuilder.emmField"),
                    options: builder.options.dateProfileFields
                }
            },
            number: {
                emmField: {
                    label: t("userform.formBuilder.emmField"),
                    options: builder.options.numberProfileFields
                }
            },
            select: {
                emmField: {
                    label: t("userform.formBuilder.emmField"),
                    options: builder.options.profileFieldsForSelect
                }
            }
        };
        var typesForTextEmmAttrs = [ "text", "hidden", "textarea", "radio-group", "checkbox-group" ];
        typesForTextEmmAttrs.forEach(function(type) {
            userAttrsByType[type] = {
                emmField: {
                    label: t("userform.formBuilder.emmField"),
                    options: builder.options.textProfileFields
                }
            };
        });
        return userAttrsByType;
    }
    function createTemplateName(templateName) {
        return t("userform.formBuilder.template.template") + ": " + templateName;
    }
    function addNewLinesAfterTags(html) {
        if (!html || html.length <= 0) {
            return html;
        }
        return html.replace(/<\/.*?>/g, "$&\n");
    }
    AGN.Lib.FormBuilder.FormBuilder = FormBuilder;
})();

AGN.Lib.DomInitializer.new("account-data", function() {
    var $accountInitials = $("#account-data .account-initials");
    var $accountDataInfobox = $accountInitials.next(".account-data-infobox");
    $accountInitials.popover({
        trigger: "hover",
        container: "body",
        html: true,
        content: $accountDataInfobox.html()
    });
});

AGN.Lib.CoreInitializer.new("ace", function($scope) {
    if (!$scope) {
        $scope = $(document);
    }
    _.each($scope.find(".js-editor, .js-editor-text, .js-editor-eql, .js-editor-css"), function(textArea) {
        AGN.Lib.Editor.get($(textArea));
    });
});

(function() {
    AGN.Lib.CoreInitializer.new("checkbox-hider", function($scope) {
        if (!$scope) {
            $scope = $(document);
        }
        _.each($scope.find("[data-show-by-checkbox]"), function(el) {
            var selector = $(el);
            var checkboxSelector = $(selector.data("show-by-checkbox"));
            updateVisibleByCheckbox(selector, checkboxSelector, true);
            addCheckboxListener(selector, checkboxSelector, true);
        });
        _.each($scope.find("[data-hide-by-checkbox]"), function(el) {
            var selector = $(el);
            var checkboxSelector = $(selector.data("hide-by-checkbox"));
            updateVisibleByCheckbox(selector, checkboxSelector, false);
            addCheckboxListener(selector, checkboxSelector, false);
        });
        _.each($scope.find("[data-show-by-select]"), function(el) {
            var selector = $(el);
            var selectSelector = $(selector.data("show-by-select"));
            var hideForData = selector.data("show-by-select-values");
            if (selectSelector && hideForData) {
                var options = hideForData.toString().split(",");
                for (var i = 0; i < options.length; i++) {
                    options[i] = options[i].trim();
                }
                updateVisibleBySelect(selector, selectSelector, options, true);
                addSelectListener(selector, selectSelector, options, true);
            }
        });
        _.each($scope.find("[data-hide-by-select]"), function(el) {
            var selector = $(el);
            var selectSelector = $(selector.data("hide-by-select"));
            var hideForData = selector.data("hide-by-select-values");
            if (selectSelector && hideForData) {
                var options = hideForData.toString().split(",");
                for (var i = 0; i < options.length; i++) {
                    options[i] = options[i].trim();
                }
                updateVisibleBySelect(selector, selectSelector, options, false);
                addSelectListener(selector, selectSelector, options, false);
            }
        });
    });
    function addCheckboxListener(selector, checkboxSelector, showIfChecked) {
        checkboxSelector.change(function() {
            updateVisibleByCheckbox(selector, checkboxSelector, showIfChecked);
        });
    }
    function updateVisibleByCheckbox(selector, checkboxSelector, showIfChecked) {
        if (showIfChecked) {
            if (checkboxSelector.is(":checked")) {
                selector.removeClass("hidden");
            } else {
                selector.addClass("hidden");
            }
        } else {
            if (!checkboxSelector.is(":checked")) {
                selector.removeClass("hidden");
            } else {
                selector.addClass("hidden");
            }
        }
    }
    function addSelectListener(selector, selectSelector, options, showIfChecked) {
        selectSelector.change(function() {
            updateVisibleBySelect(selector, selectSelector, options, showIfChecked);
        });
    }
    function updateVisibleBySelect(selector, selectSelector, options, showIfChecked) {
        var selectValue = selectSelector.val();
        var selected = false;
        for (var i = 0; i < options.length; i++) {
            if (options[i] == selectValue) {
                selected = true;
                break;
            }
        }
        var forSelectFun, forNotSelectFun;
        if (showIfChecked) {
            forSelectFun = function() {
                selector.removeClass("hidden");
            };
            forNotSelectFun = function() {
                selector.addClass("hidden");
            };
        } else {
            forSelectFun = function() {
                selector.addClass("hidden");
            };
            forNotSelectFun = function() {
                selector.removeClass("hidden");
            };
        }
        selected ? forSelectFun() : forNotSelectFun();
    }
})();

(function() {
    var AutoSave = AGN.Lib.AutoSave;
    function restoreValue($target, value) {
        var id = $target.attr("id"), editor = $target.data("_editor");
        if (window.CKEDITOR && CKEDITOR.instances[id]) {
            CKEDITOR.instances[id].setData(value);
        } else if (editor) {
            editor.val(value);
        } else {
            $target.val(value);
        }
    }
    AGN.Lib.CoreInitializer.new("auto-save", [ "ace" ], function($scope) {
        if (!$scope) {
            $scope = $(document);
        }
        _.each($scope.find("[data-autosave-scope]"), function(e) {
            var $this = $(e);
            var scopeId = $this.data("autosave-scope");
            var period = $this.data("autosave-period");
            var $targets = $this.all("[data-autosave]");
            if ($targets.length > 0) {
                function save() {
                    $targets = $targets.filter(function(index, e) {
                        return document.body.contains(e);
                    });
                    if ($targets.length > 0) {
                        var values = {};
                        _.each($targets, function(target) {
                            var $target = $(target);
                            values["value#" + $target.data("autosave")] = $target.val();
                        });
                        return values;
                    }
                    return false;
                }
                function check(values) {
                    var available = $.map($targets, function(target) {
                        var $target = $(target);
                        var key = "value#" + $target.data("autosave");
                        if (key in values) {
                            var currentValue = $target.val();
                            var restoredValue = values[key];
                            if (currentValue != restoredValue) {
                                if ($target.is("[data-autorestore]")) {
                                    restoreValue($target, restoredValue);
                                } else {
                                    return {
                                        target: $target,
                                        value: restoredValue
                                    };
                                }
                            }
                            return null;
                        }
                    });
                    if (available.length > 0) {
                        return available;
                    }
                    return false;
                }
                function restore(values) {
                    _.each(values, function(a) {
                        restoreValue(a.target, a.value);
                    });
                }
                AutoSave.initialize(scopeId, save, check, restore, period);
            }
        });
    });
})();

AGN.Lib.DomInitializer.new("autosubmit", function($e) {
    setTimeout(function() {
        AGN.Lib.Form.get($e).submit();
    }, 100);
});

AGN.Lib.DomInitializer.new("calendar-table", function() {
    var conf = this.config;
    AGN.Lib.CalendarService.setUp(conf);
    window.setInterval(AGN.Lib.CalendarService.checkProgress, 500);
    if (AGN.Lib.CalendarService.getMonthMode()) {
        AGN.Lib.CalendarService.generateMonthCalendar(AGN.Lib.CalendarService.getCurMonth(), AGN.Lib.CalendarService.getCurYear());
    } else {
        AGN.Lib.CalendarService.generateWeekCalendar(AGN.Lib.CalendarService.getCurMonth(), AGN.Lib.CalendarService.getCurYear(), AGN.Lib.CalendarService.getCurDay());
    }
    AGN.Lib.CalendarService.generateUnsentMailingsTable();
    var Action = AGN.Lib.Action;
    Action.new({
        click: "#dateTimePicker"
    }, function() {
        this.event.stopPropagation();
    });
    Action.new({
        click: "#dateTimePickerButton"
    }, function() {
        this.event.stopPropagation();
    });
    Action.new({
        click: ".js-calendar-navigate-previous"
    }, function() {
        AGN.Lib.CalendarService.prevEntry();
        this.event.preventDefault();
        return false;
    });
    Action.new({
        click: ".js-calendar-navigate-next"
    }, function() {
        AGN.Lib.CalendarService.nextEntry();
        this.event.preventDefault();
        return false;
    });
    Action.new({
        click: ".js-calendar-navigate-today"
    }, function() {
        AGN.Lib.CalendarService.jumpToday();
        this.event.preventDefault();
        return false;
    });
    Action.new({
        click: ".js-calendar-view-month"
    }, function() {
        AGN.Lib.CalendarService.toggleDateSelectionMode("SELECT_MONTH");
        this.event.preventDefault();
        return false;
    });
    Action.new({
        click: ".js-calendar-view-week"
    }, function() {
        AGN.Lib.CalendarService.toggleDateSelectionMode("SELECT_WEEK");
        this.event.preventDefault();
        return false;
    });
    Action.new({
        click: ".js-calendar-list-unsent"
    }, function() {
        AGN.Lib.CalendarService.generateUnsentMailingsTable();
        this.event.preventDefault();
        return false;
    });
    Action.new({
        click: ".js-calendar-list-planned"
    }, function() {
        AGN.Lib.CalendarService.generatePlannedMailingsTable();
        this.event.preventDefault();
        return false;
    });
    Action.new({
        click: "#comment-save-button"
    }, function() {
        AGN.Lib.ReminderService.reminder.onSave();
    });
    Action.new({
        click: ".calendar-comments-add"
    }, function() {
        var $el = this.el, date;
        date = $el.parents(".calendar-day-container").data("date");
        AGN.Lib.CalendarService.showCommentDialog(AGN.Lib.ReminderService.getNewReminder(date, conf));
        return false;
    });
    Action.new({
        click: ".calendar-comments-toggle"
    }, function() {
        var $el = this.el, date;
        date = $el.parents(".calendar-day-container").data("date");
        AGN.Lib.CalendarService.toggleComment(date);
        return false;
    });
    Action.new({
        change: ".js-calendar-toggle-all-comments"
    }, function() {
        if (this.el.prop("checked")) {
            $(".calendar-table").find(".calendar-comment").show();
        } else {
            $(".calendar-table").find(".calendar-comment").hide();
        }
        AGN.Lib.CalendarService.adjustSidebarHeight();
    });
    Action.new({
        change: "#scheduleReminder"
    }, function() {
        AGN.Lib.ReminderService.onScheduleChanged();
    });
    Action.new({
        change: "#isDeadline"
    }, function() {
        AGN.Lib.ReminderService.onDeadlineChanged();
    });
    Action.new({
        change: "#month_list, #month_list_year, #weeks_list"
    }, function() {
        AGN.Lib.CalendarService.showDate();
    });
    Action.new({
        change: "#weeks_list_year"
    }, function() {
        AGN.Lib.CalendarService.createWeeksList(this.el[0]);
    });
    Action.new({
        change: '#reminderDetails input[name="userType"]'
    }, function() {
        var $el = this.el[0];
        AGN.Lib.ReminderService.onUserTypeChanged($el.value);
    });
    this.addAction({
        mouseover: "mailing-popup"
    }, function() {
        var $badge = this.el, $popup = $("#popup-" + $badge.data("mailing-id"));
        if ($popup.exists()) {
            var viewportTop = $(window).scrollTop();
            var popupHeight = $popup.outerHeight();
            var margin = 15;
            var badgeTop = $badge.offset().top;
            var badgeBottom = badgeTop + $badge.outerHeight();
            var spaceAbove = badgeTop - viewportTop - margin;
            var spaceBelow = viewportTop + $(window).outerHeight() - badgeBottom;
            var positionTop;
            if (popupHeight <= spaceAbove || spaceAbove > spaceBelow) {
                positionTop = badgeTop - margin - popupHeight;
                $popup.addClass("top");
                $popup.removeClass("bottom");
            } else {
                positionTop = badgeBottom + margin;
                $popup.addClass("bottom");
                $popup.removeClass("top");
            }
            $popup.css({
                top: positionTop,
                left: $badge.offset().left + $badge.outerWidth() / 2 - $popup.outerWidth() / 2
            });
            $popup.css("z-index", "1500");
            $popup.css("display", "block");
        }
    });
    this.addAction({
        mouseout: "mailing-popup"
    }, function() {
        var mailingId = this.el.data("mailing-id");
        $("#popup-" + mailingId).css("display", "none");
    });
});

(function() {
    var CalendarService;
    CalendarService = function() {
        var dayWidth = 0;
        var localeDatePattern;
        var currentServerDateTime;
        var firstDayOfWeek;
        var curWeek;
        var pushStatusSent;
        var pushStatusScheduled;
        var secondsBeforeWaitMessage;
        var adminName;
        var urlCalendarUnsent;
        var urlCalendarPlanned;
        var urlCalendarMailingsList;
        var urlCalendarMailingsMove;
        var urlCalendarPushesList;
        var urlCalendarPushesMove;
        var urlCalendarAutoOptimization;
        var urlCalendarCommentList;
        var urlCalendarCommentSave;
        var urlCalendarCommentRemove;
        var urlMailingView;
        var urlMailingStatisticsView;
        var isStatisticsViewPermitted;
        var monthNames = t("date.monthsFull");
        var curDate = new Date();
        curDate.setHours(0, 0, 0, 0);
        var curMonth = curDate.getMonth();
        var curYear = curDate.getFullYear();
        var curDay = curDate.getDate();
        var monthMode = true;
        var showComments = false;
        var showCommentsByDay = {};
        var viewMode = "MONTH";
        var weeksListArray = [];
        var secondsAfterLastRequest = 0;
        var requestInProgress = false;
        var requestNumberActive = 0;
        function getMonthMode() {
            return monthMode;
        }
        this.getMonthMode = getMonthMode;
        function getDayWidth() {
            return dayWidth;
        }
        this.getDayWidth = getDayWidth;
        function getCurMonth() {
            return curMonth;
        }
        this.getCurMonth = getCurMonth;
        function getCurYear() {
            return curYear;
        }
        this.getCurYear = getCurYear;
        function getCurDay() {
            return curDay;
        }
        this.getCurDay = getCurDay;
        function setDayWidth(val) {
            dayWidth = val;
        }
        this.setDayWidth = setDayWidth;
        function setUp(conf) {
            localeDatePattern = conf.localeDatePattern;
            currentServerDateTime = new Date(conf.currentServerTime);
            firstDayOfWeek = conf.firstDayOfWeek;
            curWeek = curDate.getWeek(firstDayOfWeek);
            pushStatusSent = conf.pushStatusSent;
            pushStatusScheduled = conf.pushStatusScheduled;
            adminName = conf.adminName;
            secondsBeforeWaitMessage = conf.secondsBeforeWaitMessage;
            urlCalendarUnsent = conf.urls.CALENDAR_UNSENT_MAILINGS;
            urlCalendarPlanned = conf.urls.CALENDAR_PLANNED_MAILINGS;
            urlCalendarMailingsList = conf.urls.CALENDAR_MAILINGS_LIST;
            urlCalendarMailingsMove = conf.urls.CALENDAR_MAILINGS_MOVE;
            urlCalendarPushesList = conf.urls.CALENDAR_PUSHES_LIST;
            urlCalendarPushesMove = conf.urls.CALENDAR_PUSHES_MOVE;
            urlCalendarAutoOptimization = conf.urls.CALENDAR_AUTO_OPTIMIZATION;
            urlCalendarCommentList = conf.urls.CALENDAR_COMMENT_LIST;
            urlCalendarCommentSave = conf.urls.CALENDAR_COMMENT_SAVE;
            urlCalendarCommentRemove = conf.urls.CALENDAR_COMMENT_REMOVE;
            urlMailingView = conf.urls.MAILING_VIEW;
            urlMailingStatisticsView = conf.urls.MAILING_STATISTICS_VIEW;
            isStatisticsViewPermitted = conf.isStatisticsViewPermitted;
        }
        this.setUp = setUp;
        function toggleDateSelectionMode(dateMode) {
            if (dateMode == "SELECT_MONTH") {
                $("#linkSelectByMonth").toggleClass("active");
                $("#linkSelectByWeek").toggleClass("active");
                $("#dateSelectByMonth").css("display", "inline");
                $("#dateSelectByWeek").css("display", "none");
                changeCalendarMode(dateMode);
                viewMode = "MONTH";
            }
            if (dateMode == "SELECT_WEEK") {
                $("#linkSelectByMonth").toggleClass("active");
                $("#linkSelectByWeek").toggleClass("active");
                $("#dateSelectByMonth").css("display", "none");
                $("#dateSelectByWeek").css("display", "inline");
                createWeeksList($("#weeks_list_year")[0]);
                changeCalendarMode(dateMode);
                viewMode = "WEEK";
            }
        }
        this.toggleDateSelectionMode = toggleDateSelectionMode;
        function checkProgress() {
            if (requestInProgress) {
                secondsAfterLastRequest += .5;
                if (secondsAfterLastRequest >= secondsBeforeWaitMessage) {
                    $("#calendar-wait-notification").show();
                }
            } else {
                secondsAfterLastRequest = 0;
            }
        }
        this.checkProgress = checkProgress;
        function startProgress() {
            requestInProgress = true;
            requestNumberActive++;
        }
        this.startProgress = startProgress;
        function stopProgress() {
            requestNumberActive--;
            if (requestNumberActive <= 0) {
                requestNumberActive = 0;
                requestInProgress = false;
                $("#calendar-wait-notification").hide();
            }
        }
        this.stopProgress = stopProgress;
        function generateMonthCalendar(month, year) {
            showCommentsByDay = {};
            var date = new Date(year, month, 1);
            var monthDaysCount = daysInMonth(month + 1, year);
            var offset = date.getDay() - firstDayOfWeek;
            if (offset < 0) {
                offset = 7 + offset;
            }
            var weeksCount = Math.ceil((monthDaysCount + offset) / 7);
            var startDate = new Date(year, month, 1 - offset);
            var endDate = new Date(year, month, 1 + weeksCount * 7);
            date = new Date(startDate);
            for (var weekIndex = 0; weekIndex < weeksCount; weekIndex++) {
                var trId = "row-" + (weekIndex + 1);
                $("#calendar-container").append('<tr id="' + trId + '">' + '<td class="calendar-week-number-cell">' + date.getWeek(firstDayOfWeek) + "</td>" + "</tr>");
                for (var index = 0; index < 7; index++) {
                    var alienMonth = date.getMonth() != month;
                    addDayToCalendar(date, date.getDate(), "", true, trId, alienMonth);
                    date.setDate(date.getDate() + 1);
                }
            }
            $("#calendar-days").html(monthNames[month] + " " + year);
            getComments(startDate, endDate);
            getMailings(startDate, endDate);
            getCalendarPushes(startDate, endDate);
            getAutoOptimizations(startDate, endDate);
            registerDayContainerHandlers();
            setAllCommentsCheckState();
            adjustSidebarHeight();
            synchronizeMonthsList(month, year);
        }
        this.generateMonthCalendar = generateMonthCalendar;
        function generateWeekCalendar(month, year, day) {
            var weekMilliseconds = 6048e5;
            showCommentsByDay = {};
            var date = new Date(year, month, day);
            var diff = date.getDay();
            date.setDate(day - date.getDay() - 1 + firstDayOfWeek);
            var startDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
            startDate.setDate(startDate.getDate() + 1);
            curWeek = startDate.getWeek(firstDayOfWeek);
            if (month == 0 && day == 1 && startDate.getWeek(firstDayOfWeek) != 1) {
                startDate.setTime(startDate.getTime() + weekMilliseconds);
                date.setTime(date.getTime() + weekMilliseconds);
            }
            $("#calendar-container").append('<tr id="week-row"></tr>');
            $("#week-row").append('<td class="calendar-week-number-cell">' + startDate.getWeek(firstDayOfWeek) + "</td>");
            for (var i = 0; i <= 6; i++) {
                date.setDate(date.getDate() + 1);
                addDayToCalendar(date, AGN.Lib.DateFormat.format(date, localeDatePattern), "calendar-week-day-container", false, "week-row", false);
            }
            $("#calendar-days").html(AGN.Lib.DateFormat.format(startDate, localeDatePattern) + " - " + AGN.Lib.DateFormat.format(date, localeDatePattern));
            getComments(startDate, date);
            getMailings(startDate, date);
            getCalendarPushes(startDate, date);
            getAutoOptimizations(startDate, date);
            registerDayContainerHandlers();
            adjustSidebarHeight();
            synchronizeWeeksList(month, year, day);
        }
        this.generateWeekCalendar = generateWeekCalendar;
        function addDragging($badge, stack) {
            var $popup;
            $badge.draggable({
                stack: stack,
                revert: "invalid",
                distance: 20,
                start: function() {
                    $popup = $("#popup-" + $badge.prop("id"));
                    $popup.hide();
                    $popup.detach();
                    clearSelection();
                },
                stop: function() {
                    $("#calendar-popup-holder").append($popup);
                }
            });
        }
        function addMailingDragging($badge) {
            addDragging($badge, ".calendar-mail-label");
        }
        this.addMailingDragging = addMailingDragging;
        function addCommentDragging($badge) {
            addDragging($badge, ".calendar-comment");
        }
        this.addCommentDragging = addCommentDragging;
        function checkHideCommentIconsVisibility() {
            $(".calendar-comments-toggle").css("visibility", "hidden");
            $(".calendar-day-container").has(".calendar-comment").each(function() {
                $(this).find(".calendar-comments-toggle").css("visibility", "visible");
            });
            adjustSidebarHeight();
        }
        this.checkHideCommentIconsVisibility = checkHideCommentIconsVisibility;
        function generateUnsentMailingsTable() {
            getUnsentMailings();
        }
        this.generateUnsentMailingsTable = generateUnsentMailingsTable;
        function generatePlannedMailingsTable() {
            getPlannedMailings();
        }
        this.generatePlannedMailingsTable = generatePlannedMailingsTable;
        function clearSelection() {
            var sel;
            if (document.selection && document.selection.empty) {
                document.selection.empty();
            } else if (window.getSelection) {
                sel = window.getSelection();
                if (sel && sel.removeAllRanges) sel.removeAllRanges();
            }
        }
        this.clearSelection = clearSelection;
        function daysInMonth(month, year) {
            return new Date(year, month, 0).getDate();
        }
        this.daysInMonth = daysInMonth;
        function changeCalendarMode(dateMode) {
            var curSelectedMonth = dateMode == "SELECT_MONTH";
            if (curSelectedMonth && monthMode || !curSelectedMonth && !monthMode) {
                if (monthMode) {
                    synchronizeMonthsList(curMonth, curYear);
                } else {
                    synchronizeWeeksList(curMonth, curYear, curDay);
                }
                return;
            }
            removeCurrentCalendar();
            if (curSelectedMonth) {
                var testYears = new Date(curYear, curMonth, curDay);
                testYears.setDate(testYears.getDate() + 7);
                if (curWeek == 1 && curYear < testYears.getFullYear()) {
                    curMonth = 0;
                    curYear++;
                    curDay = 1;
                }
                generateMonthCalendar(curMonth, curYear);
                monthMode = true;
                showComments = false;
            } else {
                generateWeekCalendar(curMonth, curYear, curDay);
                monthMode = false;
                showComments = true;
            }
        }
        this.changeCalendarMode = changeCalendarMode;
        function removeCurrentCalendar() {
            $("#calendar-container").empty();
            $("#calendar-popup-holder").empty();
            $(".calendar-mail-label").remove();
        }
        this.removeCurrentCalendar = removeCurrentCalendar;
        function prevEntry() {
            if (monthMode) {
                prevMonth();
            } else {
                switchWeek(true);
            }
        }
        this.prevEntry = prevEntry;
        function nextEntry() {
            if (monthMode) {
                nextMonth();
            } else {
                switchWeek(false);
            }
        }
        this.nextEntry = nextEntry;
        function switchWeek(back) {
            var dayDiff = back ? -7 : 7;
            removeCurrentCalendar();
            var date = new Date(curYear, curMonth, curDay);
            date.setDate(date.getDate() + dayDiff);
            curDay = date.getDate();
            curMonth = date.getMonth();
            curYear = date.getFullYear();
            date.setDate(date.getDate() + dayDiff);
            var monthYears = $("#month_list_year option");
            var minYear = Number(monthYears[monthYears.length - 1].value);
            var maxYear = Number(monthYears[0].value);
            if (date.getFullYear() < minYear) {
                addMinYearControl();
            }
            if (date.getFullYear() > maxYear) {
                addMaxYearControl();
            }
            generateWeekCalendar(curMonth, curYear, curDay);
        }
        this.switchWeek = switchWeek;
        function prevMonth() {
            removeCurrentCalendar();
            curMonth--;
            if (curMonth < 0) {
                curMonth = 11;
                curYear--;
            }
            var monthYears = $("#month_list_year option");
            var minYear = Number(monthYears[monthYears.length - 1].value);
            if (curYear < minYear) {
                addMinYearControl();
            }
            generateMonthCalendar(curMonth, curYear);
        }
        this.prevMonth = prevMonth;
        function nextMonth() {
            removeCurrentCalendar();
            curMonth++;
            if (curMonth > 11) {
                curMonth = 0;
                curYear++;
            }
            var monthYears = $("#month_list_year option");
            var maxYear = Number(monthYears[0].value);
            if (curYear > maxYear) {
                addMaxYearControl();
            }
            generateMonthCalendar(curMonth, curYear);
        }
        this.nextMonth = nextMonth;
        function addDayToCalendar(date, output, additionalClass, commentShowButton, trId, alienMonth) {
            var dayStyle = "";
            var weekEndLabelStyle = "";
            if (alienMonth) {
                dayStyle = "calendar-another-month-day";
            } else {
                var renderDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
                if (renderDate.getTime() == curDate.getTime()) {
                    dayStyle = "calendar-current-day";
                }
                if (renderDate.getDay() == 0 || renderDate.getDay() == 6) {
                    dayStyle += " calendar-weekend-day";
                    weekEndLabelStyle = " calendar-weekend-day-label";
                }
            }
            var dateAsString = dateToServiceFormat(new Date(date.getFullYear(), date.getMonth(), date.getDate()));
            var newId = "day-" + dateAsString;
            $("#" + trId).append('<td id="' + newId + '" data-date="' + dateAsString + '" class="calendar-day-container ' + additionalClass + " " + dayStyle + '"></td>');
            $("#" + newId).append('<div class="calendar-day-label' + weekEndLabelStyle + '" id="label-' + newId + '"></div>');
            $("#label-" + newId).append(output);
            addDayPopup(newId);
            if (commentShowButton) {
                addCommentsShowButton(newId);
            }
            showCommentsByDay[newId] = !commentShowButton;
        }
        this.addDayToCalendar = addDayToCalendar;
        function addCommentsShowButton(dayId) {
            $("#label-" + dayId).append('<button type="button" class="calendar-comments-toggle" title="' + t("calendar.title.show_hide_comment") + '"><i class="icon icon-comments"></i></button>');
            $("#" + dayId + " .calendar-comments-toggle").css("visibility", "hidden");
        }
        this.addCommentsShowButton = addCommentsShowButton;
        function addDayPopup(dayId) {
            $("#" + "label-" + dayId).append('<button type="button" class="calendar-comments-add" title="' + t("calendar.title.new_comment") + '"><i class="icon icon-plus"></i></button>');
            $("#" + "label-" + dayId + " .calendar-comments-add").css("visibility", "hidden");
            $("#" + dayId).mouseover(function() {
                if (!$("#" + dayId).hasClass("calendar-another-month-day")) {
                    $("#" + "label-" + dayId + " .calendar-comments-add").css("visibility", "visible");
                }
            });
            $("#" + dayId).mouseout(function() {
                $("#" + "label-" + dayId + " .calendar-comments-add").css("visibility", "hidden");
            });
        }
        this.addDayPopup = addDayPopup;
        function toggleComment(dayId) {
            if (showCommentsByDay["day-" + dayId]) {
                $("#day-" + dayId + " .calendar-comment").hide();
            } else {
                $("#day-" + dayId + " .calendar-comment").show();
            }
            showCommentsByDay["day-" + dayId] = !showCommentsByDay["day-" + dayId];
            adjustSidebarHeight();
        }
        this.toggleComment = toggleComment;
        function validateComment(commentText) {
            if (commentText == "") {
                $("#calendar-comment-error").html(t("calendar.error.empty_comment"));
                return false;
            }
            if (byteCount(commentText) > 1e3) {
                $("#calendar-comment-error").html(t("calendar.error.long_comment"));
                return false;
            }
            return true;
        }
        this.validateComment = validateComment;
        function parseRecipients(recipients) {
            if (recipients) {
                var splitted = recipients.split(/[,; \t\n]+/);
                var emails = [];
                for (var i = 0; i < splitted.length; i++) {
                    if (splitted[i]) {
                        emails.push(splitted[i]);
                    }
                }
                return emails;
            } else {
                return [];
            }
        }
        this.parseRecipients = parseRecipients;
        function validateEmails(emails) {
            if (!emails || emails.length == 0) {
                $("#calendar-comment-error").html(t("calendar.error.empty_recipient_list"));
                return false;
            }
            var recipients = emails.join(",");
            if (byteCount(recipients) > 2e3) {
                $("#calendar-comment-error").html(t("calendar.error.long_recipient_list"));
                return false;
            }
            var re = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i;
            for (var i = 0; i < emails.length; i++) {
                if (!re.test(emails[i])) {
                    $("#calendar-comment-error").html(t("calendar.error.invalid_email") + " " + emails[i]);
                    return false;
                }
            }
            return true;
        }
        this.validateEmails = validateEmails;
        function showCommentDialog(reminder) {
            AGN.Lib.Modal.create($("#calendar-dialog-modal-template").html());
            AGN.Lib.ReminderService.fillCommentDialog(reminder);
            $("#calendar-comment-error").html("");
            AGN.Lib.ReminderService.updateVisibility();
        }
        this.showCommentDialog = showCommentDialog;
        function addComment(reminder) {
            var commentId = "comment-" + reminder.id;
            var dayId = "day-" + reminder.getDateAsString();
            var text = reminder.text.replace(/\n/g, "<br>");
            var $day = $("#" + dayId);
            var $comment = $("#" + commentId);
            if ($comment.exists() || !$day.exists()) {
                return;
            }
            $comment = $('<div id="' + commentId + '" data-comment-id="' + reminder.id + '" class="calendar-mail-label calendar-comment">' + '<span class="calendar-badge comment-badge">' + '<span class="comment-text-content">' + text + "</span>" + "</span>" + "</div>");
            if (!showCommentsByDay[dayId]) {
                $comment.css("display", "none");
            }
            $day.append($comment);
            var $popupHolder = $("#calendar-popup-holder");
            $popupHolder.append('<input type="hidden" id="deadline-' + commentId + '" name="' + commentId + '" value="' + reminder.isDeadline + '"/>');
            $popupHolder.append('<input type="hidden" id="notified-' + commentId + '" name="' + commentId + '" value="' + reminder.isNotified + '"/>');
            $popupHolder.append('<input type="hidden" id="emm-user-type-' + commentId + '" name="' + commentId + '" value="' + reminder.isEmmUserType + '"/>');
            $popupHolder.append('<input type="hidden" id="notify-admin-id-' + commentId + '" name="' + commentId + '" value="' + reminder.notifyAdminId + '"/>');
            $popupHolder.append('<input type="hidden" id="recipients-' + commentId + '" name="' + commentId + '" value="' + reminder.recipients + '"/>');
            $popupHolder.append('<input type="hidden" id="plannedSendDate-' + commentId + '" name="' + commentId + '" value="' + reminder.getPlannedSendDateAsString() + '"/>');
            $comment.dblclick(function() {
                AGN.Lib.CalendarService.showCommentDialog(AGN.Lib.ReminderService.getReminder(commentId, reminder.currentAdminName));
            });
            var $removeButton = $('<button type="button" id="remove-' + commentId + '" class="calendar-comments-remove"><i class="icon icon-trash-o"></i></button>');
            $comment.find(".comment-badge").append($removeButton);
            $removeButton.attr("title", t("calendar.title.delete_comment"));
            $removeButton.on("click", function() {
                $("#deadline-" + commentId).remove();
                $("#popup-" + commentId).remove();
                $comment.remove();
                removeCommentDB(commentId);
                checkHideCommentIconsVisibility();
                adjustSidebarHeight();
                return false;
            });
            $comment.mouseover(function() {
                $removeButton.css("display", "block");
            });
            $comment.mouseout(function() {
                $removeButton.css("display", "none");
            });
            addCommentDragging($comment);
            createCommentFullTextPopup(reminder.id, text);
        }
        this.addComment = addComment;
        function createCommentFullTextPopup(commentId, commentText) {
            $("#calendar-popup-holder").append('<div class="calendar-mail-popup" id="popup-comment-' + commentId + '"></div>');
            $("#popup-comment-" + commentId).append('<div class="arrow"></div>');
            $("#popup-comment-" + commentId).append('<div class="calendar-mail-popup-header">' + t("calendar.common.comment") + "</div>");
            $("#popup-comment-" + commentId).append('<div class="calendar-mail-popup-content"><p class="comment-text-content">' + commentText + "</p></div>");
            $("#popup-comment-" + commentId).css("display", "none");
            $("#popup-comment-" + commentId).css("word-wrap", "break-word");
            $("#comment-" + commentId).mouseover(function() {
                var $popup = $("#popup-comment-" + commentId), $trigger = $(this);
                var offsetTop = $trigger.offset().top - $(window).scrollTop(), triggerHeight = $trigger.outerHeight(), popupHeight = $popup.outerHeight(), margin = 15, posTop = $trigger.offset().top + triggerHeight + margin;
                if (popupHeight + margin < offsetTop) {
                    posTop = $trigger.offset().top - popupHeight - margin;
                    $popup.addClass("top");
                    $popup.removeClass("bottom");
                } else {
                    $popup.addClass("bottom");
                    $popup.removeClass("top");
                }
                $popup.css({
                    top: posTop,
                    left: $trigger.offset().left + $trigger.outerWidth() / 2 - $popup.outerWidth() / 2
                });
                $popup.css("z-index", "1500");
                $popup.css("display", "block");
            });
            $("#comment-" + commentId).mouseout(function() {
                $("#popup-comment-" + commentId).css("display", "none");
            });
        }
        function doCommentDrop($droppable, $draggable, commentId) {
            var date = $droppable.data("date");
            if (!showCommentsByDay["day-" + date] && !$(".js-calendar-toggle-all-comments").prop("checked")) {
                $draggable.hide();
            }
            $droppable.append($draggable);
            saveCommentDB(AGN.Lib.ReminderService.getReminder("comment-" + commentId, adminName));
            adjustSidebarHeight();
            checkHideCommentIconsVisibility();
        }
        function doMailingDrop($droppable, $draggable, mailingId) {
            var date = $droppable.data("date");
            if ($draggable.attr("sent") != "true") {
                var sendTime = $draggable.data("time");
                var sendDateTime = dateFromServiceFormat(date, sendTime);
                if (sendDateTime >= currentServerDateTime) {
                    if ($draggable.attr("planned") == "true") {
                        var $a = $draggable.find("a");
                        if ($a.hasClass("calendar-mailing-status-planned-in-past")) {
                            var statusClass = "calendar-" + $draggable.attr("workstatus").replace(/\./g, "-");
                            $a.addClass(statusClass).removeClass("calendar-mailing-status-planned-in-past");
                        }
                    }
                    var genDate = new Date(sendDateTime);
                    genDate.setHours(genDate.getHours() - 3);
                    if (genDate < currentServerDateTime) {
                        sendTime = null;
                        $draggable.data("time", null);
                    }
                    var $badges = $droppable.find(".calendar-mail-label");
                    var inserted = false;
                    if (sendTime) {
                        $($badges.get().reverse()).each(function() {
                            var $badge = $(this);
                            var foundTime = $badge.data("time");
                            if (foundTime && foundTime < sendTime) {
                                $badge.after($draggable);
                                inserted = true;
                            }
                        });
                    }
                    if (!inserted) {
                        var $lastMailingBadge = $badges.filter("[data-mailing-id]").last();
                        if ($lastMailingBadge.length) {
                            $lastMailingBadge.after($draggable);
                            inserted = true;
                        } else {
                            $droppable.append($draggable);
                        }
                    }
                    adjustSidebarHeight();
                    saveMailingMoveDB(mailingId, date);
                }
            }
        }
        function doPushDrop($droppable, $draggable, pushId) {
            var date = $droppable.data("date");
            switch ($draggable.data("status")) {
              case pushStatusSent:
                return;

              case pushStatusScheduled:
                if (dateFromServiceFormat(date, "00:00") < curDate) {
                    return;
                }
                break;
            }
            var $lastPushBadge = $droppable.find(".calendar-mail-label").filter("[data-push-id]").last();
            if ($lastPushBadge.length) {
                $lastPushBadge.after($draggable);
            } else {
                $droppable.append($draggable);
            }
            savePushMoveDB(pushId, date);
        }
        function registerDayContainerHandlers() {
            $(".calendar-day-container").droppable({
                hoverClass: "calendar-day-hover",
                drop: function(event, ui) {
                    var $this = $(this);
                    var entityType = "UNKNOWN";
                    var entityId = ui.draggable.data("comment-id");
                    if (entityId) {
                        entityType = "COMMENT";
                    } else {
                        entityId = ui.draggable.data("mailing-id");
                        if (entityId) {
                            entityType = "MAILING";
                        } else {
                            entityId = ui.draggable.data("push-id");
                            if (entityId) {
                                entityType = "PUSH";
                            }
                        }
                    }
                    if (entityType == "UNKNOWN") {
                        return;
                    }
                    ui.draggable.css({
                        top: "",
                        left: ""
                    });
                    switch (entityType) {
                      case "COMMENT":
                        doCommentDrop($this, ui.draggable, entityId);
                        break;

                      case "MAILING":
                        doMailingDrop($this, ui.draggable, entityId);
                        break;

                      case "PUSH":
                        doPushDrop($this, ui.draggable, entityId);
                        break;
                    }
                }
            });
        }
        function adjustSidebarHeight() {
            var height = $("#calendar-table").height();
            $(".calendar-sidebar").css({
                "max-height": height + "px"
            });
        }
        this.adjustSidebarHeight = adjustSidebarHeight;
        function saveMailingMoveDB(mailingId, date) {
            return $.ajax({
                type: "POST",
                url: urlCalendarMailingsMove,
                data: {
                    mailingId: mailingId,
                    date: date
                }
            });
        }
        function savePushMoveDB(pushId, date) {
            return $.ajax({
                type: "POST",
                url: urlCalendarPushesMove,
                data: {
                    pushId: pushId,
                    date: date
                }
            });
        }
        function updateComment(reminder) {
            var id = "comment-" + reminder.id;
            var $comment = $("#" + id);
            $("#deadline-" + id).val(reminder.isDeadline);
            $("#emm-user-type-" + id).val(reminder.isEmmUserType);
            $("#notify-admin-id-" + id).val(reminder.notifyAdminId);
            $("#recipients-" + id).val(reminder.recipients);
            var text = reminder.text.replace(/\n/g, "<br>");
            addCommentDragging($comment);
            $comment.find(".comment-text-content").html(text);
            $("#popup-" + id + " .comment-text-content").html(text);
            $("#plannedSendDate-" + id).val(reminder.getPlannedSendDateAsString());
        }
        function saveCommentDB(reminder) {
            $.ajax({
                type: "POST",
                url: urlCalendarCommentSave,
                data: {
                    commentId: reminder.id,
                    date: reminder.getDateAsString(),
                    comment: reminder.text,
                    deadline: reminder.isDeadline,
                    sendNow: reminder.isSendNow,
                    emmUserType: reminder.isEmmUserType,
                    notifyAdminId: reminder.notifyAdminId,
                    recipients: reminder.recipients,
                    notified: reminder.isNotified,
                    plannedSendDate: reminder.getPlannedSendDateAsString()
                },
                success: function(data) {
                    if (typeof data.commentId == "undefined") {
                        AGN.Lib.Page.render(data);
                    } else {
                        reminder.isSendNow = false;
                        if (reminder.id == 0) {
                            reminder.id = data.commentId;
                            addComment(reminder);
                            checkHideCommentIconsVisibility();
                        } else {
                            updateComment(reminder);
                        }
                    }
                }
            });
        }
        this.saveCommentDB = saveCommentDB;
        function removeCommentDB(commentId) {
            $.ajax({
                type: "POST",
                url: urlCalendarCommentRemove,
                data: {
                    commentId: AGN.Lib.ReminderService.getReminderIdFromTag(commentId)
                }
            });
        }
        this.removeCommentDB = removeCommentDB;
        function getMailings(startDate, endDate) {
            startDate = dateToServiceFormat(startDate);
            endDate = dateToServiceFormat(endDate);
            startProgress();
            $.ajax({
                type: "GET",
                url: urlCalendarMailingsList,
                data: {
                    startDate: startDate,
                    endDate: endDate
                }
            }).done(function(data) {
                $.each(data, function(index, d) {
                    setMailings(d);
                });
                adjustSidebarHeight();
            }).always(stopProgress);
        }
        function setMailings(d) {
            var $day = $("#day-" + d.sendDate);
            var $badge = $("#" + d.mailingId);
            if ($day.exists() && !$badge.exists()) {
                var statusClass;
                var mailingLink = getMailingLink(d);
                if (d.plannedInPast) {
                    statusClass = "calendar-mailing-status-planned-in-past";
                } else {
                    statusClass = "calendar-" + d.workstatus.replace(".", "-");
                }
                var musData = {
                    sent: d.sent,
                    planned: d.planned,
                    mailingId: d.mailingId,
                    statusClass: statusClass,
                    mailingLink: mailingLink,
                    workstatus: d.workstatus,
                    shortname: d.shortname,
                    sendTime: d.sendTime
                };
                $badge = AGN.Lib.Template.dom("calendar-mail-link", musData);
                $day.append($badge);
                musData.subject = d.subject;
                musData.mailsSent = d.mailsSent;
                musData.previewImage = getPreviewImage(d.preview_component, d.isOnlyPostType);
                musData.popupClass = d.preview_component ? "" : "calendar-mail-popup-preview-missing";
                musData.emptyWorkstatus = !d.workstatus.trim();
                musData.openers = d.openers;
                musData.clickers = d.clickers;
                musData.workstatusIn = d.workstatusIn;
                var $popup = AGN.Lib.Template.dom("calendar-mail-popup", musData);
                $("#calendar-popup-holder").append($popup);
                AGN.Lib.CalendarService.addMailingDragging($badge);
            }
        }
        function getMailingLink(d) {
            var link;
            if (d.sent && d.workstatus != "mailing.status.test" && isStatisticsViewPermitted) {
                link = urlMailingStatisticsView.replace(":mailingId:", d.mailingId);
            } else {
                link = urlMailingView.replace(":mailingId:", d.mailingId);
            }
            return link;
        }
        function getPreviewImage(previewComp, isPostType) {
            var link;
            if (isPostType) {
                link = AGN.url("/assets/core/images/facelift/post_thumbnail.jpg");
            } else if (previewComp) {
                link = AGN.url("/sc?compID=" + previewComp);
            } else {
                link = AGN.url("/assets/core/images/facelift/no_preview.svg");
            }
            return link;
        }
        function getCalendarDateForPushNotification(data) {
            switch (data.status) {
              case pushStatusSent:
                return data.sendDate;

              case pushStatusScheduled:
                return data.startDate;

              default:
                return dateToServiceFormat(dateFromArray(data.plannedFor));
            }
        }
        function getCalendarPushes(startDate, endDate) {
            startProgress();
            $.ajax({
                type: "GET",
                url: urlCalendarPushesList,
                data: {
                    startDate: dateToServiceFormat(startDate),
                    endDate: dateToServiceFormat(endDate)
                }
            }).done(function(data) {
                var createBadge = AGN.Lib.Template.prepare("calendar-planned-push-notification");
                $.each(data, function(index, d) {
                    var $badge = $(createBadge(d));
                    $("#day-" + getCalendarDateForPushNotification(d)).append($badge);
                    addMailingDragging($badge);
                });
                adjustSidebarHeight();
            }).always(stopProgress);
        }
        function getAutoOptimizations(startDate, endDate) {
            startProgress();
            $.ajax({
                type: "GET",
                url: urlCalendarAutoOptimization,
                data: {
                    startDate: dateToServiceFormat(startDate),
                    endDate: dateToServiceFormat(endDate)
                },
                success: function(data) {
                    var createBadge = AGN.Lib.Template.prepare("calendar-auto-optimization");
                    $.each(data, function(index, d) {
                        var $badge = $(createBadge({
                            optimizationId: d.campaignID,
                            shortname: d.shortname,
                            linkUrl: getOptimizationLinkUrl(d),
                            status: d.autoOptimizationStatus
                        }));
                        $("#day-" + d.sendDate).append($badge);
                    });
                    adjustSidebarHeight();
                }
            }).always(stopProgress);
        }
        function getOptimizationLinkUrl(data) {
            if (data.workflowId == 0) {
                return "optimization/" + data.id + "/view.action";
            } else {
                return "workflow/" + data.workflowId + "/view.action";
            }
        }
        function getComments(startDate, endDate) {
            $.ajax({
                type: "GET",
                url: urlCalendarCommentList,
                data: {
                    startDate: dateToServiceFormat(startDate),
                    endDate: dateToServiceFormat(endDate)
                },
                success: function(data) {
                    $.each(data, function(index, c) {
                        setComment(c);
                    });
                    AGN.Lib.CalendarService.checkHideCommentIconsVisibility();
                    setAllCommentsCheckState();
                    adjustSidebarHeight();
                }
            });
        }
        function setComment(c) {
            var reminder = _.cloneDeep(AGN.Lib.ReminderService.reminder);
            var recipientAdminId = c.recipients.adminId;
            reminder.id = c.commentId;
            reminder.setDate(c.date);
            reminder.text = c.comment;
            reminder.notifyAdminId = recipientAdminId;
            reminder.isEmmUserType = recipientAdminId != 0;
            reminder.currentAdminName = c.adminName;
            reminder.isDeadline = c.deadline;
            reminder.isNotified = c.notified;
            reminder.setPlannedSendDate(c.plannedSendDates);
            reminder.recipients = c.recipients.value;
            AGN.Lib.CalendarService.addComment(reminder);
        }
        function getUnsentMailings() {
            $.ajax({
                type: "GET",
                url: urlCalendarUnsent,
                success: function(data) {
                    $(".calendar-sidebar-content").html(data);
                    adjustSidebarHeight();
                    AGN.Lib.CoreInitializer.run([ "tooltip", "scrollable" ], $(".calendar-wrapper"));
                }
            });
        }
        function getPlannedMailings() {
            $.ajax({
                type: "GET",
                url: urlCalendarPlanned,
                success: function(data) {
                    $(".calendar-sidebar-content").html(data);
                    adjustSidebarHeight();
                    AGN.Lib.CoreInitializer.run([ "tooltip", "scrollable" ], $(".calendar-wrapper"));
                }
            });
        }
        function addMaxYearControl() {
            var monthYears = $("#month_list_year option");
            var weekYears = $("#weeks_list_year option");
            var lastYear = Number(monthYears[monthYears.length - 1].value);
            for (var i = 0; i < monthYears.length; i++) {
                var currentYear = Number(monthYears[i].value) + 1;
                monthYears[i].text = currentYear;
                monthYears[i].value = currentYear;
                weekYears[i].text = currentYear;
                weekYears[i].value = currentYear;
            }
            monthYears[monthYears.length] = new Option(lastYear, lastYear);
            weekYears[weekYears.length] = new Option(lastYear, lastYear);
        }
        function addMinYearControl() {
            var monthYears = $("#month_list_year option");
            var weekYears = $("#weeks_list_year option");
            var lastYear = Number(monthYears[monthYears.length - 1].value) - 1;
            monthYears[monthYears.length] = new Option(lastYear, lastYear);
            weekYears[weekYears.length] = new Option(lastYear, lastYear);
        }
        function showDate() {
            var selectedIndex;
            if (viewMode == "MONTH") {
                var month = $("#month_list option:selected").val();
                var year = $("#month_list_year option:selected").val();
                var resultDate = new Date(year, month, 1);
                strDate = AGN.Lib.DateFormat.format(resultDate, getDateFormat());
                selectedIndex = $("#month_list_year option:selected").index();
            }
            if (viewMode == "WEEK") {
                var weekNumber = $("#weeks_list option:selected").val();
                for (var j in weeksListArray) {
                    if (!weeksListArray.hasOwnProperty(j)) continue;
                    if (weeksListArray[j].number == weekNumber) {
                        strDate = AGN.Lib.DateFormat.format(weeksListArray[j].firstDay, getDateFormat());
                        break;
                    }
                }
                selectedIndex = $("#weeks_list_year option:selected").index();
            }
            if (selectedIndex == 0) {
                addMaxYearControl();
            }
            jumpToDate(strDate);
        }
        this.showDate = showDate;
        function jumpToDate(strDate) {
            var date = AGN.Lib.DateFormat.parseFormat(strDate, getDateFormat());
            curMonth = date.getMonth();
            curYear = date.getFullYear();
            curDay = date.getDate();
            removeCurrentCalendar();
            if (monthMode) {
                generateMonthCalendar(curMonth, curYear);
            } else {
                generateWeekCalendar(curMonth, curYear, curDay);
            }
        }
        this.jumpToDate = jumpToDate;
        function jumpToday() {
            var todayDate = AGN.Lib.DateFormat.format(new Date(), getDateFormat());
            jumpToDate(todayDate);
        }
        this.jumpToday = jumpToday;
        function synchronizeWeeksList(month, year, day) {
            var weekMilliseconds = 6048e5;
            var date = new Date(year, month, day);
            date.setDate(day - date.getDay() - 1 + firstDayOfWeek);
            var startWeekDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
            startWeekDate.setDate(startWeekDate.getDate() + 1);
            if (month == 0 && day == 1 && startWeekDate.getWeek(firstDayOfWeek) != 1) {
                startWeekDate.setTime(startWeekDate.getTime() + weekMilliseconds);
            }
            var weekNumber = startWeekDate.getWeek(firstDayOfWeek);
            if (weekNumber == 1) {
                var endWeekDate = new Date(startWeekDate.valueOf() + weekMilliseconds);
                if (startWeekDate.getFullYear() != endWeekDate.getFullYear()) {
                    year = endWeekDate.getFullYear();
                }
            }
            $("#weeks_list_year")[0].selectedIndex = $("#weeks_list_year option[value = " + year + "]")[0].index;
            createWeeksList($("#weeks_list_year")[0]);
            $("#weeks_list")[0].selectedIndex = $("#weeks_list option[value = " + weekNumber + "]")[0].index;
            $("#weeks_list_year").select2({
                minimumResultsForSearch: -1
            });
            $("#weeks_list").select2({
                minimumResultsForSearch: -1
            });
        }
        function synchronizeMonthsList(month, year) {
            $("#month_list_year")[0].selectedIndex = $("#month_list_year option[value = " + year + "]")[0].index;
            $("#month_list")[0].selectedIndex = $("#month_list option[value = " + month + "]")[0].index;
            $("#month_list").select2({
                minimumResultsForSearch: -1
            });
            $("#month_list_year").select2({
                minimumResultsForSearch: -1
            });
        }
        function createWeeksList(pThis) {
            weeksListArray = [];
            var currentWeek;
            var weekMilliseconds = 6048e5;
            var year = pThis.options[pThis.selectedIndex].value;
            var lastYearDay = new Date(year, 11, 31);
            var firstWeekDay = new Date(year, 0, 1);
            firstWeekDay.setDate(1 - firstWeekDay.getDay() - 1 + firstDayOfWeek);
            firstWeekDay.setDate(firstWeekDay.getDate() + 1);
            var lastWeekDay = new Date(firstWeekDay.getFullYear(), firstWeekDay.getMonth(), firstWeekDay.getDate());
            lastWeekDay.setTime(firstWeekDay.getTime() + weekMilliseconds - 864e5);
            if (firstWeekDay.getWeek(firstDayOfWeek) != 1) {
                firstWeekDay.setTime(firstWeekDay.getTime() + weekMilliseconds);
                lastWeekDay.setTime(lastWeekDay.getTime() + weekMilliseconds);
            }
            do {
                currentWeek = new Object();
                currentWeek.number = firstWeekDay.getWeek(firstDayOfWeek);
                currentWeek.firstDay = new Date(firstWeekDay.getFullYear(), firstWeekDay.getMonth(), firstWeekDay.getDate());
                currentWeek.lastDay = new Date(lastWeekDay.getFullYear(), lastWeekDay.getMonth(), lastWeekDay.getDate());
                weeksListArray.push(currentWeek);
                firstWeekDay.setTime(firstWeekDay.getTime() + weekMilliseconds);
                lastWeekDay.setTime(lastWeekDay.getTime() + weekMilliseconds);
            } while (firstWeekDay.getWeek(firstDayOfWeek) != 1 && firstWeekDay.getFullYear() == year);
            $("#weeks_list option").remove();
            for (var j in weeksListArray) {
                if (!weeksListArray.hasOwnProperty(j)) continue;
                var optElem = document.createElement("option");
                var firstDay = AGN.Lib.DateFormat.format(weeksListArray[j].firstDay, localeDatePattern);
                var lastDay = AGN.Lib.DateFormat.format(weeksListArray[j].lastDay, localeDatePattern);
                optElem.value = weeksListArray[j].number;
                optElem.innerHTML = weeksListArray[j].number + " : " + firstDay + " - " + lastDay;
                $("#weeks_list").append(optElem);
            }
        }
        this.createWeeksList = createWeeksList;
        function pad(num, size) {
            var s = num + "";
            while (s.length < size) s = "0" + s;
            return s;
        }
        function dateToServiceFormat(date) {
            var dd = pad(date.getDate(), 2);
            var mm = pad(date.getMonth() + 1, 2);
            var yyyy = date.getFullYear();
            return dd + "-" + mm + "-" + yyyy;
        }
        function dateFromArray(d) {
            if (d) {
                var yyyy = d[0];
                var mm = d[1] - 1;
                var dd = d[2];
                return new Date(yyyy, mm, dd);
            }
            return null;
        }
        function dateFromServiceFormat(dateString, timeString) {
            var res = dateString.match(/^(\d\d)-(\d\d)-(\d{4})$/);
            if (res) {
                var dd = res[1];
                var mm = res[2] - 1;
                var yyyy = res[3];
                if (timeString) {
                    res = timeString.match(/^(\d\d):(\d\d)$/);
                    if (res) {
                        var hh = res[1];
                        var mi = res[2];
                        return new Date(yyyy, mm, dd, hh, mi);
                    }
                }
                return new Date(yyyy, mm, dd);
            }
            return null;
        }
        function setAllCommentsCheckState() {
            if ($(".js-calendar-toggle-all-comments").prop("checked")) {
                $(".calendar-table .calendar-comment").show();
            }
        }
        this.setAllCommentsCheckState = setAllCommentsCheckState;
        function byteCount(s) {
            var escapedStr = encodeURI(s);
            if (escapedStr.indexOf("%") != -1) {
                var count = escapedStr.split("%").length - 1;
                if (count == 0) count++;
                var tmp = escapedStr.length - count * 3;
                count = count + tmp;
            } else {
                count = escapedStr.length;
            }
            return count;
        }
    };
    AGN.Lib.CalendarService = new CalendarService();
    var reminderService = {
        showDiv: function(id) {
            $("div#calendar-dialog-modal div#" + id).css("display", "block");
        },
        hideDiv: function(id) {
            $("div#calendar-dialog-modal div#" + id).css("display", "none");
        },
        updateVisibility: function() {
            this.onScheduleChanged();
            this.onDeadlineChanged();
        },
        onDeadlineChanged: function() {
            if ($("#isDeadline:checked").val()) {
                $("#remindDate").prop("disabled", false);
                $("#remindTime").prop("disabled", false);
                $(".js-open-datepicker").prop("disabled", false);
                $(".js-open-timepicker").prop("disabled", false);
            } else {
                $("#remindDate").prop("disabled", true);
                $("#remindTime").prop("disabled", true);
                $(".js-open-datepicker").prop("disabled", true);
                $(".js-open-timepicker").prop("disabled", true);
            }
            return false;
        },
        onUserTypeChanged: function(userType) {
            if (userType == this.reminder.recipientEmm) {
                $("#emmUsers").show();
                $("#customRecipients").hide();
            } else {
                $("#customRecipients").show();
                $("#emmUsers").hide();
            }
        },
        onScheduleChanged: function() {
            if ($("#scheduleReminder:checked").val()) {
                $("#admin-for-notify").prop("disabled", false);
                this.showDiv("reminderDetails");
            } else {
                $("#admin-for-notify").prop("disabled", true);
                this.hideDiv("reminderDetails");
            }
            return false;
        },
        reminder: {
            isDeadline: false,
            isSendNow: false,
            isEmmUserType: true,
            recipientEmm: 1,
            recipientCustom: 2,
            defaultDate: {
                date: "",
                hours: 8,
                minutes: 0
            },
            plannedSendDate: {
                date: "",
                hours: 8,
                minutes: 0
            },
            getDateAsString: function() {
                return $.datepicker.formatDate("dd-mm-yy", this.defaultDate.date);
            },
            setDate: function(date) {
                this.defaultDate.date = $.datepicker.parseDate("dd-mm-yy", date);
                this.plannedSendDate.date = $.datepicker.parseDate("dd-mm-yy", date);
                this.plannedSendDate.hours = this.defaultDate.hours;
                this.plannedSendDate.minutes = this.defaultDate.minutes;
            },
            getPlannedSendDateAsString: function() {
                return $.datepicker.formatDate("dd-mm-yy", this.plannedSendDate.date) + (this.plannedSendDate.hours < 10 ? " 0" : " ") + this.plannedSendDate.hours.toString() + (this.plannedSendDate.minutes < 10 ? ":0" : ":") + this.plannedSendDate.minutes.toString();
            },
            setPlannedSendDate: function(dateTime) {
                var dt = dateTime.split(" ");
                this.plannedSendDate.date = $.datepicker.parseDate("dd-mm-yy", dt[0]);
                var t = dt[1].split(":");
                this.plannedSendDate.hours = parseInt(t[0]);
                this.plannedSendDate.minutes = parseInt(t[1]);
            },
            getScheduleReminder: function() {
                return this.isDeadline || this.isSendNow;
            },
            getRemindCalendarDate: function() {
                if (this.defaultDate.date.toString() == this.plannedSendDate.date.toString() && this.defaultDate.hours == this.plannedSendDate.hours && this.defaultDate.minutes == this.plannedSendDate.minutes) {
                    return true;
                } else {
                    return false;
                }
            },
            onSave: function() {
                reminderService.saveReminder(reminderService.reminder);
            }
        },
        getNewReminder: function(date, conf) {
            this.reminder.id = 0;
            this.reminder.setDate(date);
            this.reminder.text = "";
            this.reminder.isEmmUserType = true;
            this.reminder.notifyAdminId = conf.adminId;
            this.reminder.recipients = "";
            this.reminder.currentAdminName = conf.adminName;
            this.reminder.isDeadline = false;
            this.reminder.isNotified = false;
            this.reminder.title = t("calendar.common.new_comment");
            this.reminder.recipientEmm = conf.recipientEmm;
            this.reminder.recipientCustom = conf.recipientCustom;
            return this.reminder;
        },
        getReminder: function(commentId, adminName) {
            var comment = $("#" + commentId + " .comment-text-content").html() + "";
            this.reminder.id = this.getReminderIdFromTag(commentId);
            this.reminder.setDate(this.getDateFromTag($("#" + commentId).parent().attr("id")));
            this.reminder.text = comment.replace(/<br>/gi, "\n");
            this.reminder.isEmmUserType = $("#emm-user-type-" + commentId).val() == "true";
            this.reminder.notifyAdminId = $("#notify-admin-id-" + commentId).val();
            this.reminder.recipients = $("#recipients-" + commentId).val();
            this.reminder.currentAdminName = adminName;
            this.reminder.isDeadline = $("#deadline-" + commentId).val() == "true";
            this.reminder.isNotified = $("#notified-" + commentId).val() == "true";
            this.reminder.setPlannedSendDate($("#plannedSendDate-" + commentId).val());
            this.reminder.title = t("calendar.common.edit_comment");
            return this.reminder;
        },
        fillCommentDialog: function(reminder) {
            var $modal = $("#calendar-dialog-modal");
            $modal.find(".modal-title").html(reminder.title);
            $modal.find("#comment-text").val(reminder.text);
            $modal.find('#reminderDetails input[name="userType"][value=' + (reminder.isEmmUserType ? reminder.recipientEmm : reminder.recipientCustom) + "]").prop("checked", true).trigger("change");
            $modal.find("#admin-for-notify").val(reminder.notifyAdminId);
            AGN.Lib.Select.get($modal.find("#admin-for-notify")).selectValueOrSelectFirst(reminder.notifyAdminId);
            $modal.find("#recipients-text").val(reminder.recipients);
            $modal.find("#isDeadline").prop("checked", reminder.isDeadline);
            $modal.find("#isSendNow").prop("checked", reminder.isSendNow);
            $modal.find("#scheduleReminder").prop("checked", reminder.getScheduleReminder());
            $modal.find("#remindDate").pickadate("picker").set("select", reminder.plannedSendDate.date);
            $modal.find("#remindTime").val(reminder.plannedSendDate.hours + ":" + reminder.plannedSendDate.minutes);
        },
        saveReminder: function(reminder) {
            var commentText = $("#comment-text").val();
            if (AGN.Lib.CalendarService.validateComment(commentText)) {
                var isEmmUserType = $("#isEmmUserType").prop("checked");
                var recipients = AGN.Lib.CalendarService.parseRecipients($("#recipients-text").val());
                if (isEmmUserType || AGN.Lib.CalendarService.validateEmails(recipients)) {
                    $("#calendar-dialog-modal").modal("hide");
                    reminder.text = commentText;
                    reminder.isEmmUserType = isEmmUserType;
                    if (isEmmUserType) {
                        reminder.notifyAdminId = $("#admin-for-notify").val();
                        reminder.recipients = "";
                    } else {
                        reminder.notifyAdminId = 0;
                        reminder.recipients = recipients.join(",");
                    }
                    reminder.isSendNow = $("#isSendNow").prop("checked");
                    reminder.isDeadline = $("#isDeadline").prop("checked");
                    if ($("#isDeadline").prop("checked") && $("#scheduleReminder").prop("checked")) {
                        var $datepicker = $("#remindDate").pickadate("picker"), $timepicker = $("#remindTime");
                        reminder.plannedSendDate.date = AGN.Lib.DateFormat.parseFormat($datepicker.get("select", "dd-mm-yyyy"), "dd-MM-yyyy");
                        reminder.plannedSendDate.hours = $timepicker.val().substring(0, 2);
                        reminder.plannedSendDate.minutes = $timepicker.val().substring(3, 5);
                    } else {
                        reminder.plannedSendDate.date = reminder.defaultDate.date;
                        reminder.plannedSendDate.hours = reminder.defaultDate.hours;
                        reminder.plannedSendDate.minutes = reminder.defaultDate.minutes;
                    }
                    AGN.Lib.CalendarService.saveCommentDB(reminder);
                }
            }
        },
        getDateFromTag: function(tag) {
            return tag.substr(tag.indexOf("-") + 1);
        },
        getReminderIdFromTag: function(tag) {
            return tag.substr(tag.indexOf("-") + 1);
        }
    };
    AGN.Lib.ReminderService = reminderService;
})();

(function() {
    function extractDateTimeToResultField(dateSelector, timeSelector, resultFieldSelector, datePattern) {
        var dateValue = $(dateSelector).pickadate("picker").get("select", datePattern);
        var timeValue = $(timeSelector).val();
        var dateTime = "";
        if (dateValue && timeValue) {
            dateTime = dateValue + " " + timeValue;
        }
        $(resultFieldSelector).val(dateTime);
    }
    function initDateTimeSelectorsGroup(dateSelector, timeSelector, resultFieldSelector, datePattern) {
        $(dateSelector).pickadate("picker").on({
            set: function() {
                extractDateTimeToResultField(dateSelector, timeSelector, resultFieldSelector, datePattern);
            }
        });
        $(timeSelector).on("change", function() {
            extractDateTimeToResultField(dateSelector, timeSelector, resultFieldSelector, datePattern);
        });
    }
    AGN.Lib.DomInitializer.new("campaign-autooptimization-view", function() {
        $("form#optimizationForm").submit(false);
        initDateTimeSelectorsGroup("#testMailingsSendDate", "#testMailingsSendTime", "input[name='testMailingsSendDateAsString']", this.config.datePattern);
        initDateTimeSelectorsGroup("#resultSendDate", "#resultSendTime", "input[name='resultSendDateAsString']", this.config.datePattern);
    });
})();

AGN.Lib.CoreInitializer.new("colorpicker", function($scope) {
    if (!$scope) {
        $scope = $(document);
    }
    $scope.find(".js-colorpicker").each(function() {
        $(this).colorpicker({
            format: "hex",
            container: true
        });
    });
});

(function() {
    var recipientStatsData = {
        URL: undefined,
        reactorChartData: {
            bindto: "#reactor-type-chart",
            data: {
                columns: [],
                type: "donut",
                order: null
            },
            color: {
                pattern: [ "#008F00", "#92D050", "#CCCDCD", "#F43536" ]
            },
            legend: {
                position: "right"
            }
        },
        rebuyChartData: {
            bindto: "#rebuy-rate-chart",
            data: {
                columns: [],
                type: "gauge"
            },
            color: {
                pattern: [ "#0071B9" ]
            }
        },
        revenueChartData: {
            bindto: "#revenue-chart",
            data: {
                columns: [],
                type: "bar",
                labels: {
                    show: true,
                    format: function(v, id, i, j) {
                        return v;
                    }
                },
                color: function(color, d) {
                    return color;
                }
            },
            tooltip: {
                show: false
            },
            axis: {
                rotated: true,
                x: {
                    show: false
                },
                y: {
                    show: false,
                    min: 0,
                    max: 150
                }
            },
            legend: {
                show: false
            },
            bar: {
                width: {
                    ratio: .7
                }
            }
        },
        progressChartData: {
            bindto: "#progress-of-used-devices-chart",
            onrendered: function() {
                d3.selectAll("#progress-of-used-devices-chart").selectAll(".c3-axis.c3-axis-x").selectAll(".tick text").style("text-anchor", "start");
            },
            data: {
                columns: [],
                groups: [ [ "windows", "mac", "android", "ios", "other" ] ],
                types: {
                    reactions: "spline"
                },
                axes: {
                    reactions: "y2"
                },
                names: {},
                type: "bar",
                x: "date",
                xFormat: "%m/%d/%Y",
                order: null
            },
            axis: {
                x: {
                    type: "timeseries",
                    tick: {
                        culling: true,
                        format: "%m/%d/%Y"
                    }
                },
                y: {
                    padding: {
                        top: 10
                    },
                    tick: {
                        format: function(value) {
                            return value + " %";
                        }
                    }
                },
                y2: {
                    show: true,
                    min: 0
                }
            },
            bar: {
                width: {
                    ratio: .5
                }
            },
            tooltip: {
                format: {
                    value: function(value, ratio, id) {
                        if (id === "reactions") {
                            return value;
                        }
                        return value + " %";
                    }
                }
            },
            color: {
                pattern: [ "#0071B9", "#4C9BCE", "#99C6E3", "#CCE3F1", "#CCCDCD", "#555555" ]
            }
        },
        devicesChartData: {
            bindto: "#devices-reacted-on-chart",
            data: {
                columns: [],
                type: "donut",
                order: null,
                names: {}
            },
            legend: {
                position: "right"
            },
            color: {
                pattern: [ "#0071B9", "#4C9BCE", "#99C6E3", "#CCE3F1", "#CCCDCD" ]
            }
        }
    };
    var chartSizesForWideScreen = {
        reactorChartData: {
            size: {
                width: 400,
                height: 350
            }
        },
        rebuyChartData: {
            size: {
                width: 400,
                height: 250
            }
        },
        revenueChartData: {
            size: {
                width: 350,
                height: 275
            }
        },
        progressChartData: {
            size: {
                width: 860,
                height: 350
            }
        },
        devicesChartData: {
            size: {
                width: 400,
                height: 350
            }
        }
    };
    var chartSizes = {
        reactorChartData: {
            size: {
                width: 350,
                height: 250
            }
        },
        rebuyChartData: {
            size: {
                width: 250,
                height: 200
            }
        },
        revenueChartData: {
            size: {
                width: 300,
                height: 250
            }
        },
        progressChartData: {
            size: {
                width: 550,
                height: 250
            }
        },
        devicesChartData: {
            size: {
                width: 350,
                height: 250
            }
        }
    };
    var chartsToRender = [];
    var resizeRenderTimer = null;
    var isLargePreviousScreen = false;
    AGN.Lib.RecipientStatsData = recipientStatsData;
    AGN.Lib.DomInitializer.new("company-insights", function() {
        loadStoredStatistics();
        loadDynamicStatistic();
        $("input[type=radio][name=progressOfUsedPeriod]").change(function() {
            if (this.value == "dates") {
                $("#progressOfUsedDates").removeClass("hidden");
            } else {
                $("#progressOfUsedDates").addClass("hidden");
            }
        });
        $("#refreshProgressOfUsedDevices").on("click", function() {
            loadDynamicStatistic();
        });
        isLargePreviousScreen = isLargeScreen();
        $(window).resize(function() {
            if (resizeRenderTimer != null) clearTimeout(resizeRenderTimer);
            resizeRenderTimer = setTimeout(function() {
                var largeScreen = isLargeScreen();
                if (isLargePreviousScreen != largeScreen) {
                    isLargePreviousScreen = largeScreen;
                    renderCharts();
                }
            }, 200);
        });
    });
    function loadStoredStatistics() {
        $.ajax({
            type: "GET",
            url: AGN.url("/recipient/chart/ajaxStatistic.action"),
            success: function(data) {
                if (data) {
                    updateReactorChart(data["reactorType"], data["notAvailable"]);
                    updateRebuyChart(data["rebuyTitle"], data["rebuyRate"], data["notAvailable"]);
                    updateRevenueChart(data["revenue"], data["notAvailable"]);
                    loadImpressionStatistics(data);
                    AGN.Lib.CoreInitializer.run("equalizer");
                }
            }
        });
    }
    function loadDynamicStatistic() {
        var data = {};
        var period = $("input[name=progressOfUsedPeriod]:checked").val();
        if (period == "month") {
            data["byMonth"] = true;
        } else if (period == "dates") {
            data["from"] = $("#progressOfUsedFrom").val();
            data["till"] = $("#progressOfUsedTill").val();
        }
        $.ajax({
            type: "GET",
            url: AGN.url("/recipient/chart/progressOfUsedDevices.action"),
            data: data,
            success: function(data) {
                updateUsedDevicesCharts(data);
                AGN.Lib.CoreInitializer.run("equalizer");
            }
        });
    }
    function renderChart(chartName) {
        var chartData = recipientStatsData[chartName + "Data"];
        if (chartData == undefined) {
            return;
        }
        var settings = isLargeScreen() ? chartSizesForWideScreen : chartSizes;
        var chartSize = settings[chartName + "Data"];
        $.extend(true, chartData, chartSize);
        $("#" + chartName).removeClass("hidden");
        c3.generate(chartData);
        if (chartsToRender.indexOf(chartName) == -1) {
            chartsToRender.push(chartName);
        }
    }
    function renderCharts() {
        chartsToRender.forEach(function(chartName) {
            renderChart(chartName);
        });
    }
    function updateReactorChart(reactorData, notAvailableMessage) {
        if (reactorData === undefined) {
            return;
        }
        var values = [];
        var hasAnyValue = false;
        for (var key in reactorData) {
            if (reactorData.hasOwnProperty(key)) {
                values.push([ key, reactorData[key] ]);
                if (reactorData[key] > 0) {
                    hasAnyValue = true;
                }
            }
        }
        if (!hasAnyValue) {
            values = [ [ notAvailableMessage, 100 ] ];
            recipientStatsData.reactorChartData.color.pattern = [ "#CCCDCD" ];
        } else {
            if (values.length == 4) {
                recipientStatsData.reactorChartData.color.pattern = [ "#008F00", "#92D050", "#CCCDCD", "#F43536" ];
            } else {
                recipientStatsData.reactorChartData.color.pattern = [ "#92D050", "#CCCDCD", "#F43536" ];
            }
        }
        recipientStatsData.reactorChartData.data.columns = values;
        renderChart("reactorChart");
    }
    function updateRebuyChart(title, rate, notAvailableMessage) {
        if (rate === undefined) {
            return;
        }
        if (rate > 0) {
            recipientStatsData.rebuyChartData.data.columns = [ [ title, toPercents(rate) ] ];
        } else {
            recipientStatsData.rebuyChartData.gauge = {};
            recipientStatsData.rebuyChartData.gauge.label = {};
            recipientStatsData.rebuyChartData.gauge.label.format = function(value, ratio) {
                return notAvailableMessage;
            };
            recipientStatsData.rebuyChartData.gauge.label.show = false;
            recipientStatsData.rebuyChartData.data.columns = [ [ notAvailableMessage, 0 ] ];
        }
        renderChart("rebuyChart");
    }
    function updateRevenueChart(revenueData, notAvailableMessage) {
        if (revenueData === undefined) {
            return;
        }
        var colors = [ "#0071B9", "#4C9BCE", "#99C6E3", "#CCCDCD" ];
        var titles = [];
        var columns = [ "" ];
        var values = [];
        var percents = [];
        var valuesSum = 0;
        var percentSum = 0;
        var isDataAvailable = false;
        for (var key in revenueData) {
            if (revenueData.hasOwnProperty(key)) {
                var value = revenueData[key];
                titles.push(key);
                if (value > 0) {
                    isDataAvailable = true;
                    values.push(value);
                    valuesSum += value;
                } else {
                    values.push(0);
                }
            }
        }
        if (isDataAvailable) {
            var maximumLengthInPercents = isLargeScreen() ? 70 : 60;
            var barIsTooLong = false;
            for (var i = 0; i < values.length; i++) {
                percents[i] = Math.round(values[i] / valuesSum * 100);
                percentSum += percents[i];
                if (percents[i] >= 70) {
                    barIsTooLong = true;
                }
            }
            if (percentSum != 100) {
                percents[percents.length - 1] += 100 - percentSum;
            }
            for (i = 0; i < percents.length; i++) {
                columns.push(25 + (barIsTooLong ? percents[i] * maximumLengthInPercents / 100 : percents[i]));
            }
            recipientStatsData.revenueChartData.data.labels.format = function(value, id, i, j) {
                return percents[i] + "% " + titles[i];
            };
        } else {
            for (i = 0; i < titles.length; i++) {
                columns.push(50);
                percents[i] = 25;
            }
            recipientStatsData.revenueChartData.data.labels.format = function(value, id, i, j) {
                return notAvailableMessage;
            };
        }
        recipientStatsData.revenueChartData.data.columns = [ columns ];
        recipientStatsData.revenueChartData.data.color = function(color, d) {
            if (d.value != undefined) {
                return colors[d.index];
            }
            return color;
        };
        renderChart("revenueChart");
    }
    function updateUsedDevicesCharts(usedDevicesData) {
        if (usedDevicesData === undefined || usedDevicesData["usedDevicesByPeriods"] === undefined || usedDevicesData["usedDevices"] === undefined) {
            return;
        }
        var columnNames = {
            windows: usedDevicesData["windowsTitle"],
            mac: usedDevicesData["macTitle"],
            android: usedDevicesData["androidTitle"],
            ios: usedDevicesData["iosTitle"],
            other: usedDevicesData["otherTitle"],
            reactions: usedDevicesData["numberOfReactions"]
        };
        var donutUsedDevices = usedDevicesData["usedDevices"];
        var donutColumns = [];
        var categoriesSortedByCount = [];
        categoriesSortedByCount.push({
            name: "windows",
            count: donutUsedDevices["windows"]
        });
        categoriesSortedByCount.push({
            name: "mac",
            count: donutUsedDevices["mac"]
        });
        categoriesSortedByCount.push({
            name: "android",
            count: donutUsedDevices["android"]
        });
        categoriesSortedByCount.push({
            name: "ios",
            count: donutUsedDevices["ios"]
        });
        categoriesSortedByCount.sort(function(a, b) {
            return b.count - a.count;
        });
        for (var j = 0; j < categoriesSortedByCount.length; j++) {
            donutColumns.push([ columnNames[categoriesSortedByCount[j].name], categoriesSortedByCount[j].count ]);
        }
        donutColumns.push([ usedDevicesData["otherTitle"], donutUsedDevices["other"] ]);
        recipientStatsData.devicesChartData.data.columns = donutColumns;
        recipientStatsData.devicesChartData.data.names = columnNames;
        renderChart("devicesChart");
        var columns = [];
        var translationMap = [];
        for (var t = 0; t < categoriesSortedByCount.length; t++) {
            translationMap[categoriesSortedByCount[t].name] = t;
            columns.push([ categoriesSortedByCount[t].name ]);
        }
        columns.push([ "other" ], [ "reactions" ], [ "date" ]);
        for (var i = 0; i < usedDevicesData["usedDevicesByPeriods"].length; i++) {
            var usedDevices = usedDevicesData["usedDevicesByPeriods"][i];
            var windows = usedDevices["windows"];
            var mac = usedDevices["mac"];
            var android = usedDevices["android"];
            var ios = usedDevices["ios"];
            var other = usedDevices["other"];
            var reactions = windows + mac + android + ios + other;
            columns[translationMap["windows"]].push(toPercents(windows / reactions));
            columns[translationMap["mac"]].push(toPercents(mac / reactions));
            columns[translationMap["android"]].push(toPercents(android / reactions));
            columns[translationMap["ios"]].push(toPercents(ios / reactions));
            columns[4].push(toPercents(other / reactions));
            columns[5].push(reactions);
            columns[6].push(usedDevices["date"]);
        }
        recipientStatsData.progressChartData.data.columns = columns;
        recipientStatsData.progressChartData.data.names = columnNames;
        recipientStatsData.progressChartData.data.xFormat = usedDevicesData["dateFormat"];
        recipientStatsData.progressChartData.axis.x.min = usedDevicesData["min"];
        recipientStatsData.progressChartData.axis.x.max = usedDevicesData["max"];
        recipientStatsData.progressChartData.axis.x.tick.format = usedDevicesData["dateFormat"];
        renderChart("progressChart");
    }
    function toPercents(num) {
        return Math.round(1e3 * num) / 10;
    }
    function isLargeScreen() {
        return $(window).width() >= 1600;
    }
    function loadImpressionStatistics(data) {
        loadFavDaysStatistic(data["favoriteOpeningDays"]);
        loadFavTimesStatistic(data["favoriteOpeningHours"]);
        loadCtr(data["ctr"]);
        loadConversion(data["conversion"]);
        loadPI(data["pageImpressions"]);
        loadPIPerVisit(data["pageImpressionsPerVisit"]);
        loadPIPerBuy(data["pageImpressionsPerBuy"]);
    }
    function loadCtr(ctr) {
        $("#ctr-val").text(ctr.toString().replace(".", ","));
    }
    function loadConversion(conversion) {
        if (conversion != 0) {
            $("#conversion-val").text(conversion.toString().replace(".", ","));
        } else {
            $("#conversion-val").text("---");
            $("#conversion-val").parent().find(".l-stat-sign").text("");
        }
    }
    function loadPI(pi) {
        if (pi != 0) {
            $("#pi-val").text(pi.toString().replace(",", "."));
        } else {
            $("#pi-val").text("---");
            $("#pi-val").parent().find(".l-stat-sign").text("");
        }
    }
    function loadPIPerVisit(piPerVisit) {
        if (piPerVisit != 0) {
            $("#pi-visit-val").text(piPerVisit.toString().replace(",", "."));
        } else {
            $("#pi-visit-val").text("---");
            $("#pi-visit-val").parent().find(".l-stat-sign").text("");
        }
    }
    function loadPIPerBuy(piPerBuy) {
        if (piPerBuy != 0) {
            $("#pi-buy-val").text(piPerBuy.toString().replace(",", "."));
        } else {
            $("#pi-buy-val").text("---");
            $("#pi-buy-val").parent().find(".l-stat-sign").text("");
        }
    }
    function loadFavDaysStatistic(favDaysData) {
        var divForFavDay = $("#favOpeningDays").find(".stat-fav-day");
        setDataToTheDiv(favDaysData, divForFavDay);
    }
    function loadFavTimesStatistic(favHoursData) {
        var divForFavTimes = $("#favOpeningHours").find(".stat-fav-time");
        setDataToTheDiv(favHoursData, divForFavTimes);
    }
    function setDataToTheDiv(statData, divForFavoriteStatistic) {
        var hr = divForFavoriteStatistic.closest(".l-stat-content").find("hr");
        var index = 0;
        var mapSize = getSize(statData);
        $.each(statData, function(key, value) {
            divForFavoriteStatistic.find(".l-stat-name").text(key);
            divForFavoriteStatistic.find(".l-stat-val").text(value);
            index++;
            if (index < mapSize) {
                var nextDivForFavDay = divForFavoriteStatistic.clone();
                nextDivForFavDay.insertAfter(hr);
                divForFavoriteStatistic = nextDivForFavDay;
                if (index < mapSize - 1) {
                    hr = hr.clone();
                    hr.insertAfter(divForFavoriteStatistic);
                }
            }
        });
    }
    function getSize(map) {
        var size = 0;
        $.each(map, function(key, value) {
            size++;
        });
        return size;
    }
})();

AGN.Lib.DomInitializer.new("connection-speed-test", function() {
    var SLOW_CONNECTION_THRESHOLD_KBPS = this.config.SLOW_CONNECTION_THRESHOLD_KBPS;
    var SPEED_TEST_RESOURCE_SIZE = this.config.SPEED_TEST_RESOURCE_SIZE;
    var ADDITIONAL_TRANSFER_DATA_SIZE = 300;
    var TEST_INTERVAL = 6e4;
    var anotherAjaxesStartedDuringTest = false;
    var anotherAjaxesRunning = false;
    var testRunning = false;
    var startTime;
    function isSpeedTestAjax(url) {
        return url.indexOf("/connectionSpeedTest") >= 0 || url.indexOf("/connectionSpeed") >= 0;
    }
    $(document).ajaxSend(function(e, jqxhr, settings) {
        if (!isSpeedTestAjax(settings.url)) {
            if (testRunning) {
                anotherAjaxesStartedDuringTest = true;
            }
            anotherAjaxesRunning = true;
            if (settings.url.indexOf("/lock.action") < 0) {
                runSpeedTestThrottled();
            }
        } else {
            testRunning = true;
            anotherAjaxesStartedDuringTest = false;
            startTime = Date.now();
        }
    });
    $(document).ajaxStop(function() {
        anotherAjaxesRunning = false;
    });
    function allImagesLoaded() {
        var result = true;
        $("img").each(function(index, element) {
            if (!element.complete) {
                result = false;
            }
        });
        return result;
    }
    function waitAnotherAjaxesAndRunTest() {
        if (anotherAjaxesRunning) {
            setTimeout(waitAnotherAjaxesAndRunTest, 2e3);
        } else {
            if (allImagesLoaded()) {
                runSpeedTest();
            }
        }
    }
    var runSpeedTestThrottled = _.throttle(function() {
        waitAnotherAjaxesAndRunTest();
    }, TEST_INTERVAL);
    function runSpeedTest() {
        AGN.Lib.Loader.prevent();
        $.ajax({
            type: "GET",
            url: AGN.url("/connectionSpeed/test.action") + "?cacheKiller=" + Date.now(),
            timeout: 1e4
        }).done(function(response) {
            if (!anotherAjaxesStartedDuringTest) {
                checkSpeed();
            }
            testRunning = false;
        }).fail(function(jqXHR, textStatus) {
            if (textStatus === "timeout") {
                changeInternetIndicatorState(0);
                testRunning = false;
            }
        });
    }
    function checkSpeed() {
        var duration = (Date.now() - startTime) / 1e3;
        var bps = (SPEED_TEST_RESOURCE_SIZE + ADDITIONAL_TRANSFER_DATA_SIZE) * 8 / duration;
        var kbits = bitsToKilobits(bps);
        changeInternetIndicatorState(kbits);
    }
    function changeInternetIndicatorState(kbits) {
        var qualityGood = kbits > SLOW_CONNECTION_THRESHOLD_KBPS;
        var $internetIndicator = $("#internet-indicator");
        $internetIndicator.data("tooltip", qualityGood ? t("defaults.ok") : kbits + " Kbit/s");
        AGN.Lib.CoreInitializer.run("tooltip", $internetIndicator.parent());
        $internetIndicator.find("i").css("color", qualityGood ? "#109e4d" : "#ffa300");
    }
    function bitsToKilobits(bps) {
        return (bps / 1e3).toFixed(2);
    }
    window.addEventListener("offline", function() {
        changeInternetIndicatorState(0);
    });
    return false;
});

AGN.Lib.CoreInitializer.new("csrf", function($scope) {
    if (!$scope) {
        $scope = $(document);
    }
    $scope.find('meta[name="_csrf_header"]').each(function() {
        window.csrfHeaderName = $(this).attr("content");
        window.csrfCookieName = window.csrfHeaderName;
    });
    $scope.find('meta[name="_csrf_parameter"]').each(function() {
        window.csrfParameterName = $(this).attr("content");
    });
});

(function() {
    AGN.Lib.CoreInitializer.new("dark-theme", function() {
        if ($("body").hasClass("dark-theme")) {
            $("iframe").each(function() {
                var $iframe = $(this);
                $iframe.on("load.iframe", function() {
                    $iframe.contents().find("body").addClass("dark-theme");
                });
            });
        }
    });
})();

(function() {
    var DashboardStatisticsService;
    DashboardStatisticsService = {
        data: {
            chartsColors: [ "#0071b9", "#009999", "#92d050", "#41641a", "#ffc000" ],
            statChartData: {
                columnTitles: [],
                c3data: {
                    bindto: ".js-stat-chart",
                    data: {
                        columns: [],
                        type: "bar",
                        labels: true
                    },
                    axis: {
                        x: {
                            tick: {
                                centered: true,
                                fit: true,
                                format: function(columnIndex) {
                                    return DashboardStatisticsService.data.statChartData.columnTitles[columnIndex];
                                }
                            }
                        }
                    },
                    legend: {
                        show: false
                    },
                    tooltip: {
                        format: {
                            title: function() {
                                return null;
                            },
                            name: function(name, ratio, id, index) {
                                return DashboardStatisticsService.data.statChartData.columnTitles[index];
                            },
                            value: function(value, ratio, id, index) {
                                return value;
                            }
                        }
                    },
                    padding: {
                        right: 25
                    }
                },
                build: function(titles, values) {
                    this.columnTitles = titles;
                    var row = values.slice(0);
                    row.unshift("values");
                    this.c3data.data.columns = [ row ];
                    return this.c3data;
                }
            },
            clickChartData: {
                c3data: {
                    bindto: ".js-click-chart",
                    data: {
                        rows: [],
                        type: "donut"
                    },
                    size: {
                        height: 150
                    },
                    donut: {
                        title: "",
                        label: {
                            show: false
                        },
                        width: 15
                    },
                    legend: {
                        position: "right"
                    },
                    tooltip: {
                        show: false
                    }
                },
                build: function(title, titles, values) {
                    this.c3data.donut.title = title;
                    this.c3data.data.rows = [ titles, values ];
                    var colors = {};
                    for (var i = 0; i < titles.length; i++) {
                        colors[titles[i]] = DashboardStatisticsService.data.chartsColors[i];
                    }
                    this.c3data.data.colors = colors;
                    return this.c3data;
                }
            },
            viewChartData: {
                c3data: {
                    bindto: ".js-view-chart",
                    data: {
                        rows: [],
                        type: "donut"
                    },
                    size: {
                        height: 150
                    },
                    donut: {
                        title: "",
                        label: {
                            show: false
                        },
                        width: 15
                    },
                    legend: {
                        position: "right"
                    },
                    tooltip: {
                        show: false
                    }
                },
                build: function(title, titles, values) {
                    this.c3data.donut.title = title;
                    this.c3data.data.rows = [ titles, values ];
                    var colors = {};
                    for (var i = 0; i < titles.length; i++) {
                        colors[titles[i]] = DashboardStatisticsService.data.chartsColors[i];
                    }
                    this.c3data.data.colors = colors;
                    return this.c3data;
                }
            }
        },
        updateCharts: function(mailingId) {
            jQuery.ajax({
                type: "GET",
                url: AGN.url("/dashboard/statistics.action"),
                data: {
                    mailingId: mailingId
                },
                success: function(data) {
                    var rowNames;
                    var rowValues;
                    var sumValue;
                    data = _.merge({
                        common: [ [ "no Data", "0" ] ],
                        clickers: [ [ "no Data", "0" ] ],
                        clickersPercent: [ 0 ],
                        openers: [ [ "no Data", "0" ] ],
                        openersPercent: [ 0 ]
                    }, data);
                    rowNames = [];
                    rowValues = [];
                    for (var i = 0; i < data["common"].length; i++) {
                        var value = parseInt(data["common"][i][1]);
                        rowNames.push(data["common"][i][0]);
                        rowValues.push(value);
                    }
                    c3.generate(DashboardStatisticsService.data.statChartData.build(rowNames, rowValues));
                    rowNames = [];
                    rowValues = [];
                    sumValue = 0;
                    for (var i = 0; i < data["clickers"].length; i++) {
                        var value = DashboardStatisticsService.roundTo(data["clickers"][i][1] * 100, 1);
                        rowNames.push(data["clickers"][i][0]);
                        rowValues.push(value);
                        sumValue += value;
                    }
                    if (!isNaN(sumValue) && sumValue > 0) {
                        for (var i = 0; i < rowValues.length; i++) {
                            rowNames[i] += " " + DashboardStatisticsService.roundTo(100 * rowValues[i] / sumValue, 1) + "%";
                        }
                    }
                    var clickChartTitle = DashboardStatisticsService.roundTo(data["clickersPercent"][0] * 100, 1) + "%*";
                    c3.generate(DashboardStatisticsService.data.clickChartData.build(clickChartTitle, rowNames, rowValues));
                    rowNames = [];
                    rowValues = [];
                    sumValue = 0;
                    for (var i = 0; i < data["openers"].length; i++) {
                        var value = DashboardStatisticsService.roundTo(data["openers"][i][1] * 100, 1);
                        rowNames.push(data["openers"][i][0]);
                        rowValues.push(value);
                        sumValue += value;
                    }
                    if (!isNaN(sumValue) && sumValue > 0) {
                        for (var i = 0; i < rowValues.length; i++) {
                            rowNames[i] += " " + DashboardStatisticsService.roundTo(100 * rowValues[i] / sumValue, 1) + "%";
                        }
                    }
                    var viewChartTitle = DashboardStatisticsService.roundTo(data["openersPercent"][0] * 100, 1) + "%*";
                    c3.generate(DashboardStatisticsService.data.viewChartData.build(viewChartTitle, rowNames, rowValues));
                    AGN.Lib.CoreInitializer.run("equalizer");
                }
            });
        },
        roundTo: function(number, fractionalDigits) {
            return parseFloat(number).toFixed(fractionalDigits) * 1;
        }
    };
    AGN.Lib.DashboardStatisticsService = DashboardStatisticsService;
})();

(function() {
    var Helpers = AGN.Lib.Helpers;
    AGN.Lib.CoreInitializer.new("pickadate", function($scope) {
        if (!$scope) {
            $scope = $(document);
        }
        _.each($scope.find(".js-datepicker"), function(input) {
            var $input = $(input), $picker, options, baseOptions = {
                editable: true,
                min: new Date(0, 0, 0),
                max: new Date(9999, 11, 31),
                maxFor: undefined,
                minFor: undefined,
                klass: {
                    holder: "datepicker__holder picker__holder" + ($input.hasClass("js-datepicker-right") ? " datepicker__holder-right" : "")
                }
            };
            options = _.merge({}, baseOptions, Helpers.objFromString($input.data("datepicker-options")));
            $picker = $input.pickadate("picker");
            if ($picker && $picker.get("start")) {
                return;
            }
            $(input).pickadate(options);
            $picker = $input.pickadate("picker");
            $picker.on("open", function() {
                this.$node.parents(".input-group").find(".js-open-datepicker").addClass("is-active");
            });
            $picker.on("close", function() {
                this.$node.parents(".input-group").find(".js-open-datepicker").removeClass("is-active");
            });
            if (options.maxFor) {
                $input.on("change", function() {
                    var maximum = $(this).val() || options.min;
                    if (maximum) {
                        $(options.maxFor).pickadate("picker").set("max", maximum);
                    }
                });
            }
            if (options.minFor) {
                $input.on("change", function() {
                    var minimum = $(this).val() || options.max;
                    if (minimum) {
                        $(options.minFor).pickadate("picker").set("min", minimum);
                    }
                });
            }
            var changeHandlerEnabled = true;
            $input.on("change", function() {
                if (changeHandlerEnabled) {
                    var $this = $(this);
                    var picker = $this.pickadate("picker");
                    try {
                        changeHandlerEnabled = false;
                        if ($this.val()) {
                            picker.set("select", $this.val());
                        } else {
                            picker.set("clear");
                        }
                    } finally {
                        changeHandlerEnabled = true;
                    }
                }
            });
        });
        _.each($scope.find(".js-timepicker"), function(input) {
            var $input = $(input), options, mask, baseOptions = {
                mask: "h:halfs",
                oncomplete: function() {
                    $input.trigger("timepicker:complete");
                },
                onincomplete: function() {
                    $input.trigger("timepicker:incomplete");
                }
            };
            options = _.merge({}, baseOptions, Helpers.objFromString($input.data("timepicker-options")));
            mask = options.mask;
            delete options.mask;
            $input.inputmask(mask, options);
            $input.attr("placeholder", $input.data("_inputmask").opts.placeholder);
        });
    });
})();

AGN.Lib.CoreInitializer.new("delegate", function($scope) {
    if (!$scope) {
        $scope = $(document);
    }
    $scope.all("[data-delegate]").each(function() {
        var $source = $(this), delegates = $source.data("delegate"), events = $source.data("delegate-events") || "click";
        $source.on(events, function(event) {
            var $delegates = $(delegates);
            if ($delegates.length > 0) {
                $delegates.trigger($.Event(event));
            }
        });
    });
});

(function() {
    var Helpers = AGN.Lib.Helpers;
    AGN.Lib.CoreInitializer.new("display-dimensions", function($scope) {
        if (!$scope) {
            $scope = $(document);
        }
        _.each($scope.find("[data-display-dimensions]"), function(el) {
            var $el = $(el), scope = Helpers.objFromString($el.data("display-dimensions"))["scope"], $row = $el.parents(scope), $target = $row.find("[data-dimensions]");
            $el.ensureLoad(function() {
                var width = el.naturalWidth, height = el.naturalHeight;
                $target.html(width + " x " + height + " px");
            });
        });
    });
})();

AGN.Lib.CoreInitializer.new("dragster", function($scope) {
    if (!$scope) {
        $scope = $(document);
    }
    $scope.find(".dropzone").each(function() {
        new Dragster(this);
    });
});

AGN.Lib.CoreInitializer.new("dropdown-expand", function($scope) {
    if (!$scope) {
        $scope = $(document);
    }
    _.each($scope.find("[data-dropdown-expand]"), function(el) {
        var spaceLeft, offsetWidth, $el = $(el), $dropdown = $el.find(".dropdown-menu"), target = $el.data("dropdown-expand"), $target = $(target), itemsToBeHidden = [];
        $el.removeClass("hidden");
        $dropdown.html("");
        spaceLeft = $target.parent().width();
        offsetWidth = $target.children().filter($el).outerWidth(true) + 15;
        _.each($target.siblings(), function(ch) {
            var $ch = $(ch);
            spaceLeft = spaceLeft - $ch.outerWidth(true);
        });
        $el.addClass("hidden");
        _.reduce($target.children().not($el), function(sum, ch) {
            var $ch = $(ch);
            $ch.removeClass("hidden");
            sum = sum + $ch.outerWidth(true);
            if (sum >= spaceLeft) {
                $el.removeClass("hidden");
                $dropdown.append($ch.clone());
                $ch.addClass("hidden");
            }
            return sum;
        }, offsetWidth);
    });
});

AGN.Lib.CoreInitializer.new("dropzone", function() {
    Dropzone.autoDiscover = false;
});

AGN.Lib.CoreInitializer.new("emoji", function($scope) {
    if (!$scope) {
        $scope = $(document);
    }
    $scope.all("[data-emoji]").each(function() {
        $(this).emojioneArea({
            placeholder: null
        });
    });
});

(function() {
    var Equalizer = AGN.Lib.Equalizer;
    AGN.Lib.CoreInitializer.new("equalizer", function($scope) {
        if (!$scope) {
            $scope = $(document);
        }
        window.setTimeout(function() {
            $scope.find("[data-equalizer]").each(function() {
                Equalizer($(this));
            });
        }, 1);
    });
})();

(function() {
    var Form = AGN.Lib.Form;
    AGN.Lib.CoreInitializer.new("form", [ "select" ], function($scope) {
        if (!$scope) {
            $scope = $(document);
        }
        $scope.find("form input[type=text], form input[type=password]").on("keyup keypress", function(e) {
            var code = e.keyCode || e.which;
            if (code === 13) {
                e.preventDefault();
                return false;
            }
        });
        var $formInFocus = $scope.all("form[data-form-focus]").first();
        if ($formInFocus.exists()) {
            setTimeout(function() {
                var $e = $formInFocus.find('[name="' + $formInFocus.data("form-focus") + '"]');
                if ($e.exists() && !$e.is(":disabled") && !$e.is(":hidden")) {
                    focusToElement($e);
                }
            }, 10);
        }
        _.each($scope.find("form"), function(form) {
            Form.get($(form));
        });
    });
    function focusToElement($e) {
        var scrollPos;
        var topPadding = 25;
        var $form = Form.get($e).$form;
        var $view = $e.closest("[data-sizing=scroll], .modal").first();
        if (!$view.length) {
            $view = $(document);
            scrollPos = $e.offset().top - $form.offset().top - topPadding;
        } else {
            scrollPos = $e.offset().top - $view.offset().top + $view.scrollTop() - topPadding;
        }
        $e.trigger("focus");
        $view.scrollTop(scrollPos);
    }
})();

AGN.Lib.DomInitializer.new("formbuilder", function($scope) {
    var Tooltip = AGN.Lib.Tooltip;
    if (!$scope) {
        $scope = $(document);
    }
    var config = this.config;
    var $commonConfig = $("script#" + CSS.escape("config:formbuilderCommon") + '[type="application/json"]');
    if ($commonConfig.length === 1) {
        config = $.extend($commonConfig.json(), config);
    }
    _.each($scope.find(".js-form-builder"), function(textArea) {
        AGN.Lib.FormBuilder.FormBuilder.get(textArea, config).promise().then(function() {
            var $textArea = $(textArea);
            $textArea.find(".form-actions button").each(function() {
                var $e = $(this);
                Tooltip.create($e, {
                    title: $e.text()
                });
            });
        });
    });
    _.each($scope.find(".modal-js-form-builder"), function(textArea) {
        var targetAttr = $(textArea).attr("data-target-formbuilder");
        if (!targetAttr) {
            return;
        }
        var $targetFB = $(targetAttr);
        if (!$targetFB) {
            return;
        }
        var targetFBObj = AGN.Lib.FormBuilder.FormBuilder.get($targetFB);
        AGN.Lib.FormBuilder.FormBuilder.get(textArea, config).setJson(targetFBObj.getJson());
    });
});

AGN.Lib.CoreInitializer.new("icons-defs", function($scope) {
    if (!$scope) {
        $scope = $(document);
    }
    _.each($scope.find("[data-icon]"), function(icon) {
        var $icon = $(icon);
        var url = AGN.url("assets/icons-defs.svg#" + $icon.data("icon"), true);
        $icon.html('<svg viewBox="0 0 45 45"><use xlink:href="' + url + '"/></svg>');
    });
    svg4everybody();
});

AGN.Lib.CoreInitializer.new("iframe", function($scope) {
    if (!$scope) {
        $scope = $(document);
    }
    $scope.find("iframe:not(.js-fixed-iframe)").each(function() {
        var el = this, $el = $(this);
        if ($el.hasClass("js-simple-iframe")) {
            var $wrapper = $el.parent(), $page = $wrapper.parent(), maxWidth = parseInt($el.data("max-width")), heightSafety = parseInt($el.data("height-extra")) || 10, mediaQuery = $el.data("media-query"), isFF = !!window.sidebar, updateIframe, resizeArea;
            updateIframe = function() {
                var doc = el.contentDocument ? el.contentDocument : el.contentWindow.document, body = doc.body, html = doc.documentElement, height, width;
                if (mediaQuery) {
                    width = maxWidth;
                } else {
                    width = Math.max(body.scrollWidth, body.offsetWidth, html.clientWidth, html.scrollWidth, html.offsetWidth);
                }
                height = Math.min(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
                $el.height(height);
                height = Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight);
                height += heightSafety;
                $el.height(height);
                if ($el.data("max-width") !== "100%") {
                    $el.width(width);
                }
                if (mediaQuery && isFF) {
                    $el.contents().find("body").css("overflow", "hidden");
                }
                resizeArea();
            };
            resizeArea = function() {
                $page.width("auto");
                if ($el.data("max-width") !== "100%") {
                    if ($el.width() > maxWidth && maxWidth > $page.width()) {
                        $wrapper.width($el.width());
                    } else {
                        $wrapper.width(Math.min(maxWidth, $page.width()));
                    }
                }
                if (!mediaQuery) {
                    $wrapper.doubleScroll();
                    $wrapper.parent().doubleScroll();
                    $(".doubleScroll-scroll-wrapper").css("margin", "0 auto");
                }
            };
            $el.off("load.iframe");
            $el.on("load.iframe", function() {
                window.setTimeout(function() {
                    updateIframe();
                    var $body = $(el.contentDocument.body);
                    if (typeof $body.imagesLoaded === "function") {
                        $body.imagesLoaded().progress(_.throttle(updateIframe, 100)).always(updateIframe);
                    }
                    $(window).off("viewportChanged.iframe", resizeArea);
                    $(window).on("viewportChanged.iframe", resizeArea);
                }, 50);
            });
        } else {
            $el.on("load.iframe", function() {
                window.setTimeout(function() {
                    $el.iFrameResize({
                        heightCalculationMethod: "grow",
                        enablePublicMethods: true
                    });
                }, 50);
            });
        }
    });
});

AGN.Lib.CoreInitializer.new("image-editor", function($scope) {
    if (!$scope) {
        $scope = $(document);
    }
    _.each($scope.find("#editor-canvas"), function(canvas) {
        var context = canvas.getContext("2d");
        var imageObj = new Image();
        imageObj.src = $("#editor-img").attr("src");
        $("#editor-result").val("");
        imageObj.onload = function() {
            var width = imageObj.width;
            var height = imageObj.height;
            context.canvas.width = width;
            context.canvas.height = height;
            context.drawImage(imageObj, 0, 0, width, height);
            $("#l-editor-img-width").attr("value", width);
            $("#l-editor-img-height").attr("value", height);
            $("#l-editor-img-percent").attr("value", 100);
            var newWidthOfEditor = width + $("#l-img-editor-tools").width() + 10;
            $("#l-img-editor").css("min-width", newWidthOfEditor);
            var contentType = $("#editor-img").data("content-type");
            var newSrc = context.canvas.toDataURL(contentType);
            $("#editor-result").attr("value", newSrc);
        };
    });
});

(function() {
    var Helpers = AGN.Lib.Helpers;
    AGN.Lib.CoreInitializer.new("input-mask", function($scope) {
        if (!$scope) {
            $scope = $(document);
        }
        _.each($scope.find(".js-inputmask"), function(input) {
            var $input = $(input);
            var options;
            var mask;
            options = _.merge({}, Helpers.objFromString($input.data("inputmask-options")));
            mask = options.mask;
            delete options.mask;
            $input.inputmask(mask, options);
        });
    });
})();

$.fn.queryBuilder.defaults({
    templates: {
        group: '<dl id="{{= it.group_id }}" class="rules-group-container">   <dt class="rules-group-header">     <div class="btn-group pull-right group-actions">       <button type="button" class="btn btn-xs btn-primary" data-add="rule">         <i class="{{= it.icons.add_rule }}"></i> {{= it.translate("add_rule") }}       </button>       {{? it.settings.allow_groups===-1 || it.settings.allow_groups>=it.level }}         <button type="button" class="btn btn-xs btn-primary" data-add="group">           <i class="{{= it.icons.add_group }}"></i> {{= it.translate("add_group") }}         </button>       {{?}}       {{? it.level>1 }}         <button type="button" class="btn btn-xs btn-alert" data-delete="group">           <i class="{{= it.icons.remove_group }}"></i> {{= it.translate("delete_group") }}         </button>       {{?}}     </div>     <div class="btn-group group-conditions">       {{~ it.conditions: condition }}         <label class="btn btn-xs btn-primary">           <input type="radio" name="{{= it.group_id }}_cond" value="{{= condition }}"> {{= it.translate("conditions", condition) }}         </label>       {{~}}     </div>     {{? it.settings.display_errors }}       <div class="error-container"><i class="{{= it.icons.error }}"></i></div>     {{?}}   </dt>   <dd class=rules-group-body>     <ul class=rules-list></ul>   </dd> </dl>'
    }
});

$.fn.queryBuilder.defaults({
    templates: {
        rule: '<li id="{{= it.rule_id }}" class="rule-container">   <div class="rule-header clearfix">     <div class="btn-group pull-right rule-actions">       <button type="button" class="btn btn-regular btn-alert" data-delete="rule">         <i class="{{= it.icons.remove_rule }}"></i>       </button>     </div>     <div class="rule-operator-conditions-container pull-right"></div>   </div>   {{? it.settings.display_errors }}     <div class="error-container"><i class="{{= it.icons.error }}"></i></div>   {{?}}   <div class="rule-filter-container"></div>   <div class="rule-operator-container"></div>   <div class="rule-value-container"></div> </li>'
    }
});

$.fn.queryBuilder.defaults({
    templates: {
        filterSelect: '{{ var optgroup = null; }} <select class="form-control js-select" name="{{= it.rule.id }}_filter">   {{? it.settings.display_empty_filter }}     <option value="-1">{{= it.settings.select_placeholder }}</option>   {{?}}   {{~ it.filters: filter }}     {{? optgroup !== filter.optgroup }}       {{? optgroup !== null }}</optgroup>{{?}}       {{? (optgroup = filter.optgroup) !== null }}         <optgroup label="{{= it.translate(it.settings.optgroups[optgroup]) }}">       {{?}}     {{?}}     <option value="{{= filter.id }}">{{= it.translate(filter.label) }}</option>   {{~}}   {{? optgroup !== null }}</optgroup>{{?}} </select>'
    }
});

$.fn.queryBuilder.defaults({
    templates: {
        ruleValueSelect: '{{ var optgroup = null; }} <select class="form-control js-select" name="{{= it.name }}" {{? it.rule.filter.multiple }}multiple{{?}}>   {{? it.rule.filter.placeholder }}     <option value="{{= it.rule.filter.placeholder_value }}" disabled selected>{{= it.rule.filter.placeholder }}</option>   {{?}}   {{~ it.rule.filter.values: entry }}     {{? optgroup !== entry.optgroup }}       {{? optgroup !== null }}</optgroup>{{?}}       {{? (optgroup = entry.optgroup) !== null }}         <optgroup label="{{= it.translate(it.settings.optgroups[optgroup]) }}">       {{?}}     {{?}}     <option value="{{= entry.value }}">{{= entry.label }}</option>   {{~}}   {{? optgroup !== null }}</optgroup>{{?}} </select>'
    }
});

$.fn.queryBuilder.defaults({
    icons: {
        add_group: "icon icon-plus-circle",
        add_rule: "icon icon-plus",
        remove_group: "icon icon-times",
        remove_rule: "icon icon-trash",
        error: "icon icon-exclamation-triangle"
    }
});

(function() {
    var Load = AGN.Lib.Load;
    AGN.Lib.CoreInitializer.new("load", function($scope) {
        if (!$scope) {
            $scope = $(document);
        }
        _.each($scope.find("[data-load]"), function(el) {
            window.setTimeout(function() {
                Load.load($(el));
            }, 100);
        });
    });
})();

AGN.Lib.DomInitializer.new("logon-complete", function($form) {
    var form = AGN.Lib.Form.get($form);
    var data = {};
    window.adminId = this.config.adminId;
    if (this.config) {
        $.each(this.config.webStorageBundleNames, function(index, name) {
            try {
                var bundle = AGN.Lib.Storage.get("web-storage#" + name);
                if (bundle != null) {
                    data[name] = bundle;
                }
            } catch (e) {
                console.error(e);
            }
        });
        var settings = AGN.Lib.Storage.get("login-page") || {};
        settings.isFrameShown = !!this.config.isFrameShown;
        AGN.Lib.Storage.set("login-page", settings);
    }
    form.setValue("webStorageJson", JSON.stringify(data));
    form.submit();
});

(function() {
    var NOTIFICATION_DISMISS_EXPIRATION_DAYS = 30;
    function getSettings() {
        return AGN.Lib.Storage.get("login-page") || {};
    }
    function setSettings(settings) {
        AGN.Lib.Storage.set("login-page", settings);
    }
    function isNotificationDismissExpired() {
        var settings = getSettings();
        if (settings) {
            if (settings.notificationDismissExpiration) {
                return settings.notificationDismissExpiration <= Date.now();
            }
        }
        var closedDate = localStorage.getItem("closedDate");
        if (closedDate) {
            var currentDate = new Date();
            var requiredDate = new Date(closedDate);
            requiredDate.setDate(requiredDate.getDate() + NOTIFICATION_DISMISS_EXPIRATION_DAYS);
            return currentDate - requiredDate > 0;
        }
        return true;
    }
    function onNotificationDismiss() {
        var settings = getSettings();
        var expirationDate = new Date();
        expirationDate.setDate(expirationDate.getDate() + NOTIFICATION_DISMISS_EXPIRATION_DAYS);
        settings.notificationDismissExpiration = expirationDate.getTime();
        setSettings(settings);
    }
    function isFrameHidden() {
        return getSettings().isFrameShown == false;
    }
    AGN.Lib.DomInitializer.new("logon", function($e) {
        $e.toggleClass("l-hide-frame", isFrameHidden());
        $e.removeClass("hidden");
        if (isNotificationDismissExpired() && this.config.SHOW_TAB_HINT === true) {
            var head = t("defaults.info");
            var content = t("logon.info.multiple_tabs");
            AGN.Lib.Messages(head, content, "info", onNotificationDismiss, false);
        }
    });
})();

(function() {
    var LOCKING_UPDATE_INTERVAL_MILLISECONDS = 45e3;
    var LOCKING_MAX_DURATION_MILLISECONDS = 3 * 60 * 6e4;
    AGN.Opt.Components.MailingContentLock = {
        manageLock: function(mailingId, isMailingExclusiveLockingAcquired, anotherLockingUserName) {
            if (mailingId > 0 && isMailingExclusiveLockingAcquired) {
                var ajaxLockingBeginTimestamp = Date.now();
                var ajaxLockingUpdateIntervalId;
                var ajaxUpdateLocking = function() {
                    if (ajaxLockingBeginTimestamp + LOCKING_MAX_DURATION_MILLISECONDS > Date.now()) {
                        $.ajax({
                            url: AGN.url("/mailing/ajax/" + mailingId + "/lock.action"),
                            type: "POST",
                            success: function(resp) {
                                if (resp.success !== true) {
                                    clearInterval(ajaxLockingUpdateIntervalId);
                                }
                            },
                            statusCode: {
                                404: function() {
                                    clearInterval(ajaxLockingUpdateIntervalId);
                                }
                            }
                        });
                    } else {
                        clearInterval(ajaxLockingUpdateIntervalId);
                        $(document).trigger("ajax:unauthorized");
                        $.ajax({
                            url: AGN.url("/logout.action"),
                            type: "POST",
                            success: function() {
                                $("body").append(AGN.Lib.Template.text("session-expired"));
                            }
                        });
                    }
                };
                ajaxLockingUpdateIntervalId = setInterval(ajaxUpdateLocking, LOCKING_UPDATE_INTERVAL_MILLISECONDS);
                return true;
            } else {
                AGN.Lib.Modal.createFromTemplate({
                    modalClass: "",
                    title: t("defaults.warning"),
                    content: t("error.mailing.exclusiveLockingFailed", anotherLockingUserName)
                }, "modal");
                return false;
            }
        }
    };
})();

AGN.Lib.DomInitializer.new("mailing-content-overview", function($elem, $scope) {
    var config = this.config;
    if (!$scope) {
        var data = AGN.Lib.Storage.get("mailings-content-dynNameID");
        if (data) {
            var $tr = $("tr[data-dyn-name-id='" + data.dynNameID + "']");
            if ($tr.exists()) {
                var top = $tr.position().top;
                setTimeout(function() {
                    $("body").scrollTop(top);
                }, 1);
                AGN.Lib.Storage.set("mailings-content-dynNameID", {
                    dynNameID: 0
                });
            }
        }
    }
    var $datePicker = $("#myDatePicker");
    if ($datePicker.exists()) {
        $datePicker.pickadate("picker").on({
            set: function(thingSet) {
                if ("select" in thingSet) {
                    var d = new Date(thingSet.select);
                    $("#startDay").val(d.getDate());
                    $("#startMonth").val(d.getMonth() + 1);
                    $("#startYear").val(d.getFullYear());
                } else {
                    $("#startDay").val(0);
                    $("#startMonth").val(0);
                    $("#startYear").val(0);
                }
            }
        });
        var $timePicker = $("#myTimePicker");
        $timePicker.on("timepicker:complete", function() {
            var time = $timePicker.val();
            $("#startHour").val(time.substr(0, 2));
            $("#startMinute").val(time.substring(3, 5));
        });
        $timePicker.on("timepicker:incomplete", function() {
            $("#startHour").val(0);
            $("#startMinute").val(0);
        });
    }
    if (!config.isEditableMailing || !AGN.Opt.Components.MailingContentLock.manageLock(config.mailingId, config.isMailingExclusiveLockingAcquired, config.anotherLockingUserName)) {
        var $controls = $('[data-controls-group="editing"]');
        $controls.prop("disabled", true);
        $controls.addClass("disabled");
    }
});

AGN.Lib.DomInitializer.new("mailing-content-view", function($elem) {
    AGN.Lib.Storage.set("mailings-content-dynNameID", {
        dynNameID: $elem.data("dyn-name-id")
    });
});

AGN.Lib.Controller.new("mailing-followup-options", function() {
    var $container;
    var $mailingSelect = "";
    var additionalOptions = [];
    this.addDomInitializer("mailing-followup-options", function() {
        $container = $("#followUpType");
        $mailingSelect = $("#lightWeightMailingList");
        additionalOptions = this.config.additionalOptions;
        changeFollowUpOptionsSet();
        $mailingSelect.on("change", function() {
            changeFollowUpOptionsSet();
        });
    });
    var getAdditionalAdvertisingOptions = function() {
        return AGN.Lib.Template.text("followupAdvertisingOptions", {
            items: additionalOptions
        });
    };
    var changeFollowUpOptionsSet = function() {
        var mailingIdToCheck = AGN.Lib.Select.get($mailingSelect).getSelectedValue();
        $container.children(".advertisingOption").remove();
        if (mailingIdToCheck) {
            $.ajax({
                type: "POST",
                url: AGN.url("/mailing/ajax/" + mailingIdToCheck + "/isAdvertisingContentType.action")
            }).done(function(resp) {
                if (resp && resp.success) {
                    $container.append(getAdditionalAdvertisingOptions());
                }
            });
        }
    };
});

AGN.Lib.DomInitializer.new("mailing-overview-filters", function() {
    $("#filtersDescription").html(AGN.Lib.Template.text("mailing-overview-filters", this.config));
    $("#mailing").after($("#mailings-overviewPreview"));
});

AGN.Lib.DomInitializer.new("mailing-overview-table", function($table) {
    $table.removeClass("hidden");
});

AGN.Lib.DomInitializer.new("mediapool-image-pick", function($dialog) {
    var $options = $dialog.find("#mediapool-image-pick-options");
    var $results = $dialog.find("#mediapool-browser-results");
    var $modalBody = $dialog.find(".modal-body");
    var $keywordsInput = $dialog.find("#mpFilterKeywords");
    var $categoryInput = $dialog.find("#mpFilterCategory");
    var $sortCriteria = $dialog.find("#mpSortCriteria");
    var $isAscendingSortOrder = $dialog.find("#mpIsAscendingSortOrder");
    var renderResults = AGN.Lib.Template.prepare("mediapool-browser-results-template");
    var categoriesSelect = AGN.Lib.Select.get($categoryInput);
    function getImage($card) {
        var id = $card.data("image-id");
        if (id > 0) {
            var image = options.images.find(function(entry) {
                return entry.id === id;
            });
            return image || {
                id: id
            };
        }
        return null;
    }
    var options = $options.json();
    var $selection = null;
    if (options.images) {
        $results.html(renderResults({
            results: options.images,
            fullListSize: options.fullListSize
        }));
    }
    if ($dialog.is("[load-filters-on-init]")) {
        fillFilters();
    }
    if ($dialog.is("[load-images-on-init]")) {
        performSearch();
    }
    function performSearch() {
        $modalBody.addClass("ui-modal-loading");
        $.ajax({
            type: "POST",
            url: options.urls.MEDIAPOOL_SEARCH,
            data: {
                categoryId: $categoryInput.val(),
                keywords: $keywordsInput.val(),
                sortCriteria: $sortCriteria.val(),
                isAscendingSortOrder: $isAscendingSortOrder.val()
            }
        }).done(function(pagination) {
            var fullSize = pagination.fullListSize;
            var images = pagination.partialList;
            $results.html(renderResults({
                results: images,
                fullListSize: fullSize
            }));
            options.images = images;
            $selection = null;
        }).fail(function() {
            $results.html(renderResults({
                results: [],
                fullListSize: 0
            }));
            options.images = [];
            $selection = null;
        }).always(function() {
            $modalBody.removeClass("ui-modal-loading");
        });
    }
    function fillFilters() {
        $.ajax({
            type: "GET",
            url: options.urls.FILTERS_JSON
        }).done(function(data) {
            _.each(data.categories, function(item) {
                categoriesSelect.addFormattedOption('<option value="' + item.id + '" data-id="' + item.id + '" data-parent-id="' + item.parentId + '">' + item.shortname + "</option>");
            });
        });
    }
    this.addAction({
        click: "mpSearchImages",
        enterdown: "mpFilterKeywords"
    }, performSearch);
    this.addAction({
        dblclick: "mpSelectImage"
    }, function() {
        var image = getImage(this.el);
        if (image) {
            AGN.Lib.Confirm.get($dialog).positive(image);
        }
    });
    this.addAction({
        click: "mpSelectImage"
    }, function() {
        if ($selection) {
            $selection.removeClass("active");
        }
        $selection = this.el;
        $selection.addClass("active");
    });
    this.addAction({
        click: "mpAcceptImage"
    }, function() {
        if ($selection) {
            var image = getImage($selection);
            if (image) {
                AGN.Lib.Confirm.get($dialog).positive(image);
            }
        } else {
            AGN.Lib.Messages(t("Error"), t("messages.error.nothing_selected"), "alert");
        }
    });
});

AGN.Lib.CoreInitializer.new("menu", function() {
    AGN.Lib.Menu.init();
});

(function() {
    var MessageStatisticsService = {
        data: {
            chartsColors: [ "#26b98a" ],
            statChartData: {
                columnTitles: [],
                c3data: {
                    bindto: "#barchart-message-stats",
                    data: {
                        columns: [],
                        type: "bar",
                        labels: true
                    },
                    axis: {
                        x: {
                            tick: {
                                centered: true,
                                fit: true,
                                format: function(columnIndex) {
                                    return MessageStatisticsService.data.statChartData.columnTitles[columnIndex];
                                }
                            }
                        },
                        y: {
                            show: false
                        }
                    },
                    legend: {
                        show: false
                    },
                    tooltip: {
                        format: {
                            title: function() {
                                return null;
                            },
                            name: function(name, ratio, id, index) {
                                return MessageStatisticsService.data.statChartData.columnTitles[index];
                            },
                            value: function(value, ratio, id, index) {
                                return value;
                            }
                        }
                    },
                    padding: {
                        right: 25,
                        left: 25
                    }
                },
                build: function(data) {
                    this.columnTitles.push(data.shift());
                    data.unshift("values");
                    this.c3data.data.columns = [ data ];
                    return this.c3data;
                }
            }
        },
        updateChart: function(url) {
            $.ajax({
                type: "GET",
                url: url,
                success: function(data) {
                    c3.generate(MessageStatisticsService.data.statChartData.build(data));
                    AGN.Lib.CoreInitializer.run("equalizer");
                }
            });
        }
    };
    AGN.Lib.MessageStatisticsService = MessageStatisticsService;
    AGN.Lib.DomInitializer.new("message-stat", function($e) {
        var config = AGN.Lib.Helpers.objFromString($e.data("config"));
        if (config && config.url) {
            MessageStatisticsService.updateChart(config.url);
        }
    });
})();

(function() {
    AGN.Lib.DomInitializer.new("news-editor-period", function($elem) {
        initDatePeriodSelector($elem);
    });
    function initDatePeriodSelector($scope) {
        if (!$scope) {
            $scope = $(document);
        }
        var periodElements = [];
        _.each($scope.find(".js-datepicker"), function(input) {
            var $input = $(input);
            if ($input.hasClass("js-datepicker-period-start")) {
                if (!($input.attr("datepicker-period-id") in periodElements)) {
                    periodElements[$input.attr("datepicker-period-id")] = {
                        startEl: null,
                        endEl: null
                    };
                }
                periodElements[$input.attr("datepicker-period-id")].startEl = $input;
            }
            if ($input.hasClass("js-datepicker-period-end")) {
                if (!($input.attr("datepicker-period-id") in periodElements)) {
                    periodElements[$input.attr("datepicker-period-id")] = {
                        startEl: null,
                        endEl: null
                    };
                }
                periodElements[$input.attr("datepicker-period-id")].endEl = $input;
            }
        });
        for (var i = 0; i < periodElements.length; i++) {
            initPeriodDatePickers(periodElements[i].startEl.pickadate("picker"), periodElements[i].endEl.pickadate("picker"));
        }
    }
    function initPeriodDatePickers($datePickerStart, $datePickerEnd) {
        var pickerStartDay = $datePickerStart;
        var pickerEndDay = $datePickerEnd;
        if (pickerStartDay.get("value")) {
            pickerEndDay.set("min", pickerStartDay.get("select"));
        }
        if (pickerEndDay.get("value")) {
            pickerStartDay.set("max", pickerEndDay.get("select"));
        }
        pickerStartDay.on("set", function(event) {
            if (event.select) {
                pickerEndDay.set("min", pickerStartDay.get("select"));
            } else if ("clear" in event) {
                pickerEndDay.set("min", false);
            }
        });
        pickerEndDay.on("set", function(event) {
            if (event.select) {
                pickerStartDay.set("max", pickerEndDay.get("select"));
            } else if ("clear" in event) {
                pickerStartDay.set("max", false);
            }
        });
    }
})();

(function() {
    var GLobalNotificationBrowserStatService = {
        data: {
            chartsColors: [ "#0071b9", "#009999", "#92d050", "#41641a", "#ffc000" ],
            browserChartData: {
                c3data: {
                    bindto: "#notificationGlobalBrowserStat",
                    data: {
                        rows: [],
                        type: "donut"
                    },
                    donut: {
                        label: {
                            show: true
                        }
                    },
                    legend: {
                        position: "right"
                    },
                    tooltip: {
                        show: false
                    }
                },
                build: function(titles, values) {
                    this.c3data.data.rows = [ titles, values ];
                    var colors = {};
                    for (var i = 0; i < titles.length; i++) {
                        colors[titles[i]] = GLobalNotificationBrowserStatService.data.chartsColors[i];
                    }
                    this.c3data.data.colors = colors;
                    return this.c3data;
                }
            }
        },
        roundTo: function(number, fractionalDigits) {
            return parseFloat(number).toFixed(fractionalDigits) * 1;
        },
        updateChart: function(url) {
            $.ajax({
                type: "GET",
                url: url,
                success: function(data) {
                    if (data && (data.warning && data.warning.length > 0)) {
                        AGN.Lib.JsonMessages(data, true);
                    } else {
                        var titles = [];
                        var values = [];
                        var sumValue = 0;
                        for (key in data) {
                            var value = GLobalNotificationBrowserStatService.roundTo(data[key] * 100, 1);
                            titles.push(key);
                            values.push(value);
                            sumValue += value;
                        }
                        if (!isNaN(sumValue) && sumValue > 0) {
                            for (var i = 0; i < values.length; i++) {
                                titles[i] += " " + GLobalNotificationBrowserStatService.roundTo(100 * values[i] / sumValue, 1) + "%";
                            }
                        }
                        c3.generate(GLobalNotificationBrowserStatService.data.browserChartData.build(titles, values));
                        AGN.Lib.CoreInitializer.run("equalizer");
                    }
                }
            });
        }
    };
    AGN.Lib.GLobalNotificationBrowserStatService = GLobalNotificationBrowserStatService;
    AGN.Lib.DomInitializer.new("notification-global-browser-stat", function($elem) {
        var config = AGN.Lib.Helpers.objFromString($elem.data("config"));
        if (config && config.url) {
            AGN.Lib.GLobalNotificationBrowserStatService.updateChart(config.url);
        }
    });
})();

(function() {
    var GLobalNotificationProgressStatService = {
        data: {
            chartColors: [ "#0071b9", "#006600", "#b30000" ],
            globalProgressChartData: {
                columnTitles: [],
                c3data: {
                    bindto: "#notificationGlobalProgressStat",
                    data: {
                        x: "x",
                        columns: []
                    },
                    axis: {
                        x: {
                            type: "category",
                            tick: {
                                centered: true,
                                fit: false
                            }
                        }
                    },
                    padding: {
                        right: 25
                    }
                },
                build: function(times, data1, data2, data3) {
                    this.c3data.data.columns = [ times, data1, data2, data3 ];
                    var colors = {};
                    colors[data1[0]] = GLobalNotificationProgressStatService.data.chartColors[0];
                    colors[data2[0]] = GLobalNotificationProgressStatService.data.chartColors[1];
                    colors[data3[0]] = GLobalNotificationProgressStatService.data.chartColors[2];
                    this.c3data.data.colors = colors;
                    return this.c3data;
                }
            }
        },
        updateChart: function(url) {
            var time = [ "x" ];
            var data1 = [];
            var data2 = [];
            var data3 = [];
            var dateMode = $("#selectMode").val();
            var selectMonth = $("#selectMonth").val();
            var selectYear = $("#selectYear").val();
            var startDayFromDatePicker = $("#startDay").val();
            var endDayFromDatePicker = $("#endDay").val();
            $.ajax({
                type: "GET",
                url: url,
                data: {
                    dateMode: dateMode,
                    selectMonth: selectMonth,
                    selectYear: selectYear,
                    startDay: startDayFromDatePicker,
                    endDay: endDayFromDatePicker
                },
                success: function(data) {
                    if (data && data.warning && data.warning.length > 0) {
                        AGN.Lib.JsonMessages(data, true);
                    } else {
                        for (objIndex in data) {
                            var jsonItem = data[objIndex];
                            for (objKey in jsonItem) {
                                if (objIndex == 0 && objKey != "time") {
                                    if (data1.length == 0) {
                                        data1.push(objKey);
                                    } else if (data2.length == 0) {
                                        data2.push(objKey);
                                    } else if (data3.length == 0) {
                                        data3.push(objKey);
                                    }
                                }
                                var value = jsonItem[objKey];
                                if (objKey == "time") {
                                    time.push(value);
                                } else if (objKey == data1[0]) {
                                    data1.push(value);
                                } else if (objKey == data2[0]) {
                                    data2.push(value);
                                } else if (objKey == data3[0]) {
                                    data3.push(value);
                                }
                            }
                        }
                        c3.generate(GLobalNotificationProgressStatService.data.globalProgressChartData.build(time, data1, data2, data3));
                        AGN.Lib.CoreInitializer.run("equalizer");
                    }
                }
            });
        }
    };
    AGN.Lib.GLobalNotificationProgressStatService = GLobalNotificationProgressStatService;
    AGN.Lib.DomInitializer.new("notification-global-progress-stat", function($elem) {
        var config = AGN.Lib.Helpers.objFromString($elem.data("config"));
        if (config && config.url) {
            AGN.Lib.GLobalNotificationProgressStatService.updateChart(config.url);
        }
    });
})();

(function() {
    var GLobalNotificationStatusStatService = {
        data: {
            chartsColors: [ "#0071b9", "#92D050", "#41641A" ],
            statusChartData: {
                columnTitles: [],
                c3data: {
                    bindto: "#notificationGlobalStatusStat",
                    data: {
                        columns: [],
                        type: "bar",
                        labels: true,
                        color: function(color, d) {
                            return GLobalNotificationStatusStatService.data.chartsColors[d.index];
                        }
                    },
                    axis: {
                        x: {
                            tick: {
                                centered: true,
                                fit: true,
                                format: function(columnIndex) {
                                    return GLobalNotificationStatusStatService.data.statusChartData.columnTitles[columnIndex];
                                }
                            }
                        },
                        y: {
                            show: false
                        }
                    },
                    legend: {
                        show: false
                    },
                    tooltip: {
                        format: {
                            title: function() {
                                return null;
                            },
                            name: function(name, ratio, id, index) {
                                return GLobalNotificationStatusStatService.data.statusChartData.columnTitles[index];
                            },
                            value: function(value, ratio, id, index) {
                                return value;
                            }
                        }
                    },
                    padding: {
                        right: 25,
                        left: 25
                    }
                },
                build: function(titles, values) {
                    this.columnTitles = titles;
                    var row = values.slice(0);
                    row.unshift("values");
                    this.c3data.data.columns = [ row ];
                    return this.c3data;
                }
            }
        },
        updateChart: function(url) {
            $.ajax({
                type: "GET",
                url: url,
                success: function(data) {
                    if (data && data.warning && data.warning.length > 0) {
                        AGN.Lib.JsonMessages(data, true);
                    } else {
                        var titles = [];
                        var values = [];
                        for (key in data) {
                            titles.push(key);
                            values.push(data[key]);
                        }
                        c3.generate(GLobalNotificationStatusStatService.data.statusChartData.build(titles, values));
                        AGN.Lib.CoreInitializer.run("equalizer");
                    }
                }
            });
        }
    };
    AGN.Lib.GLobalNotificationStatusStatService = GLobalNotificationStatusStatService;
    AGN.Lib.DomInitializer.new("notification-global-status-stat", function($elem) {
        var config = AGN.Lib.Helpers.objFromString($elem.data("config"));
        if (config && config.url) {
            AGN.Lib.GLobalNotificationStatusStatService.updateChart(config.url);
        }
    });
})();

AGN.Lib.CoreInitializer.new("push-notification-preview", function($scope) {
    if (!$scope) {
        $scope = $(document);
    }
    _.each($scope.find(".push-notification-preview-button"), function(el) {
        function disablePreviewButton($element) {
            $element.prop("disabled", true);
            $element.parent().attr("data-tooltip", $element.parent().attr("data-tooltip-if-disabled"));
        }
        var $el = $(el);
        var formName = $el.data("notification-form");
        if (Notification.permission == "denied") {
            disablePreviewButton($el);
        } else {
            $el.on("click", function() {
                function preview_push_notification() {
                    var form = $("#" + formName);
                    var titleElement = form.find("#pushTitle");
                    var contentElement = form.find("#pushContent");
                    var iconElement = form.find("#pushIcon");
                    var linkElement = form.find("#pushLink");
                    var pushTitle = titleElement ? titleElement.val() : "";
                    var pushContent = contentElement ? contentElement.val() : "";
                    var pushIcon = iconElement ? iconElement.val() : "";
                    var pushLink = linkElement ? linkElement.val() : "";
                    var opt = {
                        body: pushContent,
                        icon: pushIcon
                    };
                    var notification = new Notification(pushTitle, opt);
                    notification.onclick = function(event) {
                        event.preventDefault();
                        window.open(pushLink, "_blank");
                    };
                }
                if (Notification.permission != "granted") {
                    Notification.requestPermission(function(result) {
                        if (result == "granted") {
                            preview_push_notification();
                        } else if (result == "denied") {
                            disablePreviewButton($el);
                        }
                    });
                } else {
                    preview_push_notification();
                }
            });
        }
    });
});

(function() {
    var NotificationStatService = {
        data: {
            chartsColors: [ "#0071b9" ],
            statChartData: {
                columnTitles: [],
                c3data: {
                    bindto: "#barchart-notification-stats",
                    data: {
                        columns: [],
                        type: "bar",
                        labels: true
                    },
                    axis: {
                        x: {
                            tick: {
                                centered: true,
                                fit: true,
                                format: function(columnIndex) {
                                    return NotificationStatService.data.statChartData.columnTitles[columnIndex];
                                }
                            }
                        }
                    },
                    legend: {
                        show: false
                    },
                    tooltip: {
                        format: {
                            title: function() {
                                return null;
                            },
                            name: function(name, ratio, id, index) {
                                return NotificationStatService.data.statChartData.columnTitles[index];
                            },
                            value: function(value, ratio, id, index) {
                                return value;
                            }
                        }
                    },
                    padding: {
                        right: 25
                    }
                },
                build: function(titles, values) {
                    this.columnTitles = titles;
                    var row = values.slice(0);
                    row.unshift("values");
                    this.c3data.data.columns = [ row ];
                    return this.c3data;
                }
            },
            progressChartData: {
                c3data: {
                    bindto: "#progresschart-notification-stats",
                    data: {
                        x: "x",
                        columns: []
                    },
                    axis: {
                        x: {
                            type: "category",
                            tick: {
                                fit: false
                            }
                        }
                    },
                    zoom: {
                        enabled: true,
                        rescale: true
                    },
                    subchart: {
                        show: true
                    },
                    padding: {
                        right: 25
                    }
                },
                build: function(times, data1, data2) {
                    this.c3data.data.columns = [ times, data1, data2 ];
                    return this.c3data;
                }
            }
        },
        updateCharts: function(pushId, url) {
            $.ajax({
                type: "GET",
                url: url,
                data: {
                    pushID: pushId
                },
                success: function(data) {
                    generateCommonStatisticChart(data["common"]);
                    generateProgressChart(data["viewsclicks"]);
                    AGN.Lib.CoreInitializer.run("equalizer");
                }
            });
        }
    };
    AGN.Lib.NotificationStatService = NotificationStatService;
    AGN.Lib.DomInitializer.new("notification-stats", function($elem) {
        var config = AGN.Lib.Helpers.objFromString($elem.data("config"));
        if (config && config.pushId && config.url) {
            AGN.Lib.NotificationStatService.updateCharts(config.pushId, config.url);
        }
    });
    function generateCommonStatisticChart(jsonCommonStatisticData) {
        var rowNames = [];
        var rowValues = [];
        for (var key in jsonCommonStatisticData) {
            if (jsonCommonStatisticData.hasOwnProperty(key)) {
                rowNames.push(key);
                rowValues.push(jsonCommonStatisticData[key]);
            }
        }
        c3.generate(NotificationStatService.data.statChartData.build(rowNames, rowValues));
    }
    function generateProgressChart(jsonProgressData) {
        var times = [ "x" ];
        var data1 = [];
        var data2 = [];
        for (objIndex in jsonProgressData) {
            var jsonProgressItem = jsonProgressData[objIndex];
            for (var jsonProgressObjectKey in jsonProgressItem) {
                if (jsonProgressItem.hasOwnProperty(jsonProgressObjectKey)) {
                    if (objIndex == 0 && jsonProgressObjectKey != "time") {
                        if (data1.length == 0) {
                            data1.push(jsonProgressObjectKey);
                        } else if (data2.length == 0) {
                            data2.push(jsonProgressObjectKey);
                        }
                    }
                    if (jsonProgressObjectKey == "time") {
                        times.push(jsonProgressItem[jsonProgressObjectKey]);
                    } else if (data1[0] == jsonProgressObjectKey) {
                        data1.push(jsonProgressItem[jsonProgressObjectKey]);
                    } else if (data2[0] == jsonProgressObjectKey) {
                        data2.push(jsonProgressItem[jsonProgressObjectKey]);
                    }
                }
            }
        }
        c3.generate(NotificationStatService.data.progressChartData.build(times, data1, data2));
    }
})();

AGN.Lib.CoreInitializer.new("polling-form", function($scope) {
    if (!$scope) {
        $scope = $(document);
    }
    $scope.find('[data-form="polling"]').each(function() {
        AGN.Lib.Form.get($(this)).submit();
    });
});

AGN.Lib.CoreInitializer.new("popover-validate", function() {
    AGN.Lib.Popover.validate();
});

(function() {
    AGN.Lib.CoreInitializer.new("target-group-query-builder-extend", function() {
        if (window.queryBuilderIsExtended) {
            return;
        }
        window.queryBuilderIsExtended = true;
        var MIN_EXPECTED_SIZE = 2;
        var Utils = {};
        function addOperator(value, dateValue) {
            if (Math.sign(value) === -1) {
                dateValue.push("sub");
            } else {
                dateValue.push("add");
            }
        }
        function updateValue(rule, value, operator) {
            if (operator) {
                if (operator === "sub") {
                    value = "-" + Math.abs(value);
                } else {
                    value = "+" + Math.abs(value);
                }
            }
            rule.$el.find("#date-filter").val(value);
        }
        var QueryBuilder = $.fn.queryBuilder;
        var QueryBuilderConstructor = QueryBuilder.constructor;
        var originalInit = QueryBuilderConstructor.prototype.init;
        var originalValidate = QueryBuilderConstructor.prototype.validate;
        var originalBindEvents = QueryBuilderConstructor.prototype.bindEvents;
        Utils = QueryBuilderConstructor.utils;
        var Selectors = QueryBuilderConstructor.selectors;
        Object.assign(Selectors, {
            rule_include_empty: ".rule-include-empty[name*=_include_empty]",
            rule_operator_conditions_container: ".rule-operator-conditions-container",
            rule_header_inputs: ".rule-header :input"
        });
        Utils.defineModelProperties(QueryBuilderConstructor.Rule, [ "includeEmpty" ]);
        QueryBuilder.extend({
            init: function(rules) {
                this.on("afterCreateRuleInput", function(event, rule) {
                    var options = event.builder.optionsByType[rule.filter.type];
                    if (options) {
                        var method = options.postCreate;
                        if (method && typeof method === "function") {
                            method.call(event.builder, rule, options);
                        }
                    }
                });
                this.on("afterUpdateRuleOperator", function(event, rule) {
                    var options = event.builder.optionsByType[rule.filter.type];
                    if (options) {
                        var method = options.postOperatorUpdate;
                        if (method && typeof method === "function") {
                            method.call(event.builder, rule, options);
                        }
                    }
                });
                this.setupInitialRule(rules);
                return originalInit.call(this, rules);
            },
            isEmptyOrInitial: function(data) {
                if (!data || !data.rules || !data.rules.length) {
                    return true;
                }
                if (data.rules.length === 1 && (data.rules[0].initialRule || data.rules[0].empty)) {
                    return true;
                }
                return false;
            },
            setupInitialRule: function(data) {
                if (this.isEmptyOrInitial(data)) {
                    this.initialRule = true;
                    data.rules = [ {
                        initialRule: true,
                        empty: true
                    } ];
                } else {
                    this.initialRule = false;
                }
            },
            optionsByType: {
                date: {
                    availableFormats: function(operator) {
                        if (operator && operator.type && (operator.type == "before" || operator.type == "after")) {
                            return [ "YYYYMMDD" ];
                        }
                        return [ "DD.MM.YYYY", "YYYYMMDD", "DDMMYYYY", "MMDD", "DDMM", "DD", "MM", "YYYY" ];
                    },
                    input: function(rule, options) {
                        return $('<div class="qb-input-label">' + '<label class="checkbox-inline">' + '<input name="today" type="checkbox">' + '<span class="text">' + t("defaults.today") + "</span>" + "</label>" + "</div>" + '<div class="qb-input-element date-filter">' + '<input class="form-control" type="text" id="date-filter"/>' + "</div>" + '<div class="qb-input-label" id="date-offset-label" style="display: none;">' + '<div class="form-badge qb-input-inner">' + t("defaults.days") + "</div>" + "</div>" + '<div class="qb-input-label">' + '<div class="qb-input-inner">' + t("date.formats.label") + "</div>" + "</div>" + '<div class="qb-input-element">' + '<select class="form-control" id="date-format">' + generateDateFormatSelect(options.availableFormats(options.operator)) + "</select>" + "</div>" + '<div class="qb-input-label">' + '<div class="qb-input-inner">' + '<button type="button" class="icon icon-help" data-help="help_' + this.settings.helpLanguage + '/targets/DateFormat.xml"></button>' + "</div>" + "</div>");
                    },
                    postCreate: function(rule) {
                        var $todayCheckbox = rule.$el.find("input[name=today]");
                        var $offsetLabel = rule.$el.find("#date-offset-label");
                        var $dateFilter = rule.$el.find("#date-filter");
                        var $dateFormat = rule.$el.find("#date-format");
                        var onModeChange = function() {
                            var isToday = $todayCheckbox.prop("checked");
                            $offsetLabel.toggle(isToday);
                            $dateFilter.off("change.offset keyup.offset");
                            if (!rule._updating_input) {
                                rule._updating_value = true;
                                if (isToday) {
                                    $dateFilter.val("+0");
                                } else {
                                    $dateFilter.val(formatDate(new Date(), $dateFormat.val()));
                                }
                                rule._updating_value = false;
                            }
                            if (isToday) {
                                $dateFilter.on("change.offset keyup.offset", function(e) {
                                    var value = $dateFilter.val();
                                    if (value) {
                                        var offset = parseInt(value);
                                        if (!isNaN(offset)) {
                                            var newValue = (offset < 0 ? "" : "+") + offset;
                                            if (newValue != value) {
                                                $dateFilter.val(newValue);
                                            }
                                        }
                                    } else if (e.type === "change") {
                                        $dateFilter.val("+0");
                                    }
                                });
                            }
                        };
                        $todayCheckbox.on("change", onModeChange);
                    },
                    postOperatorUpdate: function(rule, options) {
                        var $dateFormat = rule.$el.find("#date-format");
                        $dateFormat.html(generateDateFormatSelect(options.availableFormats(rule.operator)));
                        $dateFormat.change();
                        $dateFormat.trigger("change-date-format");
                    },
                    valueSetter: function(rule, values) {
                        var valuesCopy = values.slice(0);
                        var $todayCheckbox = rule.$el.find("input[name=today]");
                        var $offsetLabel = rule.$el.find("#date-offset-label");
                        var $dateFormat = rule.$el.find("#date-format");
                        var isToday = false, operator, dateFormat, value;
                        if (values.length > MIN_EXPECTED_SIZE) {
                            if (valuesCopy.shift() === "today") {
                                isToday = true;
                            }
                            value = valuesCopy.shift();
                            operator = valuesCopy.shift();
                            dateFormat = valuesCopy.shift();
                        } else {
                            value = valuesCopy.shift();
                            if (value === "today") {
                                isToday = true;
                                value = "+0";
                            }
                            dateFormat = valuesCopy.shift();
                        }
                        $offsetLabel.toggle(isToday);
                        updateValue(rule, value, operator);
                        $dateFormat.val(dateFormat);
                        $todayCheckbox.prop("checked", isToday).change();
                    },
                    valueGetter: function(rule) {
                        var dateValue = [], value = rule.$el.find("#date-filter").val(), dateFormat = rule.$el.find("#date-format").val(), today = rule.$el.find("input[name=today]").is(":checked");
                        if (today) {
                            dateValue.push("today");
                            dateValue.push(value);
                            addOperator(value, dateValue);
                        } else {
                            dateValue.push(value);
                        }
                        dateValue.push(dateFormat);
                        return dateValue;
                    },
                    validate: function(values) {
                        if (values.length == 2) {
                            var date = values[0];
                            var format = values[1];
                            if (date) {
                                if ("today" != date && format) {
                                    return validateDateFormat(date, format.toUpperCase()) ? true : [ "invalid_format" ];
                                } else {
                                    return true;
                                }
                            } else {
                                return [ "empty_date" ];
                            }
                        } else if (values.length == 4) {
                            var delta = values[1];
                            if (!delta || delta != parseInt(delta)) {
                                return [ "invalid_expression" ];
                            }
                        }
                        return true;
                    }
                }
            },
            clearInitialRuleSettings: function() {
                var self = this;
                self.initialRule = false;
                $(".initial-rule").removeClass("initial-rule");
            },
            isInitial: function(root) {
                if (root.length === 1 && root[0].$el.hasClass("initial-rule")) {
                    return true;
                }
                if (this.initialRule && root.length === 1) {
                    root[0].$el.addClass("initial-rule");
                    return true;
                }
                return false;
            },
            validate: function(options) {
                var self = this;
                var root = self.model.root.rules;
                var validationOptions = _.clone(options);
                validationOptions = $.extend({
                    skip_filter_validation: true,
                    skip_empty: false
                }, validationOptions);
                if (validationOptions.skip_filter_validation) {
                    validationOptions.skip_empty = true;
                }
                if (this.isInitial(root)) {
                    self.clearErrors();
                    return true;
                }
                self.clearInitialRuleSettings();
                return originalValidate.call(this, validationOptions);
            },
            getRuleInput: function(rule, value_id) {
                var filter = rule.filter;
                var validation = rule.filter.validation || {};
                var name = rule.id + "_value_" + value_id;
                var c = filter.vertical ? " class=block" : "";
                var h = "";
                if (typeof filter.input === "function") {
                    h = filter.input.call(this, rule, name);
                } else if (typeof rule.operator.input === "function") {
                    h = rule.operator.input.call(this, rule, name);
                } else if (this.optionsByType[rule.filter.type] && typeof this.optionsByType[rule.filter.type].input === "function") {
                    h = this.optionsByType[rule.filter.type].input.call(this, rule, this.optionsByType[rule.filter.type], name);
                } else {
                    switch (filter.input) {
                      case "radio":
                      case "checkbox":
                        Utils.iterateOptions(filter.values, function(key, val) {
                            h += "<label" + c + '><input type="' + filter.input + '" name="' + name + '" value="' + key + '"> ' + val + "</label> ";
                        });
                        break;

                      case "select":
                        h = this.getRuleValueSelect(name, rule);
                        break;

                      case "textarea":
                        h += '<textarea class="form-control" name="' + name + '"';
                        if (filter.size) h += ' cols="' + filter.size + '"';
                        if (filter.rows) h += ' rows="' + filter.rows + '"';
                        if (validation.min !== undefined) h += ' minlength="' + validation.min + '"';
                        if (validation.max !== undefined) h += ' maxlength="' + validation.max + '"';
                        if (filter.placeholder) h += ' placeholder="' + filter.placeholder + '"';
                        h += "></textarea>";
                        break;

                      case "number":
                        h += '<input class="form-control" type="number" name="' + name + '"';
                        if (validation.step !== undefined) h += ' step="' + validation.step + '"';
                        if (validation.min !== undefined) h += ' min="' + validation.min + '"';
                        if (validation.max !== undefined) h += ' max="' + validation.max + '"';
                        if (filter.placeholder) h += ' placeholder="' + filter.placeholder + '"';
                        if (filter.size) h += ' size="' + filter.size + '"';
                        h += ">";
                        break;

                      default:
                        h += '<input class="form-control" type="text" name="' + name + '"';
                        if (filter.placeholder) h += ' placeholder="' + filter.placeholder + '"';
                        if (filter.type === "string" && validation.min !== undefined) h += ' minlength="' + validation.min + '"';
                        if (filter.type === "string" && validation.max !== undefined) h += ' maxlength="' + validation.max + '"';
                        if (filter.size) h += ' size="' + filter.size + '"';
                        h += ">";
                    }
                }
                return this.change("getRuleInput", h, rule, name);
            },
            getRuleValueSelect: function(name, rule) {
                var h = this.templates.ruleValueSelect({
                    builder: this,
                    name: name,
                    rule: rule,
                    icons: this.icons,
                    settings: this.settings,
                    translate: this.translate.bind(this)
                });
                return this.change("getRuleValueSelect", h, name, rule);
            },
            updateRuleOperator: function(rule, previousOperator) {
                var $valueContainer = rule.$el.find(Selectors.value_container);
                if (!rule.operator || rule.operator.nb_inputs === 0) {
                    $valueContainer.hide();
                    rule.__.value = undefined;
                } else {
                    $valueContainer.css("display", "");
                    if ($valueContainer.is(":empty") || !previousOperator || typeof previousOperator.input === "function" || typeof rule.operator.input === "function" || rule.operator.nb_inputs !== previousOperator.nb_inputs || rule.operator.optgroup !== previousOperator.optgroup) {
                        this.createRuleInput(rule);
                    }
                }
                if (rule.operator) {
                    rule.$el.find(Selectors.rule_operator).val(rule.operator.type);
                    rule.__.value = this.getRuleInputValue(rule);
                    this.createExtendedOperatorConditions(rule);
                }
                this.trigger("afterUpdateRuleOperator", rule, previousOperator);
                this.trigger("rulesChanged");
            },
            createExtendedOperatorConditions: function(rule) {
                var self = this;
                var operatorConditionsContainer = rule.$el.find(Selectors.rule_operator_conditions_container);
                if (rule.operator.type === "not_equal") {
                    rule.includeEmpty = true;
                    var $condition = $('<div class="qb-input-label">' + '<label class="checkbox-inline">' + '<input type="checkbox" class="rule-include-empty" name="' + rule.id + '_include_empty" checked="checked"/>' + '<span class="text">' + t("querybuilder.common.include_empty") + "</span>" + "</label>" + "</div>");
                    operatorConditionsContainer.html($condition);
                    var $checkbox = $condition.find(Selectors.rule_include_empty);
                    $checkbox.on("change", function() {
                        rule.includeEmpty = self.getRuleIncludeEmptyValue(rule);
                    });
                    rule.$el.find(Selectors.rule_header_inputs).prop("disabled", rule.flags.header_readonly);
                } else {
                    rule.includeEmpty = false;
                    operatorConditionsContainer.html("");
                }
            },
            createRuleOperators: function(rule) {
                var $operatorContainer = rule.$el.find(Selectors.operator_container).empty();
                if (!rule.filter) {
                    return;
                }
                var operators = this.getOperators(rule.filter);
                if (!rule.filter.skipOperator) {
                    var $operatorSelect = $(this.getRuleOperatorSelect(rule, operators));
                    $operatorContainer.html($operatorSelect);
                }
                if (rule.filter.default_operator) {
                    rule.__.operator = this.getOperatorByType(rule.filter.default_operator);
                } else {
                    rule.__.operator = operators[0];
                }
                rule.$el.find(Selectors.rule_operator).val(rule.operator.type);
                this.trigger("afterCreateRuleOperators", rule, operators);
                this.applyRuleFlags(rule);
            },
            createRuleInput: function(rule) {
                var $valueContainer = rule.$el.find(Selectors.value_container).empty();
                rule.__.value = undefined;
                if (!rule.filter || !rule.operator || rule.operator.nb_inputs === 0) {
                    return;
                }
                var self = this;
                var $inputs = $();
                var filter = rule.filter;
                for (var i = 0; i < rule.operator.nb_inputs; i++) {
                    var $ruleInput = $(this.getRuleInput(rule, i));
                    if (filter.canBeNegated) {
                        var $negateInput = self.getNegateInput();
                        $valueContainer.prepend($negateInput);
                        $inputs = $inputs.add($negateInput);
                    }
                    if (i > 0) $valueContainer.append(this.settings.inputs_separator);
                    $valueContainer.append($ruleInput);
                    if (typeof filter.values === "function") {
                        filter.values.call(this, $ruleInput);
                    }
                    $inputs = $inputs.add($ruleInput);
                }
                $valueContainer.css("display", "");
                $inputs.on("change " + (filter.input_event || ""), function() {
                    if (!rule._updating_input) {
                        rule._updating_value = true;
                        rule.negated = self.getNegateValue(rule);
                        rule.value = self.getRuleInputValue(rule);
                        rule._updating_value = false;
                    }
                });
                if (filter.plugin) {
                    $inputs[filter.plugin](filter.plugin_config || {});
                }
                this.trigger("afterCreateRuleInput", rule);
                if (filter.default_value !== undefined) {
                    rule.value = filter.default_value;
                } else {
                    rule._updating_value = true;
                    rule.negated = self.getNegateValue(rule);
                    rule.value = self.getRuleInputValue(rule);
                    rule._updating_value = false;
                }
                this.applyRuleFlags(rule);
            },
            setRuleInputValue: function(rule, value) {
                var filter = rule.filter;
                var operator = rule.operator;
                if (!filter || !operator) {
                    return;
                }
                rule._updating_input = true;
                if (filter.valueSetter) {
                    filter.valueSetter.call(this, rule, value);
                } else if (typeof rule.operator.valueSetter === "function") {
                    rule.operator.valueSetter.call(this, rule, value);
                } else if (this.optionsByType[rule.filter.type] && typeof this.optionsByType[rule.filter.type].valueSetter === "function") {
                    this.optionsByType[rule.filter.type].valueSetter.call(this, rule, value);
                } else {
                    var $value = rule.$el.find(Selectors.value_container);
                    if (operator.nb_inputs === 1) {
                        value = [ value ];
                    }
                    for (var i = 0; i < operator.nb_inputs; i++) {
                        var name = Utils.escapeElementId(rule.id + "_value_" + i);
                        switch (filter.input) {
                          case "radio":
                            $value.find("[name=" + name + '][value="' + value[i] + '"]').prop("checked", true).trigger("change");
                            break;

                          case "checkbox":
                            if (!$.isArray(value[i])) {
                                value[i] = [ value[i] ];
                            }
                            value[i].forEach(function(value) {
                                $value.find("[name=" + name + '][value="' + value + '"]').prop("checked", true).trigger("change");
                            });
                            break;

                          default:
                            if (operator.multiple && filter.value_separator && $.isArray(value[i])) {
                                value[i] = value[i].join(filter.value_separator);
                            }
                            $value.find("[name=" + name + "]").val(value[i]).trigger("change");
                            break;
                        }
                    }
                }
                this.setNegated(rule);
                rule._updating_input = false;
            },
            getRuleInputValue: function(rule) {
                var filter = rule.filter;
                var operator = rule.operator;
                var value = [];
                if (filter.valueGetter) {
                    value = filter.valueGetter.call(this, rule);
                } else if (typeof rule.operator.valueGetter === "function") {
                    value = rule.operator.valueGetter.call(this, rule);
                } else if (this.optionsByType[rule.filter.type] && typeof this.optionsByType[rule.filter.type].valueGetter === "function") {
                    value = this.optionsByType[rule.filter.type].valueGetter.call(this, rule);
                } else {
                    var $value = rule.$el.find(Selectors.value_container);
                    for (var i = 0; i < operator.nb_inputs; i++) {
                        var name = Utils.escapeElementId(rule.id + "_value_" + i);
                        var tmp;
                        switch (filter.input) {
                          case "radio":
                            value.push($value.find("[name=" + name + "]:checked").val());
                            break;

                          case "checkbox":
                            tmp = [];
                            $value.find("[name=" + name + "]:checked").each(function() {
                                tmp.push($(this).val());
                            });
                            value.push(tmp);
                            break;

                          case "select":
                            if (filter.multiple) {
                                tmp = [];
                                $value.find("[name=" + name + "] option:selected").each(function() {
                                    tmp.push($(this).val());
                                });
                                value.push(tmp);
                            } else {
                                value.push($value.find("[name=" + name + "] option:selected").val());
                            }
                            break;

                          default:
                            value.push($value.find("[name=" + name + "]").val());
                        }
                    }
                    value = value.map(function(val) {
                        if (operator.multiple && filter.value_separator && typeof val == "string") {
                            val = val.split(filter.value_separator);
                        }
                        if ($.isArray(val)) {
                            return val.map(function(subval) {
                                return Utils.changeType(subval, filter.type);
                            });
                        } else {
                            return Utils.changeType(val, filter.type);
                        }
                    });
                    if (operator.nb_inputs === 1) {
                        value = value[0];
                    }
                    if (filter.valueParser) {
                        value = filter.valueParser.call(this, rule, value);
                    }
                }
                return this.change("getRuleValue", value, rule);
            },
            getRuleIncludeEmptyValue: function(rule) {
                return rule.$el.find(Selectors.rule_include_empty).is(":checked");
            },
            validateValue: function(rule, value) {
                var validation = rule.filter.validation || {};
                var result = true;
                if (validation.callback) {
                    result = validation.callback.call(this, value, rule);
                } else if (typeof rule.operator.validate === "function") {
                    result = rule.operator.validate.call(this, value, rule);
                } else if (this.optionsByType[rule.filter.type] && typeof this.optionsByType[rule.filter.type].validate === "function") {
                    result = this.optionsByType[rule.filter.type].validate.call(this, value, rule);
                } else {
                    result = this._validateValue(rule, value);
                }
                return this.change("validateValue", result, value, rule);
            },
            getRules: function(options) {
                options = $.extend({
                    get_flags: false,
                    allow_invalid: false,
                    skip_empty: false
                }, options);
                var valid = this.validate(options);
                if (!valid && !options.allow_invalid) {
                    return null;
                }
                var self = this;
                var out = function parse(group) {
                    var groupData = {
                        condition: group.condition,
                        rules: []
                    };
                    if (group.data) {
                        groupData.data = $.extendext(true, "replace", {}, group.data);
                    }
                    if (options.get_flags) {
                        var flags = self.getGroupFlags(group.flags, options.get_flags === "all");
                        if (!$.isEmptyObject(flags)) {
                            groupData.flags = flags;
                        }
                    }
                    group.each(function(rule) {
                        if (!rule.filter && options.skip_empty) {
                            return;
                        }
                        var value = null;
                        if (!rule.operator || rule.operator.nb_inputs !== 0) {
                            value = rule.value;
                        }
                        var ruleData = {
                            id: rule.filter ? rule.filter.id : null,
                            field: rule.filter ? rule.filter.field : null,
                            type: rule.filter ? rule.filter.type : null,
                            input: rule.filter ? rule.filter.input : null,
                            operator: rule.operator ? rule.operator.type : null,
                            value: value,
                            includeEmpty: rule.includeEmpty
                        };
                        if (rule.filter && rule.filter.data || rule.data) {
                            ruleData.data = $.extendext(true, "replace", {}, rule.filter.data, rule.data);
                        }
                        if (rule.filter && rule.filter.canBeNegated) {
                            ruleData.negated = rule.negated;
                        }
                        if (options.get_flags) {
                            var flags = self.getRuleFlags(rule.flags, options.get_flags === "all");
                            if (!$.isEmptyObject(flags)) {
                                ruleData.flags = flags;
                            }
                        }
                        groupData.rules.push(self.change("ruleToJson", ruleData, rule));
                    }, function(model) {
                        var data = parse(model);
                        if (data.rules.length !== 0 || !options.skip_empty) {
                            groupData.rules.push(data);
                        }
                    }, this);
                    return self.change("groupToJson", groupData, group);
                }(this.model.root);
                out.valid = valid;
                return this.change("getRules", out);
            },
            setRules: function(data, options) {
                options = $.extend({
                    allow_invalid: false
                }, options);
                this.setupInitialRule(data);
                if ($.isArray(data)) {
                    data = {
                        condition: this.settings.default_condition,
                        rules: data
                    };
                }
                if (!data || !data.rules || data.rules.length === 0 && !this.settings.allow_empty) {
                    Utils.error("RulesParse", "Incorrect data object passed");
                }
                this.clear();
                this.setRoot(false, data.data, this.parseGroupFlags(data));
                this.applyGroupFlags(this.model.root);
                data = this.change("setRules", data, options);
                var self = this;
                (function add(data, group) {
                    if (group === null) {
                        return;
                    }
                    if (data.condition === undefined) {
                        data.condition = self.settings.default_condition;
                    } else if (self.settings.conditions.indexOf(data.condition) == -1) {
                        Utils.error(!options.allow_invalid, "UndefinedCondition", 'Invalid condition "{0}"', data.condition);
                        data.condition = self.settings.default_condition;
                    }
                    group.condition = data.condition;
                    data.rules.forEach(function(item) {
                        var model;
                        if (item.rules !== undefined) {
                            if (self.settings.allow_groups !== -1 && self.settings.allow_groups < group.level) {
                                Utils.error(!options.allow_invalid, "RulesParse", "No more than {0} groups are allowed", self.settings.allow_groups);
                                self.reset();
                            } else {
                                model = self.addGroup(group, false, item.data, self.parseGroupFlags(item));
                                if (model === null) {
                                    return;
                                }
                                self.applyGroupFlags(model);
                                add(item, model);
                            }
                        } else {
                            if (!item.empty) {
                                if (item.id === undefined) {
                                    Utils.error(!options.allow_invalid, "RulesParse", "Missing rule field id");
                                    item.empty = true;
                                }
                                if (item.operator === undefined) {
                                    item.operator = "equal";
                                }
                            }
                            model = self.addRule(group, item.data, self.parseRuleFlags(item));
                            if (model === null) {
                                return;
                            }
                            if (item.id) {
                                if (!item.empty) {
                                    model.filter = self.getFilterById(item.id, !options.allow_invalid);
                                }
                                if (model.filter) {
                                    model.operator = self.getOperatorByType(item.operator, !options.allow_invalid);
                                    if (!model.operator) {
                                        model.operator = self.getOperators(model.filter)[0];
                                    }
                                }
                                model.negated = item.negated;
                                if (model.operator && model.operator.nb_inputs !== 0) {
                                    model.includeEmpty = !!item.includeEmpty;
                                    if (item.value !== undefined) {
                                        model.value = item.value;
                                    } else if (model.filter.default_value !== undefined) {
                                        model.value = model.filter.default_value;
                                    }
                                }
                            }
                            if (self.change("jsonToRule", model, item) != model) {
                                Utils.error("RulesParse", "Plugin tried to change rule reference");
                            }
                        }
                    });
                    if (self.change("jsonToGroup", group, data) != group) {
                        Utils.error("RulesParse", "Plugin tried to change group reference");
                    }
                })(data, this.model.root);
                this.validate();
                this.trigger("afterSetRules");
            },
            getNegateValue: function(rule) {
                var $negateInput = rule.$el.find("select.negate"), result;
                if ($negateInput.length !== 0) {
                    result = $negateInput.val() === "true";
                }
                return result;
            },
            getNegateInput: function() {
                var negationSelect = '<div class="qb-input-negate">' + '<select class="form-control negate">' + '<option value="false">' + t("defaults.yes") + "</option>" + '<option value="true">' + t("defaults.no") + "</option>" + "</select>" + "</div>";
                return $(negationSelect);
            },
            setNegated: function(rule) {
                var negateSelect = rule.$el.find("select.negate");
                if (negateSelect.length !== 0) {
                    negateSelect.val("" + rule.negated);
                }
            },
            displayError: function(node) {
                if (this.settings.display_errors) {
                    if (node.error === null) {
                        node.$el.removeClass("has-error");
                    } else {
                        var errorMessage = this.translate("errors", node.error[0]);
                        errorMessage = this.constructor.utils.fmt(errorMessage, node.error.slice(1));
                        errorMessage = this.change("displayError", errorMessage, node.error, node);
                        node.$el.addClass("has-error").find(this.constructor.selectors.error_container).eq(0).attr("data-tooltip", errorMessage);
                        AGN.Lib.CoreInitializer.run("tooltip", node.$el);
                    }
                }
            },
            bindEvents: function() {
                originalBindEvents.call(this);
                var self = this;
                this.model.on("update", function(e, node, field) {
                    if (node instanceof QueryBuilderConstructor.Rule && field === "includeEmpty") {
                        self.updateRuleIncludeEmpty(node);
                    }
                });
            },
            findRuleByField: function(root, id, recursively) {
                var isGroup = function(node) {
                    return node.hasOwnProperty("rules");
                };
                if (isGroup(root)) {
                    var self = this;
                    return root.rules.find(function(node) {
                        if (isGroup(node)) {
                            return recursively ? self.findRuleByField(node, recursively) : false;
                        } else {
                            return node.field && node.field === id;
                        }
                    });
                } else {
                    return root.field && root.field === id;
                }
            },
            deleteRuleByField: function(root, id, recursively) {
                var self = this;
                if (!root) {
                    root = self.model.root;
                    if (!root) {
                        return;
                    }
                }
                var del = false;
                root.each("reverse", function(rule) {
                    if (rule && rule.filter && rule.filter.id == id) {
                        del &= self.deleteRule(self.getModel(rule.$el));
                    }
                }, function(group) {
                    del &= self.deleteRuleByField(group, id, recursively);
                }, self);
                return !!del;
            },
            setOrReplaceRule: function(rules, rule, recursively) {
                if (!rules) {
                    rules = this.getRules({
                        allow_invalid: true,
                        skip_empty: true
                    });
                }
                if (rule && rule.id) {
                    var foundRule = this.findRuleByField(rules, rule.id, recursively);
                    if (foundRule) {
                        $.extend(foundRule, rule);
                    } else {
                        rules.rules.push(rule);
                    }
                    this.setRules(rules);
                    return true;
                } else {
                    return false;
                }
            },
            containsNotEmptyRule: function(target) {
                var self = this;
                var model = self.getModel(target);
                if (model.rules && model.rules.length) {
                    return model.rules.every(function(node) {
                        if (node.hasOwnProperty("rules")) {
                            return self.containsNotEmptyRule(node);
                        } else {
                            return !!node.filter;
                        }
                    });
                } else {
                    return !!model.filter;
                }
            }
        });
        QueryBuilderConstructor.prototype.updateRuleIncludeEmpty = function(rule) {
            var $includeEmptyCheckbox = rule.$el.find(Selectors.rule_include_empty);
            $includeEmptyCheckbox.prop("checked", rule.includeEmpty);
            this.trigger("rulesChanged");
        };
    });
    function generateDateFormatSelect(availableFormats) {
        var resultMarkup = [];
        availableFormats.forEach(function(element) {
            var $option = $("<option />");
            $option.text(t("date.formats." + element));
            $option.val(element);
            resultMarkup.push($("<div/>").append($option).html());
        });
        return resultMarkup.join("");
    }
    function formatDate(date, format) {
        return format.replace("DD", AGN.Lib.Helpers.pad(date.getDate(), 2)).replace("MM", AGN.Lib.Helpers.pad(date.getMonth() + 1, 2)).replace("YYYY", AGN.Lib.Helpers.pad(date.getFullYear(), 4));
    }
    function validateDateFormat(date, format) {
        if (!date) {
            return false;
        }
        var fragments = getDateFormatFragments(format);
        if (fragments) {
            for (var i = 0; i < fragments.length; i++) {
                var fragment = fragments[i];
                if (fragment.isDigitFragment) {
                    if (fragment.isLenient) {
                        var match = date.match("^\\d{1," + fragment.lexeme.length + "}");
                        if (match) {
                            date = date.substring(match[0].length);
                        } else {
                            return false;
                        }
                    } else {
                        if (date.length < fragment.lexeme.length) {
                            return false;
                        }
                        if (!date.substr(0, fragment.lexeme.length).match(/^\d+$/)) {
                            return false;
                        }
                        date = date.substring(fragment.lexeme.length);
                    }
                } else {
                    if (date.startsWith(fragment.lexeme)) {
                        date = date.substring(fragment.lexeme.length);
                    } else {
                        return false;
                    }
                }
            }
            return !date;
        }
        return false;
    }
    function getDateFormatFragment(format) {
        var fragments = [ "DD", "MM", "YYYY", ".", "-", "_" ];
        if (format) {
            for (var i = 0; i < fragments.length; i++) {
                if (format.startsWith(fragments[i])) {
                    return fragments[i];
                }
            }
        }
        return false;
    }
    function getDateFormatFragments(format) {
        var digitFragments = [ "DD", "MM", "YYYY" ];
        var fragments = [];
        while (format) {
            var fragmentLexeme = getDateFormatFragment(format);
            if (fragmentLexeme) {
                var isDigitFragment = false;
                var isLenient = false;
                if (digitFragments.includes(fragmentLexeme)) {
                    isDigitFragment = true;
                    isLenient = true;
                    if (fragments.length) {
                        var previousFragment = fragments[fragments.length - 1];
                        if (previousFragment.isDigitFragment) {
                            previousFragment.isLenient = false;
                            isLenient = false;
                        }
                    }
                }
                fragments.push({
                    lexeme: fragmentLexeme,
                    isDigitFragment: isDigitFragment,
                    isLenient: isLenient
                });
            } else {
                return false;
            }
            format = format.substring(fragmentLexeme.length);
        }
        return fragments.length ? fragments : false;
    }
})();

(function() {
    var MISSING_VALUE_MARK = "---";
    var MIN_VALUE_THRESHOLD = .01;
    var LOW_VALUE_MARK = "< 1";
    var LOW_VALUE = .001;
    var REACTION_GRADE_COLORS = {
        HIGH_PERFORMER: "#008F00",
        OPPORTUNITY: "#92D050",
        LEAD: "#CCCDCD",
        SLEEPER: "#F43536"
    };
    var REVENUE_GRADE_CASH_COW = 500;
    var REVENUE_GRADE_RISING_STAR = 150;
    var REVENUE_ICON_POOR_DOG = "poor-dog";
    var REVENUE_ICON_QUESTION_MARK = "question-mark";
    var REVENUE_ICON_RISING_STAR = "rising-star";
    var REVENUE_ICON_CASH_COW = "cash-cow";
    AGN.Lib.DomInitializer.new("recipient-insights", function() {
        var config = this.config;
        var data = this.config.insightsData;
        $.i18n.load(config.translations);
        showWeekdayReactionRankChart(data.weekdayReactionRankData);
        showHourReactionRankChart(data.hourReactionRankData);
        showMailingsRevenueRatingChart(data.mailingsRevenueRatingData, config.mailingUriPattern, config.localeLanguage);
        showReactionsInProgressChart(data.reactionsInProgressData);
        showReactionDeviceRankChart(data.reactionDeviceRankData);
        showMailingReactionPercentage(data.mailingReactionPercentageData);
        showCustomerRevenue(data.customerRevenueData);
        showCustomerPerformance(data.customerPerformanceData);
        showPageImpressions(data.pageImpressionsData);
        this.addAction({
            change: "selectReactionProgressPeriodType"
        }, function() {
            $("#reactionProgressPeriodDates").toggleClass("hidden", "CUSTOM" !== this.el.val());
        });
        this.addAction({
            click: "selectReactionProgressPeriod"
        }, function() {
            var $type = $('input[name="reactionProgressPeriod"]:checked');
            var min, max;
            switch ($type.val()) {
              case "YEAR":
              case "MONTH":
                min = $type.data("min");
                max = $type.data("max");
                break;

              case "CUSTOM":
                min = $("#reactionProgressMinDate").val();
                max = $("#reactionProgressMaxDate").val();
                break;

              default:
                console.error("Unexpected period type: `" + $type.val() + "`");
                return;
            }
            if (min && max) {
                $.ajax(config.urls.reactionsInProgress, {
                    type: "GET",
                    data: {
                        customerId: config.customerId,
                        min: min,
                        max: max
                    }
                }).done(function(data) {
                    showReactionsInProgressChart(data);
                });
            } else {
                AGN.Lib.Messages(t("defaults.error"), t("defaults.error"), "alert");
            }
        });
    });
    function asRankChartData(data) {
        var values = [ "data1" ];
        var percentages = [];
        var maxValue = 0;
        $.each(data.values, function(key, value) {
            if (value > maxValue) {
                maxValue = value;
            }
            values.push(value);
            percentages.push(data.percentages[key]);
        });
        return {
            values: values,
            percentages: percentages,
            maxValue: maxValue
        };
    }
    function setPaddingForAxisX($$, extraPadding) {
        $($$.axes.x[0]).find(".tick text").attr("y", function(index, value) {
            return parseInt(value || 0) + extraPadding;
        });
    }
    function showWeekdayReactionRankChart(data) {
        data = asRankChartData(data);
        var chartTitle = t("recipient.reaction.day");
        var categories = t("date.weekdaysShort");
        c3.generate({
            bindto: "#reaction-weekday-chart",
            onrendered: function() {
                setPaddingForAxisX(this, 10);
            },
            size: {
                height: 200
            },
            data: {
                type: "bar",
                columns: [ data.values ],
                labels: {
                    format: {
                        data1: function(v, id, index) {
                            return data.percentages[index] + "%";
                        }
                    }
                },
                color: function(color, d) {
                    return d.value === data.maxValue ? "#0071b9" : "#eaeaea";
                }
            },
            bar: {
                width: {
                    ratio: .88
                }
            },
            legend: {
                show: false
            },
            tooltip: {
                format: {
                    name: function() {
                        return chartTitle;
                    }
                }
            },
            axis: {
                x: {
                    type: "category",
                    categories: categories,
                    tick: {
                        outer: false
                    }
                },
                y: {
                    show: false,
                    padding: {
                        top: 20,
                        bottom: 20
                    }
                }
            }
        });
    }
    function showHourReactionRankChart(data) {
        data = asRankChartData(data);
        var categories = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 ];
        c3.generate({
            bindto: "#reaction-hour-chart",
            onrendered: function() {
                setPaddingForAxisX(this, 10);
            },
            size: {
                height: 200
            },
            data: {
                type: "bar",
                columns: [ data.values ],
                labels: {
                    format: {
                        data1: function(v, id, index) {
                            return data.percentages[index] + "%";
                        }
                    }
                },
                color: function(color, d) {
                    return d.value === data.maxValue ? "#0071b9" : "#eaeaea";
                },
                onmouseover: function(d) {
                    this.internal.mainText.style("visibility", function(label) {
                        return d.index === label.index ? "visible" : "hidden";
                    });
                },
                onmouseout: function(d) {
                    this.internal.mainText.filter(function(label) {
                        return d.index === label.index;
                    }).style("visibility", "hidden");
                }
            },
            bar: {
                width: {
                    ratio: .7
                }
            },
            legend: {
                show: false
            },
            tooltip: {
                show: false
            },
            axis: {
                x: {
                    type: "category",
                    categories: categories,
                    tick: {
                        multiline: false,
                        centered: true,
                        outer: false
                    }
                },
                y: {
                    show: false,
                    padding: {
                        top: 20,
                        bottom: 20
                    }
                }
            }
        });
    }
    function extractRowDataWithLocale(locale) {
        var format;
        if (locale === "de") {
            var d3_locale_deDe = d3.locale({
                decimal: ",",
                thousands: ".",
                grouping: [ 3 ],
                currency: [ "" ],
                dateTime: "%a %b %e %X %Y",
                date: "%m/%d/%Y",
                time: "%H:%M:%S",
                periods: [ "AM", "PM" ],
                days: [ "Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag" ],
                shortDays: [ "So", "Mo", "Di", "Mi", "Do", "Fr", "Sa" ],
                months: [ "Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember" ],
                shortMonths: [ "Jan", "Feb", "Mar", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ]
            });
            format = d3_locale_deDe.numberFormat;
        } else {
            format = d3.format;
        }
        return function(d) {
            return [ {
                text: d.date,
                classes: "l-revenue-date"
            }, {
                text: format(",.2f")(d.revenue),
                classes: "l-revenue-value"
            }, {
                text: d.name,
                mailingId: d.mailingId,
                classes: "l-revenue-name"
            } ];
        };
    }
    function showMailingsRevenueRatingChart(data, mailingUriPattern, locale) {
        var headersData = [ {
            title: t("mailing.senddate"),
            criterion: "timestamp",
            sorting: false
        }, {
            title: t("statistic.revenue"),
            criterion: "revenue",
            sorting: false
        }, {
            title: t("Mailing"),
            criterion: "name",
            sorting: false
        } ];
        var extractRowData = extractRowDataWithLocale(locale);
        var getSortingIconClasses = function(d) {
            if (d.sorting === "asc") {
                return "icon icon-arrow-down";
            } else if (d.sorting === "desc") {
                return "icon icon-arrow-up";
            }
            return "hidden";
        };
        var changeSorting = $.noop;
        var table = d3.select("#mailings-revenue-rating-table").append("table");
        var headers = table.append("thead").append("tr").selectAll("th").data(headersData).enter().append("th");
        headers.append("span").on("click", function(d) {
            changeSorting(d);
        }).attr("class", "clickable unselectable").html(function(d) {
            return d.title + "&nbsp;";
        });
        var sortingIcons = headers.append("i").attr("class", getSortingIconClasses);
        if (data.length) {
            var rows = table.append("tbody").selectAll("tr").data(data).enter().append("tr");
            var cells = rows.selectAll("td").data(extractRowData).enter().append("td").attr("class", function(d) {
                return d.classes;
            });
            cells.filter(function(d) {
                return !d.mailingId;
            }).text(function(d) {
                return d.text;
            });
            cells.filter(function(d) {
                return d.mailingId > 0;
            }).append("a").attr("href", function(d) {
                return mailingUriPattern.replace(":mailing-id:", d.mailingId);
            }).attr("title", function(d) {
                return d.text;
            }).text(function(d) {
                return d.text;
            });
            changeSorting = function(chosen) {
                sortingIcons.attr("class", function(d) {
                    if (d === chosen) {
                        d.sorting = d.sorting === "asc" ? "desc" : "asc";
                    } else {
                        d.sorting = false;
                    }
                    return getSortingIconClasses(d);
                });
                var compare = chosen.sorting === "desc" ? d3.descending : d3.ascending;
                rows.sort(function(a, b) {
                    return compare(a[chosen.criterion], b[chosen.criterion]);
                });
            };
        } else {
            rows = table.append("tbody").append("tr").append("td").attr("colspan", 3).attr("class", "l-revenue-unavailable").text(t("recipient.chart.not_available"));
        }
    }
    function showReactionsInProgressChart(data) {
        var reactionsKey = t("statistic.reactions");
        var impressionsKey = t("statistic.impressions");
        var revenuesKey = t("statistic.revenue");
        var colorsMap = {};
        colorsMap[reactionsKey] = "#99c6e3";
        colorsMap[impressionsKey] = "#f43536";
        colorsMap[revenuesKey] = "#0071b9";
        var categories = [];
        var reactions = [ reactionsKey ];
        var impressions = [ impressionsKey ];
        var revenues = [ revenuesKey ];
        var isImpressionAvailable = false;
        var isRevenueAvailable = false;
        $.each(data.values, function(date, d) {
            categories.push(date);
            reactions.push(d.reactions);
            impressions.push(d.impressions);
            revenues.push(d.revenues);
            if (d.impressions > 0) {
                isImpressionAvailable = true;
            }
            if (d.revenues > 0) {
                isRevenueAvailable = true;
            }
        });
        var columns = [ reactions ];
        var types = {
            reactions: "area"
        };
        if (isImpressionAvailable) {
            columns.push(impressions);
            types.impressions = "area";
        }
        if (isRevenueAvailable) {
            columns.push(revenues);
            types.revenues = "bar";
        }
        var mailingNames = data.mailingNames;
        var count = categories.length;
        var pointSize = 3;
        if (count < 60) {
            pointSize = 5;
        } else if (count < 100) {
            pointSize = 4;
        }
        c3.generate({
            bindto: "#reaction-progress-chart",
            onrendered: function() {
                setPaddingForAxisX(this, 10);
            },
            size: {
                height: 200
            },
            data: {
                columns: columns,
                types: types,
                color: function(color, d) {
                    return colorsMap[d.id ? d.id : d] || color;
                }
            },
            tooltip: {
                format: {
                    title: function(index) {
                        var date = categories[index];
                        var mailingIds = data.values[date].mailingIds;
                        if (mailingIds.length) {
                            return mailingNames[mailingIds[0]];
                        } else {
                            return date;
                        }
                    }
                }
            },
            bar: {
                width: 10
            },
            point: {
                r: pointSize
            },
            axis: {
                x: {
                    type: "category",
                    categories: categories,
                    height: 40,
                    tick: {
                        multiline: false,
                        centered: true,
                        outer: false,
                        culling: true
                    }
                },
                y: {
                    show: false
                }
            }
        });
    }
    function showReactionDeviceRankChart(data) {
        var palette = [ "#0071B9", "#009BFF", "#64C3FF", "#00558A", "#92D050" ];
        var columns = [];
        var names = {};
        var percentages = {};
        var colors = {};
        $.each(data, function(index, d) {
            var id = "data" + index;
            columns.push([ id, d.value ]);
            names[id] = t(d.deviceClass);
            percentages[id] = d.percentage;
            colors[id] = palette[index];
        });
        c3.generate({
            bindto: "#reaction-device-chart",
            size: {
                height: 200
            },
            data: {
                columns: columns,
                type: "donut",
                names: names,
                color: function(color, d) {
                    return colors[d.id ? d.id : d] || color;
                }
            },
            donut: {
                label: {
                    format: function(value, fraction, id) {
                        return percentages[id] + "%";
                    }
                }
            },
            legend: {
                position: "right"
            },
            tooltip: {
                format: {
                    value: function(value, fraction, id) {
                        return value + " (" + percentages[id] + "%)";
                    }
                }
            }
        });
    }
    function showKpiValue(selector, value) {
        var $content = $(selector);
        var $value = $content.find(".l-kpi-value");
        var $sign = $content.find(".l-kpi-sign");
        if (value > 0) {
            if (value < MIN_VALUE_THRESHOLD) {
                $value.text(LOW_VALUE_MARK);
            } else {
                $value.text(d3.round(value, 2));
            }
        } else {
            $value.text(MISSING_VALUE_MARK);
        }
        $sign.toggle(value > 0);
    }
    function showMailingReactionPercentage(data) {
        showKpiValue("#reactionTypeKpi", data.percentage.percentage);
        $("#reactionGradeIcon").css("color", getActivityGradeColor(data.grade));
    }
    function showCustomerRevenue(data) {
        showKpiValue("#revenueSumKpi", data.value);
        showKpiValue("#revenueAvgKpi", data.average);
        $("#revenueIcon").addClass(getRevenueGradeIcon(data.value));
    }
    function showCustomerPerformance(data) {
        if (data.clicks.percentage > 0) {
            showKpiValue("#performanceClicksKpi", data.clicks.percentage);
        } else {
            showKpiValue("#performanceClicksKpi", data.clicks.value > 0 ? LOW_VALUE : 0);
        }
        showKpiValue("#performanceRevenueKpi", data.revenue);
    }
    function showPageImpressions(data) {
        showKpiValue("#impressionsByClickKpi", data.perClick);
        showKpiValue("#impressionsByVisitKpi", data.perVisit);
        showKpiValue("#impressionsByBuyKpi", data.perBuy);
    }
    function getActivityGradeColor(grade) {
        return REACTION_GRADE_COLORS[grade] || "inherit";
    }
    function getRevenueGradeIcon(value) {
        if (value >= REVENUE_GRADE_CASH_COW) {
            return REVENUE_ICON_CASH_COW;
        } else {
            if (value >= REVENUE_GRADE_RISING_STAR) {
                return REVENUE_ICON_RISING_STAR;
            } else {
                if (value > 0) {
                    return REVENUE_ICON_QUESTION_MARK;
                } else {
                    return REVENUE_ICON_POOR_DOG;
                }
            }
        }
    }
})();

(function() {
    AGN.Lib.DomInitializer.new("recipient-report-initializer", function($el) {
        initLogIframeBackground($el);
    });
    function initLogIframeBackground($scope) {
        if (!$("body").hasClass("dark-theme")) {
            return;
        }
        var $iframe = $scope.find("iframe");
        $iframe.on("load.iframe", function() {
            changeColorsToDarkTheme($iframe);
        });
        $iframe.ready(function() {
            changeColorsToDarkTheme($iframe);
        });
    }
    function changeColorsToDarkTheme($iframe) {
        var $body = $iframe.contents().find("body");
        var $center = $body.find("center");
        if ($center.length) {
            $body.css("background", "#303030");
            $center.css("background", "#303030");
        } else {
            $iframe.contents().find("body").css("color", "#ffffff");
        }
    }
})();

AGN.Lib.CoreInitializer.new("relative-href", function($scope) {
    if (!$scope) {
        $scope = $(document);
    }
    $scope.find("a[data-relative]").each(function() {
        var $a = $(this);
        $a.attr("href", AGN.url($a.attr("href")));
        $a.removeAttr("data-relative");
    });
});

(function() {
    AGN.Lib.CoreInitializer.new("scrollable", function($scope) {
        if (!$scope) {
            $scope = $(document);
        }
        _.each($scope.find(".js-scrollable"), function(el) {
            var $el = $(el);
            $el.perfectScrollbar("destroy");
            $el.perfectScrollbar({
                wheelSpeed: 5,
                scrollXMarginOffset: 1
            });
        });
    });
})();

(function() {
    var Popover = AGN.Lib.Popover, Template = AGN.Lib.Template, Page = AGN.Lib.Page;
    AGN.Lib.CoreInitializer.new("select", [ "template" ], function($scope) {
        if (!$scope) {
            $scope = $(document);
        }
        _.each($scope.all("select"), function(el) {
            var $el = $(el);
            var resultTemplateId = $el.data("result-template");
            if ($el.data("select2")) {
                $el.select2("destroy");
            }
            var options = {
                placeholder: $el.attr("placeholder"),
                minimumResultsForSearch: 10
            };
            if (!$el.hasClass("js-select") && !$el.hasClass("js-select-tags")) {
                options.minimumResultsForSearch = -1;
            }
            if ($el.hasClass("js-select-tags")) {
                options.inlineTags = true;
            }
            if ($el.is("[data-sort]")) {
                if ($el.data("sort") === "alphabetic") {
                    options.sortResults = function(results, container, query) {
                        return results.sort(function(a, b) {
                            if ($(a.element).is("[data-fix-position]")) {
                                return -1;
                            } else if ($(b.element).is("[data-fix-position]")) {
                                return 1;
                            }
                            return a.text.toLowerCase().localeCompare(b.text.toLowerCase());
                        });
                    };
                }
            }
            if ($el.prop("multiple")) {
                var selectionTemplateId = $el.data("selection-template");
                options.minimumResultsForSearch = 1;
                if (selectionTemplateId) {
                    var createSelection = Template.prepare(selectionTemplateId);
                    options.formatSelection = function(data) {
                        return createSelection({
                            element: data.element[0],
                            isLocked: data.locked,
                            isDisabled: data.disabled,
                            text: data.text,
                            value: data.id
                        });
                    };
                } else {
                    options.formatSelection = function(state) {
                        if (state.element && state.element.length === 1) {
                            var url = $(state.element).data("url");
                            if (url) {
                                return $("<a></a>", {
                                    href: url,
                                    text: state.text,
                                    click: function() {
                                        Page.reload(url);
                                    }
                                });
                            }
                        }
                        return state.text;
                    };
                }
            }
            if (resultTemplateId) {
                var createResult = Template.prepare(resultTemplateId);
                options.formatResult = function(data) {
                    return createResult({
                        element: data.element[0],
                        isLocked: data.locked,
                        isDisabled: data.disabled,
                        text: data.text,
                        value: data.id
                    });
                };
            } else if ($el.hasClass("js-option-popovers")) {
                options.formatResult = function(data, $label, query, escapeMarkup) {
                    var text = '<span style="white-space: nowrap;">' + escapeMarkup(data.text) + "</span>";
                    Popover.new($label, {
                        trigger: "hover",
                        delay: {
                            show: 300,
                            hide: 100
                        },
                        html: true,
                        template: '<div class="popover popover-wide" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>',
                        content: text
                    });
                    return text;
                };
                $el.on("select2-close", function() {
                    Popover.validate();
                });
            }
            var currentFormatSelection = options.formatSelection;
            options.formatSelection = function(data) {
                var text = data.text;
                if (text) {
                    data.text = text.trim();
                }
                if (currentFormatSelection instanceof Function) {
                    return currentFormatSelection.apply(this, arguments);
                }
                return $.fn.select2.defaults.formatSelection.apply(this, arguments);
            };
            $el.select2(options);
            var $exclusiveOption = $el.find("option[data-exclusive]");
            if ($exclusiveOption.length > 0) {
                $el.on("select2-selecting", function(e) {
                    var exclusiveIsChosen = $el.find("option[value='" + e.val + "'][data-exclusive]").length > 0;
                    if (exclusiveIsChosen) {
                        var needUpdate = false;
                        $el.find("option:selected:not([data-exclusive])").each(function() {
                            needUpdate = true;
                            $(this).removeAttr("selected");
                        });
                        if (needUpdate) {
                            $el.trigger("change");
                        }
                    } else {
                        needUpdate = false;
                        $el.find("option:selected[data-exclusive]").each(function() {
                            needUpdate = true;
                            $(this).removeAttr("selected");
                        });
                        if (needUpdate) {
                            $el.trigger("change");
                        }
                    }
                });
            }
        });
    });
})();

AGN.Lib.DomInitializer.new("session-timer", function() {
    var BLOCK_VISIBLE_TIME_MILLISECONDS = 10 * 60 * 1e3;
    var DELAY_TIME_MILLISECONDS = 5 * 1e3;
    var UNAUTHORIZED_STATUS = 401;
    var NOT_IMPLEMENTED_STATUS = 501;
    var config = this.config;
    var sessionInfoUrl = this.config.sessionInfoUrl;
    var creationTimeMs = this.config.creationTime;
    var lastAccessedTimeMs = this.config.lastAccessedTime;
    var maxInactiveIntervalS = this.config.maxInactiveInterval;
    var sessionExpiredDateMs;
    var isSessionReallyExpired = false;
    var isFirstChecking = true;
    var isChecking = false;
    var timerLoader;
    if (config && creationTimeMs && lastAccessedTimeMs && maxInactiveIntervalS) {
        sessionExpiredDateMs = maxInactiveIntervalS * 1e3 + Date.now();
        startTimer();
    }
    function startTimer() {
        setInterval(function() {
            var nowMs = Date.now();
            var timeLeftMs = sessionExpiredDateMs > nowMs ? sessionExpiredDateMs - nowMs : 0;
            if (!timerLoader) {
                timerLoader = new TimerGUI();
            }
            if ((!isFirstChecking || timeLeftMs <= BLOCK_VISIBLE_TIME_MILLISECONDS) && !isSessionReallyExpired && !isChecking) {
                timerLoader.showTimerBlock(timeLeftMs);
            }
            if (!isChecking && !isSessionReallyExpired && sessionExpiredDateMs + DELAY_TIME_MILLISECONDS > nowMs && sessionExpiredDateMs < nowMs) {
                timerLoader.showLoading();
            }
            if (!isSessionReallyExpired && !isChecking && sessionExpiredDateMs + DELAY_TIME_MILLISECONDS < nowMs) {
                checkIsReallyExpired();
            }
        }, 1e3);
    }
    function checkIsReallyExpired() {
        $.ajax({
            url: sessionInfoUrl,
            global: false,
            beforeSend: beforeRequest,
            success: successResponse,
            error: errorResponse,
            complete: afterResponse
        });
    }
    function beforeRequest() {
        isChecking = true;
    }
    function successResponse(data) {
        if (!!data) {
            maxInactiveIntervalS = data.maxInactiveInterval;
            sessionExpiredDateMs = Date.now() + data.maxInactiveInterval * 1e3;
            isSessionReallyExpired = false;
        } else {
            isSessionReallyExpired = true;
            timerLoader.showSessionExpired();
        }
    }
    function errorResponse(response) {
        if (response.status === UNAUTHORIZED_STATUS) {
            isSessionReallyExpired = true;
            timerLoader.showSessionExpired();
        }
    }
    function afterResponse() {
        isChecking = false;
        isFirstChecking = false;
    }
    $(document).ajaxComplete(function(event, xhr) {
        if (!event.preventSessionTimer && !isSessionReallyExpired && !isChecking && (xhr.status !== UNAUTHORIZED_STATUS && xhr.status < NOT_IMPLEMENTED_STATUS)) {
            sessionExpiredDateMs = maxInactiveIntervalS * 1e3 + Date.now();
        }
        event.preventSessionTimer = true;
    });
    var TimerGUI = function() {
        var self = this;
        self.timerLayout = $("#session-time-layout");
        self.timeField = $("#session-time-field");
        self.isSessionExpiredNotification = false;
        self.refreshIconClass = "icon icon-refresh icon-spin";
    };
    TimerGUI.prototype.showTimerBlock = function(timeLeftMs) {
        var self = this;
        self.timerLayout.show();
        self.printTimerText(timeLeftMs);
    };
    TimerGUI.prototype.showSessionExpired = function() {
        var self = this;
        self.printTimerText(0);
        if (!self.isSessionExpiredNotification) {
            $("body").append(AGN.Lib.Template.text("session-expired"));
            self.isSessionExpiredNotification = true;
        }
    };
    TimerGUI.prototype.showLoading = function() {
        var self = this;
        var loadingText = '<i class="' + self.refreshIconClass + '"></i>';
        self.changeTimeFieldContent(loadingText);
    };
    TimerGUI.prototype.printTimerText = function(timeMs) {
        var self = this;
        var timeString = "00:00";
        if (timeMs > 0) {
            var time = new Date(timeMs);
            timeString = time.getMinutes() > 0 ? d3.format("02")(time.getUTCMinutes()) + ":" : "00:";
            timeString += time.getSeconds() > 0 ? d3.format("02")(time.getUTCSeconds()) : "00";
        }
        self.changeTimeFieldContent(timeString);
    };
    TimerGUI.prototype.changeTimeFieldContent = function(content) {
        this.timeField.html(content);
    };
    return false;
});

AGN.Lib.CoreInitializer.new("sizing", function($scope) {
    if (!$scope) {
        $scope = $(document);
    }
    var windowHeight = $(window).height();
    _.each($scope.find('[data-sizing="container"]'), function(cont) {
        var $cont = $(cont), $topEls = $cont.find('[data-sizing="top"]'), $bottomEls = $cont.find('[data-sizing="bottom"]'), $els = $cont.find('[data-sizing="scroll"]'), offsetCont, topElsHeight, bottomElsHeight, elsHeight, offsetBottom;
        offsetCont = $cont.offset().top;
        topElsHeight = _.reduce(_.map($topEls, function(el) {
            return $(el).outerHeight();
        }), function(sum, addend) {
            return sum + addend;
        }) || 0;
        bottomElsHeight = _.reduce(_.map($bottomEls, function(el) {
            return $(el).outerHeight();
        }), function(sum, addend) {
            return sum + addend;
        }) || 0;
        offsetBottom = $cont.data("sizing-offset") || 20;
        elsHeight = windowHeight - offsetCont - topElsHeight - bottomElsHeight - offsetBottom;
        _.each($els, function(el) {
            var $el = $(el), offset;
            offset = $el.data("sizing-offset") || 0;
            $el.css({
                height: elsHeight - offset,
                "overflow-y": "auto"
            });
            $el.trigger("scrollTo");
        });
    });
});

(function() {
    var Helpers = AGN.Lib.Helpers;
    AGN.Lib.CoreInitializer.new("slider", function($scope) {
        if (!$scope) {
            $scope = $(document);
        }
        _.each($scope.find(".js-slider"), function(el) {
            var $el = $(el), baseOptions, options;
            baseOptions = {
                handle: "round",
                min: 0,
                max: 101
            };
            options = _.merge({}, baseOptions, Helpers.objFromString($el.data("slider-options")));
            $el.slider(options);
        });
    });
})();

AGN.Lib.CoreInitializer.new("sync", [ "ace" ], function($scope) {
    if (!$scope) {
        $scope = $(document);
    }
    _.each($scope.find("[data-sync]"), function(el) {
        var $this = $(el), $source = $($this.data("sync")), editor = $this.data("_editor");
        if (editor) {
            editor.val($source.val());
        } else {
            $this.val($source.val());
        }
    });
});

(function() {
    var Tab = AGN.Lib.Tab;
    AGN.Lib.CoreInitializer.new("tab-toggle", function($scope) {
        if (!$scope) {
            $scope = $(document);
        }
        _.each($scope.find("[data-toggle-tab]"), function(tab) {
            Tab.init($(tab));
        });
    });
})();

AGN.Lib.CoreInitializer.new("table-responsive-wrap", function($scope) {
    if (!$scope) {
        $scope = $(document);
    }
    $scope.find(".table-wrapper:not(.table-overflow-visible) table").wrap('<div class="table-responsive" />');
    $scope.find(".table-wrapper.table-overflow-visible table").wrap('<div class="table-responsive" style="overflow: visible;" />');
});

(function() {
    var Popover = AGN.Lib.Popover;
    function initializeRowClicks($row) {
        var $link = $row.find(".js-row-show");
        if ($link.length !== 1) {
            return;
        }
        $row.data("link", $link.attr("href"));
        $link.remove();
        _.each($row.prop("cells"), function(cell) {
            var $cell = $(cell);
            if ($cell.find("a,input,select,textarea,button").length !== 0) {
                return;
            }
            $cell.addClass("table-link");
            if ($cell.contents().length === 0) {
                $cell.html('<a href="' + $link.attr("href") + '">&nbsp;</a>');
            } else {
                $cell.contents().wrapAll('<a href="' + $link.attr("href") + '"></a>');
            }
        });
    }
    function initializeRowPopovers($row) {
        var $popover = $row.find(".js-row-popover");
        if ($popover.length !== 1) {
            return;
        }
        var deferred = false;
        var content = null;
        var getContent = function() {
            if (deferred === false) {
                deferred = $.Deferred();
                var $elements = $popover.children();
                if ($elements.length == 0) {
                    var $container = $("<div></div>");
                    $container.css({
                        position: "fixed",
                        visibility: "hidden"
                    });
                    $container.html($popover.html());
                    $elements = $container.children();
                    $(document.body).append($container);
                    deferred.done(function() {
                        $elements.detach();
                        $container.remove();
                    });
                }
                deferred.done(function() {
                    content = $elements;
                });
                var images = $elements.find("img").add($elements.filter("img")).filter(function() {
                    return this.complete ? null : this;
                });
                if (images.length > 0) {
                    deferred.done(function() {
                        var popover = $row.data("bs.popover");
                        if (popover) {
                            popover.setContent();
                            if ($row.is(":hover")) {
                                $row.popover("show");
                            }
                        }
                    });
                    var checkLoadingComplete = function() {
                        var complete = true;
                        for (var i = 0; i < images.length; i++) {
                            var image = images[i];
                            if (image) {
                                if (image.complete) {
                                    $(image).off("load error");
                                    images[i] = null;
                                } else {
                                    complete = false;
                                }
                            }
                        }
                        return complete;
                    };
                    for (var i = 0; i < images.length; i++) {
                        $(images[i]).on("load error", function() {
                            if (checkLoadingComplete()) {
                                deferred.resolve();
                            }
                        });
                    }
                } else {
                    deferred.resolve();
                }
            }
            return content;
        };
        Popover.new($row, {
            trigger: "hover",
            delay: {
                show: 300,
                hide: 100
            },
            html: true,
            content: getContent
        });
    }
    AGN.Lib.CoreInitializer.new("table-row-actions", function($scope) {
        if (!$scope) {
            $scope = $(document);
        }
        $scope.find(".js-table").each(function() {
            _.each(this.rows, function(row) {
                var $row = $(row);
                initializeRowClicks($row);
                initializeRowPopovers($row);
            });
        });
    });
})();

(function() {
    var Table = AGN.Lib.Table;
    AGN.Lib.CoreInitializer.new("table", function($scope) {
        if (!$scope) {
            $scope = $(document);
        }
        $scope.all(".js-data-table").each(function() {
            var $el = $(this);
            var $body = $el.find(".js-data-table-body");
            var id = $el.data("table");
            if ($body.exists() && id) {
                var $config = $("script#" + CSS.escape(id)), config, options;
                if ($config.exists()) {
                    config = $config.json();
                    if ($body.data("web-storage")) {
                        options = _.merge(AGN.Lib.WebStorage.get($body.data("web-storage")) || {}, config.options || {});
                    } else {
                        options = config.options || {};
                    }
                    new Table($body, config.columns, config.data, options);
                }
            }
        });
    });
})();

AGN.Lib.DomInitializer.new("targetgroup-overview-filters", function() {
    $("#filtersDescription").html(AGN.Lib.Template.text("targetgroup-overview-filters", this.config));
});

(function() {
    var READ_ONLY_PARAMS = {
        header_readonly: true,
        filter_readonly: true,
        condition_readonly: true,
        operator_readonly: true,
        value_readonly: true,
        no_delete: true,
        no_add_rule: true,
        no_sortable: true,
        no_add_group: true
    };
    AGN.Lib.DomInitializer.new("target-group-query-builder", function($needle) {
        var $form = AGN.Lib.Form.getWrapper($needle);
        var qbSelector = "#targetgroup-querybuilder";
        var queryBuilders = $(qbSelector);
        var mailTrackingAvailable = this.config.mailTrackingAvailable;
        var isTargetGroupLocked = this.config.isTargetGroupLocked;
        var helpLanguage = this.config.helpLanguage;
        var isIE10 = navigator.userAgent.match("MSIE 10.0;");
        var self = this;
        _.each(queryBuilders, function(el) {
            var $el = $(el);
            var operator_groups = buildOperatorGroups();
            var qbFilters = readFiltersFromJson(self.config.queryBuilderFilters, {
                mail_tracking_available: mailTrackingAvailable
            });
            var rules = readRulesFromJson(JSON.parse(self.config.queryBuilderRules), isTargetGroupLocked);
            $el.queryBuilder({
                filters: qbFilters,
                allow_empty: true,
                operators: operator_groups,
                helpLanguage: helpLanguage,
                readonly: isTargetGroupLocked,
                plugins: {
                    sortable: {
                        inherit_no_drop: true,
                        inherit_no_sortable: true,
                        icon: "icon icon-arrows-alt"
                    }
                },
                rules: rules
            });
            if (!isIE10) {
                AGN.Lib.CoreInitializer.run("select", $el);
            }
            $el.on("afterSetRules.queryBuilder afterUpdateRuleFilter.queryBuilder afterCreateRuleFilters.queryBuilder afterAddRule.querybuilder", function(event) {
                if (!isIE10) {
                    AGN.Lib.CoreInitializer.run("select", $(this));
                }
            });
            $el.on("link-values-set", function(e) {
                if (!isIE10) {
                    AGN.Lib.CoreInitializer.run("select", $(e.target));
                }
            });
            $el.on("mailing-values-set values-set ", function(e) {
                if (!isIE10) {
                    AGN.Lib.CoreInitializer.run("select", $(e.target));
                }
            });
            $el.on("change-date-format", function(e) {
                if (!isIE10) {
                    AGN.Lib.CoreInitializer.run("select", $(e.target));
                }
            });
            $el.on("enterdown", "input", function(e) {
                return false;
            });
        });
        $form.off().on("validation", function(e, options) {
            options = $.extend({
                ignore_qb_validation: false,
                skip_empty: false
            }, options);
            _.each($(qbSelector), function(el) {
                var $el = $(el);
                var qb = $el.prop("queryBuilder");
                if (!validate(e, qb, options, $el)) {
                    return false;
                }
            });
        });
        function validate(e, qb, options, $el) {
            qb.clearInitialRuleSettings();
            if (options.ignore_qb_validation) {
                return true;
            } else if (qb.validate({
                skip_filter_validation: false,
                skip_empty: options.skip_empty
            })) {
                $el.find("#queryBuilderRules").val(getRulesAsJson(qb, options.skip_empty));
                return true;
            } else {
                $el.trigger("qb:invalidrules");
                e.preventDefault();
                return false;
            }
        }
        function getRulesAsJson(qb, skipEmpty) {
            return JSON.stringify(qb.getRules({
                allow_invalid: true,
                skip_empty: skipEmpty
            }));
        }
        function setValue($element, value) {
            if (!isIE10 && $element.is("select")) {
                AGN.Lib.Select.get($element).selectValueOrSelectFirst(value);
            } else {
                $element.val(value);
            }
        }
        function readFiltersFromJson(filtersJson, options) {
            if (filtersJson === null) {
                filtersJson = [ {
                    id: "?",
                    label: "?",
                    type: "string"
                } ];
            } else {
                var ids = {};
                filtersJson = filtersJson.filter(function(e) {
                    if (ids[e.id]) {
                        return false;
                    }
                    ids[e.id] = true;
                    return true;
                });
            }
            augmentIndependentFields(filtersJson, options);
            return $.extend([], filtersJson);
        }
        function addReadOnlyFlags(options) {
            if (options) {
                options.flags = READ_ONLY_PARAMS;
                _.each(options.rules, function(rule) {
                    rule.flags = READ_ONLY_PARAMS;
                    if (rule.hasOwnProperty("condition")) {
                        addReadOnlyFlags(rule);
                    }
                });
            }
            return options;
        }
        function augmentIndependentFields(result, options) {
            options = $.extend({
                mail_tracking_available: false
            }, options);
            var getEmptyMailingSelect = function(rule) {
                var $select = $('<select class="form-control qb-input-element-select mailings js-select"></select>');
                $select.attr("id", rule.id);
                return $select;
            };
            var getEmptyAutoImportSelect = function(rule) {
                var $select = $('<select class="form-control qb-input-element-select auto-imports js-select"></select>');
                $select.attr("id", rule.id);
                return $select;
            };
            var mailingsValueGetter = function(rule) {
                return rule.$el.find(".mailings :selected").val();
            };
            var autoImportsValueGetter = function(rule) {
                return rule.$el.find(".auto-imports :selected").val();
            };
            var generateValueSetter = function(selector) {
                var savedValues = {}, savedRules = {}, defaultValue = -1;
                $(qbSelector).on("values-set", selector, function(event) {
                    if ($.isEmptyObject(savedRules)) {
                        setValue($(event.target), defaultValue);
                    } else {
                        var id = $(event.target).attr("id"), savedRule = savedRules[id], $inputs = savedRule ? savedRule.$el.find(selector) : $(event.target);
                        setValue($inputs, savedValues[id] || defaultValue);
                    }
                });
                return function(rule, value) {
                    var $inputs = rule.$el.find(selector);
                    savedValues[rule.id] = value;
                    savedRules[rule.id] = rule;
                    setValue($inputs, value);
                };
            };
            var mailingValueSetter = generateValueSetter("select.mailings");
            var autoImportValueSetter = generateValueSetter("select.auto-imports");
            var augmentations = {
                "finished auto-import": {
                    type: "string",
                    input_event: "values-setup-finished",
                    input: getEmptyAutoImportSelect,
                    values: function($ruleInput) {
                        requestAutoImports($ruleInput).done(function() {
                            $ruleInput.trigger("values-setup-finished");
                        });
                    },
                    valueSetter: autoImportValueSetter,
                    valueGetter: autoImportsValueGetter,
                    canBeNegated: true,
                    skipOperator: true
                },
                "received mailing": {
                    type: "string",
                    input_event: "values-setup-finished",
                    input: getEmptyMailingSelect,
                    values: function($ruleInput) {
                        requestMailings($ruleInput).done(function() {
                            $ruleInput.trigger("values-setup-finished");
                        });
                    },
                    valueSetter: mailingValueSetter,
                    valueGetter: mailingsValueGetter,
                    canBeNegated: true,
                    skipOperator: true
                },
                "opened mailing": {
                    type: "string",
                    input_event: "values-setup-finished",
                    input: getEmptyMailingSelect,
                    values: function($ruleInput) {
                        requestMailings($ruleInput).done(function() {
                            $ruleInput.trigger("values-setup-finished");
                        });
                    },
                    valueSetter: mailingValueSetter,
                    valueGetter: mailingsValueGetter,
                    canBeNegated: options.mail_tracking_available,
                    skipOperator: true
                },
                "clicked in mailing": {
                    type: "string",
                    input_event: "values-setup-finished",
                    valueSelector: function(ruleId, index) {
                        var ids = [ "mailingID", "linkID" ];
                        return ruleId + "_" + ids[index];
                    },
                    input: function(rule) {
                        return $('<div class="qb-input-element-select">' + '<select class="form-control js-select mailings" data-rule-id="' + rule.id + '" id="' + rule.filter.valueSelector(rule.id, 0) + '" ></select>' + "</div>" + '<div class="qb-input-label">' + '<div class="qb-input-inner">Links</div>' + "</div>" + '<div class="qb-input-element-select">' + '<select class="form-control js-select links" data-rule-id="' + rule.id + '" id="' + rule.filter.valueSelector(rule.id, 1) + '" ></select>' + "</div>");
                    },
                    values: function($ruleInput) {
                        var $mailings = $ruleInput.find(".mailings");
                        var mailings = AGN.Lib.Select.get($mailings);
                        $mailings.change(function() {
                            var mailingID = mailings.getSelectedValue();
                            requestMailingLinks(mailingID, function(data) {
                                var $links = $ruleInput.find(".links");
                                var links = AGN.Lib.Select.get($links);
                                var options = [ {
                                    id: -1,
                                    text: t("querybuilder.common.anyLink")
                                } ];
                                $.each(data, function(key, value) {
                                    options.push({
                                        id: value.id,
                                        text: value.url
                                    });
                                });
                                links.setOptions(options);
                                $links.trigger("link-values-set");
                            });
                        });
                        requestMailings($mailings, function(data) {
                            var options = [];
                            data.forEach(function(element) {
                                options.push({
                                    id: element.mailingID,
                                    text: element.shortname
                                });
                            });
                            mailings.setOptions(options);
                            $mailings.trigger("mailing-values-set");
                        });
                    },
                    valueGetter: function(rule) {
                        var mailingID = 0, linkID = 1, value = [];
                        value[mailingID] = rule.$el.find("#" + rule.filter.valueSelector(rule.id, mailingID)).val();
                        value[linkID] = rule.$el.find("#" + rule.filter.valueSelector(rule.id, linkID)).val();
                        return value;
                    },
                    valueSetter: function() {
                        var mailingID = 0, linkID = 1, savedValues = {}, savedRules = {};
                        var valueSetter = function(rule, value) {
                            savedValues[rule.id] = value;
                            savedRules[rule.id] = rule;
                        };
                        $(qbSelector).on("mailing-values-set", function(event) {
                            var $select = $(event.target), id = $select.data("rule-id"), savedRule = savedRules[id], $mailings;
                            if (savedRule) {
                                $mailings = savedRule.$el.find(".mailings");
                                setValue($mailings, savedValues[id][mailingID]);
                                $mailings.trigger("change");
                            } else {
                                setValue($select);
                                $select.trigger("change");
                            }
                        });
                        $(qbSelector).on("link-values-set", function(event) {
                            var id = $(event.target).data("rule-id"), savedRule = savedRules[id], $links;
                            if (savedRule) {
                                $links = savedRule.$el.find(".links");
                                setValue($links, savedValues[id][linkID] || -1);
                            } else {
                                $links = $(event.target);
                                setValue($links);
                            }
                            $links.trigger("values-setup-finished");
                        });
                        return valueSetter;
                    }(),
                    validation: {
                        callback: function(values) {
                            return values.every(function(v) {
                                return v;
                            }) || [ "string_empty" ];
                        }
                    },
                    canBeNegated: options.mail_tracking_available,
                    skipOperator: true
                },
                "revenue by mailing": {
                    type: "string",
                    input_event: "values-setup-finished",
                    input: getEmptyMailingSelect,
                    values: function($ruleInput) {
                        requestMailings($ruleInput).done(function() {
                            $ruleInput.trigger("values-setup-finished");
                        });
                    },
                    valueSetter: mailingValueSetter,
                    valueGetter: mailingsValueGetter,
                    canBeNegated: options.mail_tracking_available,
                    skipOperator: true
                }
            };
            if (!options.mail_tracking_available) {
                delete augmentations["received mailing"];
            }
            result.forEach(function(element) {
                var properties = augmentations[element.id];
                if (properties) {
                    $.extend(element, properties);
                }
            });
        }
        function requestMailings($ruleInput, successCallback) {
            var success = successCallback || function(data) {
                var rule = AGN.Lib.Select.get($ruleInput);
                var options = [];
                data.forEach(function(element) {
                    options.push({
                        id: element.mailingID,
                        text: element.shortname
                    });
                });
                rule.setOptions(options);
                $ruleInput.trigger("values-set");
            };
            return $.ajax({
                type: "GET",
                url: AGN.url("/workflow/getAllMailingSorted.action"),
                data: {
                    sortField: "date",
                    sortDirection: "desc"
                },
                success: success
            });
        }
        function requestAutoImports($ruleInput, successCallback) {
            var success = successCallback || function(data) {
                data.forEach(function(element) {
                    $ruleInput.append($("<option>", {
                        text: element.shortname,
                        value: element.autoImportId
                    }));
                });
                $ruleInput.trigger("values-set");
            };
            return $.ajax({
                type: "POST",
                url: AGN.url("/autoimport.do"),
                data: {
                    method: "listJson"
                },
                success: success
            });
        }
        function defaultMailingsSuccessCallback(data, $ruleInput) {
            data.forEach(function(element) {
                var option = $("<option>");
                option.text(element.shortname);
                option.val(element.mailingID);
                $ruleInput.append(option);
            });
        }
        function requestMailingLinks(mailingId, success) {
            $.ajax({
                type: "POST",
                url: AGN.url("/workflow/getMailingLinks.action"),
                data: {
                    mailingId: mailingId
                },
                success: success
            });
        }
        function readRulesFromJson(rulesJson, isTGLocked) {
            if (isTGLocked) {
                rulesJson = addReadOnlyFlags(rulesJson);
            }
            return $.extend({}, rulesJson);
        }
        function buildOperatorGroups() {
            return [ {
                type: "equal",
                apply_to: [ "string", "number", "datetime" ]
            }, {
                type: "not_equal",
                apply_to: [ "string", "number", "datetime" ]
            }, {
                type: "less",
                apply_to: [ "string", "number" ]
            }, {
                type: "less_or_equal",
                apply_to: [ "string", "number" ]
            }, {
                type: "greater",
                apply_to: [ "string", "number" ]
            }, {
                type: "greater_or_equal",
                apply_to: [ "string", "number" ]
            }, {
                type: "like",
                nb_inputs: 1,
                apply_to: [ "string" ]
            }, {
                type: "not_like",
                nb_inputs: 1,
                apply_to: [ "string" ]
            }, {
                type: "contains",
                nb_inputs: 1,
                apply_to: [ "string" ]
            }, {
                type: "not_contains",
                nb_inputs: 1,
                apply_to: [ "string" ]
            }, {
                type: "begins_with",
                nb_inputs: 1,
                apply_to: [ "string" ]
            }, {
                type: "not_begins_with",
                nb_inputs: 1,
                apply_to: [ "string" ]
            }, {
                type: "mod",
                nb_inputs: 1,
                apply_to: [ "number" ],
                valueSelectors: [ "#first", "#operator select", "#second" ],
                valueGetter: function(rule) {
                    var values = [];
                    rule.operator.valueSelectors.forEach(function(element) {
                        values.push(rule.$el.find(element).val());
                    });
                    return values;
                },
                valueSetter: function(rule, value) {
                    rule.operator.valueSelectors.forEach(function(element, index) {
                        rule.$el.find(element).val(value[index]);
                    });
                },
                input: function(rule) {
                    var operators = this.operators.filter(function(operator) {
                        return operator.type !== "mod" && operator.apply_to.includes("number");
                    });
                    var operatorSelect = this.getRuleOperatorSelect(rule, operators);
                    return "" + "<div class='qb-input-element'>" + "<input class='form-control' id='first' type='number'/>" + "</div>" + "<div class='qb-input-element' id='operator'>" + operatorSelect + "</div>" + "<div class='qb-input-element'>" + "<input class='form-control' id='second' type='number'/>" + "</div>";
                },
                validate: function(values) {
                    return values.every(function(v) {
                        return v;
                    }) || [ "string_empty" ];
                }
            }, {
                type: "is_empty",
                nb_inputs: 0,
                apply_to: [ "string", "number", "datetime" ]
            }, {
                type: "is_not_empty",
                nb_inputs: 0,
                apply_to: [ "string", "number", "datetime" ]
            }, {
                type: "before",
                nb_inputs: 1,
                apply_to: [ "datetime" ]
            }, {
                type: "after",
                nb_inputs: 1,
                apply_to: [ "datetime" ]
            } ];
        }
    });
})();

AGN.Lib.Controller.new("targets-list", function() {
    this.addAction({
        change: "check-favorites"
    }, function() {
        AGN.Lib.Loader.prevent();
        $.ajax({
            type: "GET",
            url: AGN.url(getFavoritesActionAddress(this.el))
        });
    });
    function getFavoritesActionAddress(el) {
        var targetId = el.data("target-id");
        var favorite = el.is(":checked");
        return "/target/" + targetId + "/" + (favorite ? "addToFavorites" : "removeFromFavorites") + ".action";
    }
    this.addAction({
        change: "check-admin-favorites"
    }, function() {
        AGN.Lib.Loader.prevent();
        const targetId = this.el.data("target-id");
        const favorite = this.el.is(":checked");
        $.ajax({
            type: favorite ? "POST" : "DELETE",
            url: AGN.url("/target/" + targetId + "/favorite.action")
        });
    });
});

AGN.Lib.CoreInitializer.new("template", function($scope) {
    if (!$scope) {
        $scope = $(document);
    }
    $scope.find('script[type="text/x-mustache-template"]').each(function() {
        var $template = $(this);
        var id = $template.attr("id");
        if (id) {
            AGN.Opt.Templates[id] = $template.html();
        }
    });
});

(function() {
    var Tile = AGN.Lib.Tile;
    AGN.Lib.CoreInitializer.new("tile-toggle", function($scope) {
        if (!$scope) {
            $scope = $(document);
        }
        _.each($scope.find("[data-toggle-tile]"), function(trigger) {
            Tile.init($(trigger));
        });
    });
})();

(function() {
    var Tooltip = AGN.Lib.Tooltip;
    AGN.Lib.CoreInitializer.new("tooltip", function($scope) {
        if (!$scope) {
            $scope = $(document);
        }
        $(".tooltip").remove();
        $scope.find("[data-tooltip], [data-tooltip-help]").each(function() {
            var $e = $(this);
            Tooltip.create($e, Tooltip.options($e));
        });
    });
})();

(function() {
    var truncate = AGN.Lib.Truncate.run;
    var breadcrumbs = AGN.Lib.Breadcrumbs.truncate;
    AGN.Lib.CoreInitializer.new("truncate", function($scope) {
        if (!$scope) {
            $scope = $(document);
        }
        setTimeout(function() {
            _.each($scope.find(".l-header"), function(trunc) {
                var $trunc = $(trunc);
                truncate($trunc, ".header-nav");
                breadcrumbs($trunc.find(".header-nav"));
            });
        }, 50);
    });
})();

AGN.Lib.DomInitializer.new("upload", function($e) {
    var Template = AGN.Lib.Template, Form = AGN.Lib.Form;
    var $dropzone = $e.find("[data-upload-dropzone]").first();
    var $file = ($dropzone.exists() ? $dropzone : $e).find("[data-upload]");
    var $listArea = $e.find("[data-upload-add]");
    var $listTable = $listArea.find("[data-upload-add-template]");
    var $progressArea = $e.find("[data-upload-progress]");
    var $progressBox = $progressArea.find("[data-upload-progress-template]");
    var makeListRow;
    var makeProgressBar;
    var name = $file.prop("name") || "";
    var nameIsIndexed = name.includes("[]");
    var multiple = !$file.exists() || $file.is("[multiple]");
    var form;
    var selection = [];
    if ($file.exists() || $dropzone.exists()) {
        exposeSelection();
        makeListRow = Template.prepare($listTable.data("upload-add-template"));
        makeProgressBar = Template.prepare($progressBox.data("upload-progress-template"));
        $file.prop("name", "");
        form = Form.get($file.exists() ? $file : $dropzone);
        if ($dropzone.exists()) {
            new Dropzone($dropzone, {
                classDragOver: "drag-over",
                onSelectFiles: function(files) {
                    drop(files);
                }
            });
        } else {
            $file.on("change", function() {
                drop($file.prop("files"));
            });
        }
        var $form = form.get$();
        $form.on("form:loadershow", function() {
            $progressBox.html(makeProgressBar({
                currentProgress: true
            }));
            $progressArea.removeClass("hidden");
        });
        $form.on("form:loaderhide", function() {
            $progressArea.addClass("hidden");
            $listArea.removeClass("hidden");
        });
        $form.on("form:submit", function() {
            $listArea.addClass("hidden");
        });
        $form.on("form:abort", function() {
            if (selection.length) {
                $listArea.removeClass("hidden");
                setFormValues();
            }
        });
        $form.on("form:progress", function(e, data) {
            $progressBox.html(makeProgressBar({
                currentProgress: data.progress
            }));
        });
        $form.on("submitted", function() {
            removeAllRows();
            reset();
        });
        $e.on("upload:reset", function() {
            removeAllRows();
            reset();
            $e.trigger("reset-upload", $form);
        });
        $e.on("click", "a[data-upload-reset], button[data-upload-reset]", function() {
            removeAllRows();
            reset();
            $e.trigger("reset-upload", $form);
        });
    }
    function reset() {
        clearFormValues();
        selection = [];
        exposeSelection();
    }
    function drop(files) {
        if (files && files.length > 0) {
            var added = false;
            var file;
            if (multiple) {
                for (var i = 0; i < files.length; i++) {
                    file = files[i];
                    if (onDrop(file, selection.length)) {
                        selection.push(file);
                        appendRow(file);
                        added = true;
                    }
                }
            } else {
                file = files[0];
                if (onDrop(file, 0)) {
                    removeAllRows();
                    reset();
                    selection = [ file ];
                    appendRow(file);
                    added = true;
                }
            }
            if (added) {
                exposeSelection();
                setFormValues();
            }
        }
    }
    function getIndexedName(index) {
        return name.replace("[]", "[" + index + "]");
    }
    function setFormValues() {
        if (nameIsIndexed) {
            selection.forEach(function(s, index) {
                form.setValueOnce(getIndexedName(index + 1), s);
            });
        } else {
            form.setValueOnce(name, selection.slice(0));
        }
    }
    function clearFormValues() {
        if (nameIsIndexed) {
            selection.forEach(function(s, index) {
                form.setValueOnce(getIndexedName(index + 1), undefined);
            });
        } else {
            form.setValueOnce(name, undefined);
        }
    }
    function onDrop(file, index) {
        var event = $.Event("upload:add");
        $e.trigger(event, {
            file: file,
            index: index
        });
        return !event.isDefaultPrevented();
    }
    function appendRow(file) {
        var duplicationErrorHidden = !file.id ? "hidden" : "";
        var data = {
            file: file,
            count: selection.length,
            filename: file.name,
            size: file.size,
            id: file.id ? file.id : 0,
            duplicationErrorHidden: duplicationErrorHidden,
            preview: undefined
        };
        if (/^image/.test(file.type)) {
            var reader = new FileReader();
            reader.onloadend = function() {
                data.preview = this.result;
                $listArea.removeClass("hidden");
                AGN.runAll($(makeListRow(data)).appendTo($listTable));
                form.initFields();
            };
            reader.readAsDataURL(file);
        } else {
            data.preview = undefined;
            $listArea.removeClass("hidden");
            AGN.runAll($(makeListRow(data)).appendTo($listTable));
            form.initFields();
        }
    }
    function removeAllRows() {
        $listArea.addClass("hidden");
        $listTable.empty();
        form.initFields();
    }
    function exposeSelection() {
        $e.data("upload-selection", selection.slice(0));
    }
});

(function() {
    AGN.Lib.DomInitializer.new("user-activity-log-period", function($elem) {
        initDatePeriodSelector($elem);
    });
    function initDatePeriodSelector($scope) {
        if (!$scope) {
            $scope = $(document);
        }
        var periodElements = [];
        _.each($scope.find(".js-datepicker"), function(input) {
            var $input = $(input);
            if ($input.hasClass("js-datepicker-period-start")) {
                if (!($input.attr("datepicker-period-id") in periodElements)) {
                    periodElements[$input.attr("datepicker-period-id")] = {
                        startEl: null,
                        endEl: null
                    };
                }
                periodElements[$input.attr("datepicker-period-id")].startEl = $input;
            }
            if ($input.hasClass("js-datepicker-period-end")) {
                if (!($input.attr("datepicker-period-id") in periodElements)) {
                    periodElements[$input.attr("datepicker-period-id")] = {
                        startEl: null,
                        endEl: null
                    };
                }
                periodElements[$input.attr("datepicker-period-id")].endEl = $input;
            }
        });
        for (var i = 0; i < periodElements.length; i++) {
            initPeriodDatePickers(periodElements[i].startEl.pickadate("picker"), periodElements[i].endEl.pickadate("picker"));
        }
    }
    function initPeriodDatePickers($datePickerStart, $datePickerEnd) {
        var pickerStartDay = $datePickerStart;
        var pickerEndDay = $datePickerEnd;
        if (pickerStartDay.get("value")) {
            pickerEndDay.set("min", pickerStartDay.get("select"));
        }
        if (pickerEndDay.get("value")) {
            pickerStartDay.set("max", pickerEndDay.get("select"));
        }
        pickerStartDay.on("set", function(event) {
            if (event.select) {
                pickerEndDay.set("min", pickerStartDay.get("select"));
            } else if ("clear" in event) {
                pickerEndDay.set("min", false);
            }
        });
        pickerEndDay.on("set", function(event) {
            if (event.select) {
                pickerStartDay.set("max", pickerEndDay.get("select"));
            } else if ("clear" in event) {
                pickerStartDay.set("max", false);
            }
        });
    }
})();

AGN.Lib.CoreInitializer.new("view", function() {
    AGN.Lib.View.init();
});

AGN.Lib.DomInitializer.new("web-storage-persist", function() {
    if (this.config) {
        $.each(this.config, function(k, v) {
            var key = "web-storage#" + $.trim(k);
            var value = null;
            try {
                value = AGN.Lib.Storage.get(key);
            } catch (e) {
                console.error(e);
            }
            if (value != null) {
                AGN.Lib.Storage.set(key, $.extend(value, v));
            } else {
                AGN.Lib.Storage.set(key, v);
            }
        });
    }
});

AGN.Lib.DomInitializer.new("workflow-pause-timer", function() {
    const WORKFLOW_ID = this.config.workflowId;
    const PAUSE_TIME_MS = this.config.pauseTime;
    const DEFAULT_EXPIRATION_HOURS = this.config.defaultExpirationHours;
    const EXPIRATION_HOURS = this.config.expirationHours > 0 ? this.config.expirationHours : DEFAULT_EXPIRATION_HOURS;
    const EXPIRATION_MS = EXPIRATION_HOURS * 60 * 60 * 1e3;
    const timeField = $("#workflow-pause-timer-text");
    const oneSecInterval = setInterval(function() {
        updateTimer();
    }, 1e3);
    updateTimer();
    function updateTimer() {
        timeField.html(getTimeStr());
    }
    function calculateTimeLeftMs() {
        return EXPIRATION_MS - (Date.now() - PAUSE_TIME_MS);
    }
    function getTimeStr() {
        const timeLeftMs = calculateTimeLeftMs();
        if (timeLeftMs <= 0) {
            if (oneSecInterval) {
                clearInterval(oneSecInterval);
            }
            autoUnpause();
            return '<i class="icon icon-refresh icon-spin"></i> ' + t("workflow.activating.auto");
        }
        const time = new Date(timeLeftMs);
        return (time.getHours() > 0 ? d3.format("01")(time.getUTCHours()) + ":" : "") + (time.getMinutes() > 0 ? d3.format("02")(time.getUTCMinutes()) + ":" : "00:") + (time.getSeconds() > 0 ? d3.format("02")(time.getUTCSeconds()) : "00");
    }
    function autoUnpause() {
        return $.post(AGN.url("/workflow/" + WORKFLOW_ID + "/autoUnpause.action")).done(function(resp) {
            if (resp.success === true) {
                AGN.Lib.Page.reload(AGN.url("/workflow/" + WORKFLOW_ID + "/view.action"));
            } else {
                AGN.Lib.JsonMessages(resp.popups);
            }
        }).fail(function() {
            AGN.Lib.Messages(t("Error"), t("defaults.error"), "alert");
        });
    }
    return false;
});

(function() {
    var Loader = AGN.Lib.Loader, Template = AGN.Lib.Template, Page = AGN.Lib.Page, CSRF = AGN.Lib.CSRF;
    var AjaxLoader = {
        initialize: function(options) {
            if (options.loader === true || options.loader === undefined) {
                options.loader = {
                    show: function() {
                        Loader.show();
                    },
                    hide: function() {
                        Loader.hide();
                    }
                };
            }
        },
        show: function(options) {
            var loader = options.loader;
            if (loader && loader.show) {
                try {
                    loader.show();
                } catch (e) {
                    console.error(e);
                }
            }
        },
        hide: function(options) {
            var loader = options.loader;
            if (loader && loader.hide) {
                try {
                    loader.hide();
                } catch (e) {
                    console.error(e);
                }
            }
        }
    };
    $.ajaxPrefilter(function(options) {
        AjaxLoader.initialize(options);
    });
    $(document).ajaxSend(function(e, jqxhr, options) {
        AjaxLoader.show(options);
        CSRF.setTokenToReqHeader(jqxhr, options.type);
    });
    $(document).ajaxComplete(function(e, jqxhr, options) {
        AjaxLoader.hide(options);
        CSRF.updateTokenInDOM();
    });
    $(document).ajaxError(function(e, jqxhr, options) {
        AjaxLoader.hide(options);
        if (jqxhr.readyState == 0 || jqxhr.status == 0) {
            return;
        }
        if (options.statusCode && jqxhr.status in options.statusCode) {
            return;
        }
        var errorMessage;
        if (jqxhr.status == 401) {
            var event = $.Event("ajax:unauthorized");
            $(document).trigger(event);
            if (!event.isDefaultPrevented() && jqxhr.responseText) {
                Page.render(jqxhr.responseText);
            }
        } else if (jqxhr.status == 403) {
            if (jqxhr.responseText) {
                if (/<\s*\/\s*body\s*>/i.test(jqxhr.responseText)) {
                    var parser = new DOMParser();
                    var csrfBody = parser.parseFromString(jqxhr.responseText, "text/html").querySelector("#csrf-error-page");
                    if ($(csrfBody).length) {
                        var csrfErrorMessage = Template.text("csrf-error", {
                            headline: t("messages.permission.denied.title"),
                            content: t("messages.error.csrf"),
                            reload: t("messages.error.reload")
                        });
                        $("body").append(csrfErrorMessage);
                        return;
                    }
                }
            }
            errorMessage = Template.text("permission-denied", {
                title: t("messages.permission.denied.title"),
                text: t("messages.permission.denied.text"),
                btn: t("defaults.ok")
            });
            $("body").append(errorMessage);
        } else {
            var isDefault = true;
            if (jqxhr.responseText) {
                try {
                    var $resp = $(jqxhr.responseText);
                    var $errorMessage = $resp.filter("#error-message");
                    var $errorPage = $resp.filter("#error-page");
                    var $scriptMessages = $resp.all("[data-message]");
                    if ($errorPage.exists()) {} else if ($errorMessage.exists()) {
                        if ($errorMessage.is('script[type="text/x-mustache-template"]')) {
                            $("body").append(_.template($errorMessage.html()));
                        } else {
                            $("body").append($errorMessage);
                        }
                        isDefault = false;
                    } else if ($scriptMessages.exists()) {
                        Page.render(jqxhr.responseText);
                        isDefault = false;
                    }
                } catch (e) {
                    console.debug(e);
                }
            }
            if (isDefault) {
                errorMessage = Template.text("error", {
                    headline: t("messages.error.headline"),
                    text: t("messages.error.text"),
                    reload: t("messages.error.reload")
                });
                $("body").append(errorMessage);
            }
        }
    });
    $(document).on("click", "a[data-ajax], a.js-ajax", function(e) {
        var $e = $(this);
        e.preventDefault();
        Page.reload($e.attr("href"), true, $e.data("ajax"));
    });
    $(document).on("click", "[data-prevent-load]", function() {
        Loader.prevent();
    });
    window.onbeforeunload = function() {
        Loader.show();
    };
})();

(function() {
    $(document).on("click", "[data-toggle-checkboxes]", function(e) {
        const $elem = $(this);
        const action = $elem.data("toggle-checkboxes");
        const tileContentId = $elem.closest(".tile-header").find("[data-toggle-tile]").data("toggle-tile");
        _.each($(tileContentId + " [type=checkbox]:enabled"), function(item) {
            const isChecked = action == "on" ? true : false;
            $(item).prop("checked", isChecked);
        });
        e.preventDefault();
    });
    $(document).on("click", "[data-toggle-checkboxes-all]", function(e) {
        const action = $(this).data("toggle-checkboxes-all");
        _.each($(".checkboxes-content [type=checkbox]:enabled"), function(item) {
            const isChecked = action == "on" ? true : false;
            $(item).prop("checked", isChecked);
        });
        e.preventDefault();
    });
})();

(function() {
    var Action = AGN.Lib.Action;
    Action.new({
        click: "[data-clone]"
    }, function() {
        var template = this.el.data("clone"), target = this.el.data("clone-target"), count = parseInt(this.el.data("clone-count")), html, $html;
        count += 1;
        this.el.data("clone-count", count);
        html = AGN.Lib.Template.text(template, {
            count: count
        });
        $html = $(target).append(html);
        AGN.runAll($html);
    });
    $(document).on("click", "a[data-clone]", function(e) {
        e.preventDefault();
    });
})();

(function() {
    var Form = AGN.Lib.Form, Confirm = AGN.Lib.Confirm, Action = AGN.Lib.Action, Page = AGN.Lib.Page;
    Action.new({
        click: "[data-confirm], .js-confirm"
    }, function() {
        var jqxhr;
        jqxhr = $.get(this.el.attr("href"));
        jqxhr.done(function(resp) {
            var $resp = $(resp), $modal;
            $modal = $resp.filter(".modal").add($resp.find(".modal"));
            if ($modal.length != 1) {
                Page.render(resp);
                return;
            }
            Confirm.create(resp).done(function(resp) {
                Page.render(resp);
            });
        });
        this.event.preventDefault();
    });
    $(document).on("click", "[data-confirm-positive], .js-confirm-positive", function() {
        var $this = $(this), confirm = Confirm.get($this), $form = Form.getWrapper($this);
        if (confirm) {
            var $saveChoice = confirm.$modal.find('[name="confirm-save-choice"]');
            if ($form.exists()) {
                const form = Form.get($form);
                if ($this.is("[data-url]")) {
                    form.setActionOnce($this.data("url"));
                }
                form.jqxhr().done(function(resp) {
                    confirm.positive(resp);
                });
            } else {
                if ($saveChoice.exists()) {
                    confirm.positive({
                        code: $this.data("confirm-positive"),
                        saveChoice: $saveChoice[0].checked
                    });
                } else {
                    confirm.positive($this.data("confirm-positive"));
                }
            }
        }
    });
    $(document).on("click", "[data-confirm-negative], .js-confirm-negative", function() {
        var $this = $(this), confirm = Confirm.get($this);
        if (confirm) {
            var $saveChoice = confirm.$modal.find('[name="confirm-save-choice"]');
            if ($saveChoice.exists()) {
                confirm.negative({
                    code: $this.data("confirm-negative"),
                    saveChoice: $saveChoice[0].checked
                });
            } else {
                confirm.negative($this.data("confirm-negative"));
            }
        }
    });
})();

(function() {
    var Action = AGN.Lib.Action, Clipboard = AGN.Lib.Clipboard, Tooltip = AGN.Lib.Tooltip;
    Action.new({
        click: "[data-copyable]"
    }, function() {
        var value = undefined;
        if (this.el.is("[data-copyable-value]")) {
            value = this.el.data("copyable-value");
        } else {
            var selector = this.el.data("copyable-target");
            var $target;
            if (selector) {
                $target = $(selector);
            } else {
                $target = this.el;
            }
            if ($target.exists()) {
                value = $target.val();
            }
        }
        if (value !== undefined) {
            var $element = this.el;
            Clipboard.set(value, function(v, success) {
                if (success) {
                    Tooltip.create($element, {
                        title: t("clipboard.copied.tooltip"),
                        trigger: "manual"
                    });
                    Tooltip.setShown($element);
                    var currentTimeoutId = $element.data("tooltip-timeout-id");
                    if (currentTimeoutId) {
                        clearTimeout(currentTimeoutId);
                    }
                    var timeoutId = setTimeout(function() {
                        Tooltip.remove($element);
                        $element.removeData("tooltip-timeout-id");
                    }, 2500);
                    $element.data("tooltip-timeout-id", timeoutId);
                }
            });
        }
    });
})();

(function() {
    var Table = AGN.Lib.Table, WebStorage = AGN.Lib.WebStorage;
    $(document).on("click", ".js-data-table-first-page", function(e) {
        Table.get($(this)).api.paginationGoToFirstPage();
    });
    $(document).on("click", ".js-data-table-prev-page", function(e) {
        Table.get($(this)).api.paginationGoToPreviousPage();
    });
    $(document).on("click", ".js-data-table-page", function(e) {
        Table.get($(this)).api.paginationGoToPage($(this).data("page"));
    });
    $(document).on("click", ".js-data-table-next-page", function(e) {
        Table.get($(this)).api.paginationGoToNextPage();
    });
    $(document).on("click", ".js-data-table-last-page", function(e) {
        Table.get($(this)).api.paginationGoToLastPage();
    });
    $(document).on("click", ".js-data-table-paginate", function(e) {
        var $e = $(this);
        var pageSize = $e.data("page-size");
        var api = Table.get($e).api;
        api.paginationSetPageSize(pageSize);
        $e.closest(".dropdown-menu").trigger("click");
        var bundle = $e.data("web-storage");
        if (bundle) {
            WebStorage.extend(bundle, {
                paginationPageSize: parseInt(pageSize)
            });
        }
    });
    $(window).on("viewportChanged", function(e) {
        $(document).all(".js-data-table-body").each(function() {
            AGN.Lib.Table.get($(this)).redraw();
        });
    });
    $(document).on("click", ".js-data-table-bulk-delete", function(e) {
        var $e = $(this);
        bulkDelete($e, false);
    });
    function bulkDelete($e) {
        var field = $e.data("bulk-field") || "id";
        var requestField = $e.data("bulk-request-field") || "bulkIds";
        var api = Table.get($e).api;
        var rows = api.getSelectedRows();
        var ids = rows.map(function(row) {
            return row[field];
        });
        var data = {};
        data[requestField] = ids;
        requestBulkDelete(ids, $e.data("bulk-url"), data).done(function() {
            api.updateRowData({
                remove: rows
            });
        });
    }
    function requestBulkDelete(ids, url, data) {
        var deferred = $.Deferred();
        if (ids && ids.length) {
            var jqxhr = $.ajax(url, {
                method: "POST",
                traditional: false,
                data: data
            }).fail(function() {
                deferred.reject();
            });
            AGN.Lib.Confirm.request(jqxhr).then(deferred.resolve, deferred.reject);
        } else {
            deferred.reject();
            AGN.Lib.Messages(t("Error"), t("messages.error.nothing_selected"), "alert");
        }
        return deferred.promise();
    }
})();

$(document).ready(function() {
    window.AGN.Lib.Controller.init();
    window.AGN.runAll();
});

(function() {
    $(document).on("dragster:enter", function(e) {
        var $target = $(e.target);
        if (!$target.is("[data-upload-dropzone]")) {
            $target.addClass("drag-over");
        }
    });
    $(document).on("dragster:leave", function(e) {
        var $target = $(e.target);
        if (!$target.is("[data-upload-dropzone]")) {
            $target.removeClass("drag-over");
        }
    });
})();

(function() {
    $(document).on("click", ".dropdown-menu *", function(e) {
        $target = $(e.target);
        if ($target.hasClass("js-dropdown-open")) {
            e.preventDropdownClose = true;
        }
        if ($target.parent(".js-dropdown-open").length == 1) {
            e.preventDropdownClose = true;
        }
        if ($target.is("button")) return;
        if ($target.is("a")) return;
        if ($target.parent("a").length == 1) return;
        if ($target.parent("button").length == 1) return;
        if ($target.hasClass("js-dropdown-close")) return;
        if ($target.parent(".js-dropdown-close").length == 1) return;
        e.preventDropdownClose = true;
    });
})();

$(document).on("click", ".js-close-error", function(e) {
    if (!$(e.target).hasClass("js-close-error")) {
        return;
    }
    $(this).closest(".backdrop").remove();
});

(function() {
    var Action = AGN.Lib.Action, Form = AGN.Lib.Form, Confirm = AGN.Lib.Confirm, Helpers = AGN.Lib.Helpers;
    Action.new({
        click: "[data-form-change]"
    }, function() {
        Form.get(this.el).setValueOnce("numberOfRowsChanged", true);
    });
    Action.new({
        click: "[data-form-bulk]"
    }, function() {
        var group = this.el.data("form-bulk"), value = this.el.prop("checked");
        Form.get(this.el).bulkUpdate(group, value);
    });
    Action.new({
        click: "a[data-form-set], button[data-form-set]",
        change: "select[data-form-set], input[data-form-set]"
    }, function() {
        var opts = Helpers.objFromString(this.el.data("form-set")), form = Form.get(this.el);
        _.forEach(opts, function(value, field) {
            form.setValueOnce(field, value);
        });
    });
    Action.new({
        click: "a[data-form-url], button[data-form-url]",
        change: "select[data-form-url], input[data-form-url]"
    }, function() {
        Form.get(this.el).setActionOnce(this.el.data("form-url"));
    });
    Action.new({
        click: "a[data-form-resource], button[data-form-resource]",
        change: "select[data-form-resource], input[data-form-resource]"
    }, function() {
        var form = Form.get(this.el);
        if (form instanceof AGN.Lib.ResourceForm) {
            form.setResourceSelectorOnce(this.el.data("form-resource"));
        }
    });
    Action.new({
        click: "a[data-form-persist], button[data-form-persist]",
        change: "select[data-form-persist], input[data-form-persist]"
    }, function() {
        var opts = Helpers.objFromString(this.el.data("form-persist")), form = Form.get(this.el);
        _.forEach(opts, function(value, field) {
            form.setValue(field, value);
        });
    });
    Action.new({
        click: "a[data-form-reset], button[data-form-reset]"
    }, function() {
        Form.get(this.el).reset();
    });
    Action.new({
        click: "a[data-form-abort], button[data-form-abort]"
    }, function() {
        Form.get(this.el).abort();
    });
    Action.new({
        click: "[data-form-confirm]"
    }, function() {
        var action = this.el.data("form-confirm"), form = Form.get(this.el), jqhxr;
        jqhxr = form.submit("confirm", action);
        jqhxr.done(function(resp) {
            var $resp = $(resp), $modal;
            $modal = $resp.filter(".modal").add($resp.find(".modal"));
            if ($modal.length != 1) {
                form.updateHtml(resp);
                return;
            }
            Confirm.create(resp).done(function(resp) {
                form.updateHtml(resp);
            }).fail(form.revertAction);
        });
    });
    Action.new({
        click: "a[data-form-action], button[data-form-action]",
        change: "select[data-form-action], input[data-form-action]"
    }, function() {
        var action = this.el.data("form-action"), form = Form.get(this.el), jqhxr;
        setTimeout(function() {
            jqhxr = form.submit("action", action);
        }, 5);
    });
    Action.new({
        click: "a[data-form-submit], button[data-form-submit]",
        change: "select[data-form-submit], input[data-form-submit]"
    }, function() {
        var self = this;
        setTimeout(function() {
            Form.get(self.el).submit();
        }, 5);
    });
    Action.new({
        click: "a[data-form-submit-static], button[data-form-submit-static]",
        change: "select[data-form-submit-static], input[data-form-submit-static]"
    }, function() {
        var self = this;
        setTimeout(function() {
            Form.get(self.el).submit("static");
        }, 5);
    });
    Action.new({
        click: "a[data-form-submit-event], button[data-form-submit-event]",
        change: "select[data-form-submit-event], input[data-form-submit-event]"
    }, function() {
        var self = this;
        setTimeout(function() {
            Form.get(self.el).submit("event");
        }, 5);
    });
    Action.new({
        submit: "[data-form]"
    }, function() {
        var self = this;
        if (this.el.data("form") != "static") {
            this.event.preventDefault();
            setTimeout(function() {
                Form.get(self.el).submit();
            }, 5);
        }
    });
    function isEnterClickEvent(event) {
        var code = event.keyCode || event.which;
        if (code === 13) {
            return true;
        }
        if (code === 229 && event.originalEvent) {
            var name = event.originalEvent.code;
            if (name === "Enter" || name === "NumpadEnter") {
                return true;
            }
        }
        return false;
    }
    Action.new({
        keydown: 'input[type="text"], input[type="password"], input[type="number"]'
    }, function() {
        if (isEnterClickEvent(this.event)) {
            var event = $.Event("enterdown");
            this.el.trigger(event);
            if (event.isDefaultPrevented()) {
                return;
            }
            var $form = this.el.parents("form");
            if ($form.exists()) {
                if ($form.is("[data-form]")) {
                    var form = Form.get($form);
                    if ($form.is("[data-action]")) {
                        form.submit("event");
                    } else {
                        form.submit();
                    }
                } else {
                    $form.submit();
                }
            }
        }
    });
})();

(function() {
    var Help = AGN.Lib.Help;
    $(document).on("click", "[data-help]", function(e) {
        Help.show($(this));
        e.preventDefault();
    });
})();

(function() {
    $(document).on("click", "label", function(e) {
        var $this = $(this), $target, selectApi;
        $target = $("#" + $this.attr("for"));
        selectApi = $target.data("select2");
        if ($target.length == 1 && selectApi) {
            setTimeout(function() {
                if (!selectApi.opened()) {
                    selectApi.open();
                }
            }, 0);
        }
    });
})();

(function() {
    var History = window.history;
    $(document).on("click", 'a[href^="#"]', function(e) {
        if (e.isDefaultPrevented()) {
            return;
        }
        e.preventDefault();
        setHash($(this).attr("href"));
    });
    $(document).on("click", "[data-one-time]", function() {
        var $this = $(this);
        setTimeout(function() {
            $this.attr("disabled", "disabled");
            if ($this.is("a")) {
                $this.removeAttr("href");
            }
        }, 1);
    });
    function setHash(hash) {
        if (hash === "#") {
            return;
        }
        var address = window.location.href;
        var hashPos = address.indexOf("#");
        if (hashPos >= 0) {
            address = address.substring(0, hashPos);
        }
        History.replaceState(History.state || {}, document.title, address + hash);
    }
})();

(function() {
    var Action = AGN.Lib.Action, Menu = AGN.Lib.Menu;
    Action.new({
        click: ".menu-close"
    }, function() {
        Menu.close();
    });
    Action.new({
        click: ".menu-open"
    }, function() {
        Menu.open();
    });
    Action.new({
        click: ".menu-open"
    }, function() {
        Menu.open();
    });
    $(document).on("click", "main", function() {
        if (Menu.isOpen()) {
            Menu.close();
        }
    });
    $(document).on("");
})();

(function() {
    var Action = AGN.Lib.Action, Messages = AGN.Lib.Messages;
    Action.new({
        click: "[data-msg]"
    }, function() {
        var head = this.el.data("msg"), content = this.el.data("msg-content"), type = this.el.data("msg-type");
        if (this.el.data("msg-system") === "system") {
            var $scope = $(document);
            if ($scope.find(".notification-info").is(":visible")) {
                return false;
            } else {
                Messages(head, content, type);
            }
        } else {
            Messages(head, content, type);
        }
    });
    $(document).on("click", "a[data-msg]", function(e) {
        e.preventDefault();
    });
})();

(function() {
    var Action = AGN.Lib.Action, Modal = AGN.Lib.Modal, Helpers = AGN.Lib.Helpers;
    Action.new({
        click: "[data-modal]"
    }, function() {
        var template = this.el.data("modal"), opts = Helpers.objFromString(this.el.data("modal-set"));
        Modal.createFromTemplate(opts, template);
    });
    $(document).on("hidden.bs.modal", ".modal", function() {
        var $modal = $(this);
        $modal.trigger("modal:close");
        setTimeout(function() {
            $modal.remove();
        }, 100);
    });
    $.fn.modal.Constructor.prototype.enforceFocus = function() {
        var self = this;
        $(document).on("focusin.modal", function(e) {
            if (self.$element[0] !== e.target && !self.$element.has(e.target).length && $(e.target.parentNode).hasClass("cke_contents cke_reset")) {
                self.$element.focus();
            }
        });
    };
})();

(function() {
    var Action = AGN.Lib.Action;
    Action.new({
        click: "[data-password]"
    }, function() {
        var target = this.el.data("password"), text = this.el.data("password-toggle"), $target = $(target);
        this.el.data("password-toggle", this.el.text());
        this.el.text(text);
        if ($target.prop("type") === "password") {
            $target.prop("type", "text");
        } else {
            $target.prop("type", "password");
        }
        this.event.preventDefault();
    });
})();

(function() {
    $(document).on("click", ".js-open-datepicker", function(e) {
        var $this = $(this), $input = $this.parents(".input-group").find(".js-datepicker"), $picker = $input.pickadate("picker");
        $picker.open();
    });
    $(document).on("click", ".js-datepicker", function(e) {
        var $input = $(this), $picker = $input.pickadate("picker");
        $picker.open();
        $input.focus();
    });
})();

(function() {
    $(document).on("click", '[data-dismiss="popover"]', function() {
        var popover = AGN.Lib.Popover.get($(this));
        if (popover) {
            popover.hide();
        }
    });
})();

(function() {
    var Action = AGN.Lib.Action, Modal = AGN.Lib.Modal, Helpers = AGN.Lib.Helpers;
    Action.new({
        click: "[data-popup]"
    }, function() {
        var url = this.el.data("popup"), loc = window.location.href, baseurl = loc.substring(0, loc.lastIndexOf("/"));
        if (!url || url.indexOf("://") <= 0) {
            url = baseurl + "/" + url;
        }
        window.open(url, "help", "width=800,height=600,left=0,top=0,scrollbars=yes");
    });
    $(document).on("click", "a[data-modal]", function(e) {
        e.preventDefault();
    });
    $(document).on("hidden.bs.modal", ".modal", function() {
        var $modal = $(this);
        $modal.trigger("modal:close");
        setTimeout(function() {
            $modal.remove();
        }, 100);
    });
})();

(function() {
    var updateViewport, viewportChanged;
    updateViewport = function() {
        if (viewportChanged) {
            clearTimeout(viewportChanged);
        }
        viewportChanged = setTimeout(function() {
            AGN.Lib.CoreInitializer.run([ "equalizer", "truncate", "sizing", "scrollable", "dropdown-expand" ]);
            _.each(AGN.Lib.Editor.all(), function(editor) {
                editor.resize();
            });
            $(window).trigger("viewportChanged");
        }, 500);
    };
    $(window).on("resize", updateViewport);
})();

(function() {
    var Action = AGN.Lib.Action, Popover = AGN.Lib.Popover, Template = AGN.Lib.Template, Helpers = AGN.Lib.Helpers;
    var BACKDROP_TEMPLATE = '<div class="modal-backdrop in" style="opacity: 0.2;"></div>';
    var POPOVER_TEMPLATE = '<div class="popover bottom support-popover" style="width: 600px; margin-top: 16px;"><div class="popover-content popover-tile"></div></div>';
    function getCurrentPageUrl() {
        var location = window.location;
        var suffixes = [ ".action", ".do" ];
        var i, suffix, suffixPos;
        if (location.origin && location.pathname) {
            var path = (location.pathname + "").replace(/;jsessionid=[a-z0-9]+/i, "");
            for (i = 0; i < suffixes.length; i++) {
                suffix = suffixes[i];
                suffixPos = path.indexOf(suffix);
                if (suffixPos > 0) {
                    path = path.substring(0, suffixPos + suffix.length);
                }
            }
            return location.origin + path + location.search + location.hash;
        } else {
            var page = (location.href + "").replace(/;jsessionid=[a-z0-9]+/i, "");
            for (i = 0; i < suffixes.length; i++) {
                suffix = suffixes[i];
                suffixPos = page.indexOf(suffix);
                if (suffixPos > 0) {
                    var suffixEndPos = suffixPos + suffix.length;
                    var pathEndPos = page.indexOf("?", suffixEndPos);
                    if (pathEndPos < 0) {
                        pathEndPos = page.indexOf("#", suffixEndPos);
                    }
                    if (pathEndPos > 0) {
                        return page.substring(0, suffixEndPos) + page.substring(pathEndPos);
                    } else {
                        return page.substring(0, suffixEndPos);
                    }
                }
            }
        }
        return page;
    }
    Action.new({
        click: "[data-support-type]"
    }, function() {
        var self = this;
        var type = self.el.data("support-type");
        var baseOptions = {
            supportType: type,
            subject: "",
            subjectChangeable: true,
            page: getCurrentPageUrl()
        };
        var options = _.merge({}, baseOptions, Helpers.objFromString(self.el.data("support-options")));
        if (type == "PROBLEM" || type == "FEATURE" || type == "ERROR") {
            var $button = $("#support-select-button");
            Popover.remove($button);
            var $backdrop = $(BACKDROP_TEMPLATE);
            $backdrop.appendTo("body");
            var popover = Popover.new($button, {
                trigger: "manual",
                template: POPOVER_TEMPLATE,
                html: true,
                sanitize: false,
                enableAgnRunAll: true,
                content: Template.text("support-popover-template", options)
            });
            popover.show();
            $backdrop.on("click", function() {
                popover.hide();
            });
            $button.on("hidden.bs.popover", function() {
                $backdrop.remove();
            });
        }
    });
})();

(function() {
    var Action = AGN.Lib.Action;
    var FormBuilder = AGN.Lib.FormBuilder.FormBuilder;
    Action.new({
        "click change": "[data-sync-from]"
    }, function() {
        var sources = this.el.data("sync-from").split(/,\s?/), targets = this.el.data("sync-to").split(/,\s?/);
        _.each(sources, function(source, index) {
            var $source = $(source), $target = $(targets[index]), val = $source.val(), id = $target.attr("id"), editor = $target.data("_editor"), select = $target.data("select2");
            if (window.CKEDITOR && CKEDITOR.instances[id]) {
                CKEDITOR.instances[id].setData(val);
            } else if (editor) {
                editor.val(val);
            } else if (select) {
                $target.select2("val", val);
            } else if (FormBuilder.isCreated("#" + id)) {
                FormBuilder.get("#" + id).setJson(FormBuilder.get(source).getJson());
            } else {
                $target.val(val);
            }
        });
    });
    $(document).on("click", "a[data-sync-from]", function(e) {
        e.preventDefault();
    });
})();

(function() {
    var Tile = AGN.Lib.Tile, Tab = AGN.Lib.Tab, Form = AGN.Lib.Form;
    $(document).on("click", "[data-toggle-tab]", function(e) {
        var $this = $(this), $tileTrigger = Tile.trigger($this), toggleMethod = $this.data("toggle-tab-method") || "show";
        if ($this.is("[data-form-submit]")) {
            var $form = Form.getWrapper($this);
            if ($form.exists() && !Form.get($form).valid()) {
                e.preventDefault();
                return false;
            }
        }
        Tile.show($tileTrigger);
        Tab[toggleMethod]($this);
        e.preventDefault();
        return false;
    });
})();

(function() {
    var Form = AGN.Lib.Form, Confirm = AGN.Lib.Confirm, Helpers = AGN.Lib.Helpers, Page = AGN.Lib.Page;
    $(document).on("click", ".js-table a, .js-table input, .js-table select, .js-table button, .js-table .js-checkable, .js-table .disabled", function(e) {
        e.preventViewLoad = true;
    });
    $(document).on("click", ".js-table-sort", function(e) {
        var $this = $(this), $sortLink = $this.children("a"), $target = $(e.target), href = $sortLink.attr("href");
        if ($target[0] != $sortLink[0]) {
            return;
        }
        if (Form.getWrapper($this).exists()) {
            var form = Form.get($this);
            var params = Helpers.paramsFromUrl(href);
            _.each(params, function(field, fieldName) {
                form.setValue(fieldName, field);
            });
            form.submit();
        } else {
            $.get(href).done(function(resp) {
                Page.render(resp, false);
            });
        }
        e.preventDefault();
    });
    $(document).on("click", ".js-table-paginate", function(e) {
        var $this = $(this), href = $this.attr("href"), form = Form.get($this), params = Helpers.paramsFromUrl(href);
        _.each(params, function(field, fieldName) {
            form.setValue(fieldName, field);
        });
        form.submit();
        e.preventDefault();
        var $tile = $this.closest(".tile");
        if ($tile.exists()) {
            var top = $tile.offset().top;
            if (window.scrollY > top) {
                window.scrollTo(0, top - 150);
            }
        } else {
            window.scrollTo(0, 0);
        }
    });
    $(document).on("click", ".js-row-delete", function(e) {
        var $this = $(this), href = $this.is("button") ? $this.data("url") : $this.attr("href"), form = Form.get($this), jqxhr;
        if (href) {
            jqxhr = $.get(href);
            jqxhr.done(function(resp) {
                var $resp = $(resp), $modal;
                $modal = $resp.filter(".modal").add($resp.find(".modal"));
                if ($modal.length != 1) {
                    form.updateHtml(resp);
                    return;
                }
                Confirm.create(resp).done(function(resp) {
                    $this.closest("tr").remove();
                    form.updateHtml(resp);
                });
            });
        }
        e.preventDefault();
    });
    $(document).on("click", ".js-table tr", function(e) {
        var $this = $(this), target;
        if (e.preventViewLoad) {
            return;
        }
        target = $this.data("link");
        if (typeof target !== "undefined") {
            window.location.href = target;
        }
    });
    $(document).on("click", '.js-checkable label, .js-checkable input[type="checkbox"], .js-checkable input[type="radio"]', function(e) {
        e.stopPropagation();
    });
    $(document).on("click", ".js-checkable", function(e) {
        var $this = $(this), $targets, $target;
        $targets = $this.find('input[type="checkbox"], input[type="radio"]');
        if ($targets.length) {
            _.each($targets, function(target) {
                $target = $(target);
                if (!$target.prop("disabled")) {
                    $target.prop("checked", !$target.prop("checked"));
                    $target.trigger("change");
                }
            });
        }
    });
    $(document).on("click", ".disabled", function(e) {
        e.preventDefault();
    });
})();

(function() {
    var Tile = AGN.Lib.Tile;
    $(document).on("click", "[data-toggle-tile]", function(e) {
        Tile.toggle($(this));
        e.preventDefault();
    });
    $(document).on("click", "[data-toggle-tile-all]", function(e) {
        var action = $(this).data("toggle-tile-all");
        _.each($("[data-toggle-tile]"), function(tile) {
            var trigger = $(tile);
            if (action == "expand") {
                Tile.show(trigger);
            } else {
                Tile.hide(trigger);
            }
            e.preventDefault();
        });
    });
})();

(function() {
    $(document).on("change", "[data-toggle-usability]", function() {
        var $this = $(this), targets = $this.data("toggle-usability"), $targets = $(document).find(targets);
        _.each($targets, function(target) {
            var $target = $(target);
            if ($target.prop("disabled")) {
                $target.prop("disabled", false);
            } else {
                $target.prop("disabled", true);
            }
        });
    });
})();

(function() {
    var Tooltip = AGN.Lib.Tooltip;
    $(window).on("load", function() {
        var body = $("body");
        if (AGN.isIE) {
            body.on("DOMNodeInserted", "[data-tooltip], [data-tooltip-help]", function(event) {
                var $e = $(event.target);
                Tooltip.create($e, Tooltip.options($e));
            });
        } else {
            body.on("DOMNodeInserted", function(event) {
                $(event.target).all("[data-tooltip], [data-tooltip-help]").each(function() {
                    var $e = $(this);
                    Tooltip.create($e, Tooltip.options($e));
                });
            });
        }
    });
})();

(function() {
    var Action = AGN.Lib.Action, View = AGN.Lib.View;
    Action.new({
        change: "[data-view]"
    }, function() {
        View.trigger(this.el);
        this.el.trigger("click.bs.dropdown.data-api");
    });
})();

(function() {
    var Form = AGN.Lib.Form, Editor = AGN.Lib.Editor;
    $(document).on("tile:show", function(e) {
        var $target = $(e.target);
        var $editor = $target.find(".js-wysiwyg");
        var editorId = $editor.attr("id");
        if ($editor.length === 1) {
            var options = getEditorOptions($editor);
            window.createEditorExt(editorId, options.width, options.height, options.browseMailingId, options.isFullHtml, options.isFullHeight, options.allowExternalScript);
            if (options.isFullHeight) {
                CKEDITOR.instances[editorId].on("instanceReady", getOnInstanceReadyListener($editor));
            }
        }
    });
    $(document).on("tile:hide modal:close", function(e) {
        $(e.target).find(".js-wysiwyg").each(function() {
            if (CKEDITOR.instances[$(this).attr("id")]) {
                CKEDITOR.instances[$(this).attr("id")].updateElement();
            }
            if (isFullHeightEditor($(this))) {
                $(window).off("resize." + getResizeAlias($(this)));
            }
            Editor.get($(this)).val($(this).val());
            window.removeEditor($(this).attr("id"));
        });
    });
    $(document).on("form:submit", function(e) {
        var $editor = $(e.target).find(".js-wysiwyg");
        if ($editor.length > 0 && window.removeAllEditors) {
            window.removeAllEditors();
        }
    });
    function getMailingId($editor) {
        var mailingId = $editor.data("browse-mailing-id");
        if (!!mailingId) {
            return mailingId;
        }
        var formId = $editor.data("form-target");
        var $form = !!formId ? $(formId) : null;
        if (!$form || $form.length === 0) {
            return null;
        }
        var form = Form.get($form);
        mailingId = form.getValue("mailingID");
        if (!mailingId) {
            mailingId = form.getValue("mailingId");
        }
        return mailingId;
    }
    function getOnInstanceReadyListener($textAreaContainer) {
        return function(event) {
            var width = $textAreaContainer.parent().width();
            var height = $textAreaContainer.parent().height();
            event.editor.resize(width, height);
            event.editor.resresize_enabledze = false;
            $(window).on("resize." + getResizeAlias($textAreaContainer), getResizeListener($textAreaContainer));
        };
    }
    var getResizeListener = function($textAreaContainer) {
        return function() {
            var $parent = $textAreaContainer.parent();
            CKEDITOR.instances[$textAreaContainer.attr("id")].resize($parent.width(), $parent.height());
        };
    };
    var getResizeAlias = function($textAreaContainer) {
        return "ck-editor-" + $textAreaContainer.attr("id");
    };
    var isFullHeightEditor = function($textAreaContainer) {
        return !!$textAreaContainer.data("full-height-editor");
    };
    var getEditorOptions = function($editor) {
        var options = {};
        options.isFullHtml = !!$editor.data("full-tags");
        options.isFullHeight = isFullHeightEditor($editor);
        options.browseMailingId = getMailingId($editor);
        options.height = options.isFullHeight ? 0 : $editor.height();
        options.width = options.isFullHeight ? $editor.parent().width() : "100%";
        options.allowExternalScript = false;
        return _.extend(options, AGN.Lib.Helpers.objFromString($editor.data("editor-options")));
    };
})();

AGN.Lib.Validator.new("action", {
    valid: function($e, options, isFieldsValid) {
        return isFieldsValid && !this.errors($e, options).length;
    },
    errors: function($e, options) {
        var errors = [];
        if ($("#serviceMailOperation").length) this.validateSendServiceOperation(errors);
        return errors;
    },
    validateSendServiceOperation: function(errors) {
        validateEmailList($("input[id$=toAddress]"), errors, "triggerManager.operation.serviceMail.error.recipientAddress");
        validateEmail($("input[id$=fromAddress]"), errors, "triggerManager.operation.serviceMail.error.senderAddress");
        validateEmail($("input[id$=replyAddress]"), errors, "triggerManager.operation.serviceMail.error.replyAddress");
        validateSubject($("input[id$=subjectLine]"), errors);
    }
});

function validateEmailList($fields, errors, errorCode) {
    $fields.each(function(i, field) {
        var $field = $(field);
        var emails = getEmailsFromField($field);
        if (!emails || !isValidEmailList(emails)) {
            errors.push({
                field: $field,
                msg: t(errorCode)
            });
        } else {
            $field.val(emails.join(","));
        }
    });
}

function validateEmail($fields, errors, errorCode) {
    $fields.each(function(i, field) {
        var $field = $(field);
        var value = $field.val().trim();
        if (!isValidEmail(value)) {
            errors.push({
                field: $field,
                msg: t(errorCode)
            });
        } else {
            $field.val(value);
        }
    });
}

function validateSubject($fields, errors) {
    $fields.each(function(i, field) {
        var $field = $(field);
        var value = $field.val().trim();
        if (!value || value.length < 3) {
            errors.push({
                field: $field,
                msg: t("triggerManager.operation.serviceMail.error.subjectToShort")
            });
        } else if (value && value.length > 200) {
            errors.push({
                field: $field,
                msg: t("triggerManager.operation.serviceMail.error.subjectToLong")
            });
        } else {
            $field.val(value);
        }
    });
}

function getEmailsFromField($field) {
    var value = $field.val();
    var emails = value.trim() && value.trim().split(/[ ,|]+/);
    _.map(emails, _.trim);
    return emails;
}

function isValidEmailList(list) {
    for (var i = 0; i < list.length; i++) {
        if (!isValidEmail(list[i])) {
            return false;
        }
    }
    return true;
}

function isValidEmail(email) {
    var re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    return re.test(String(email).toLowerCase());
}

(function() {
    AGN.Lib.Validator.new("export/form", {
        valid: function($e, options) {
            return !this.errors($e, options).length;
        },
        errors: function($e, options) {
            var errors = [];
            validateColumnMappings(errors);
            return errors;
        }
    });
    function validateColumnMappings(errors) {
        var allCustomColumnNames = [];
        _.each($("#columnMappings tbody").find("[data-column-mapping-row]"), function(row) {
            var $row = $(row);
            var $columnNameField = $row.find("[data-column-name]");
            var name = getColumnName($columnNameField);
            checkColumnNameValid($columnNameField, errors);
            checkColumnNameUnique(name, allCustomColumnNames, errors, $columnNameField);
            allCustomColumnNames.push(name.toLowerCase());
        });
    }
    function checkColumnNameValid($columnNameField, errors) {
        var name = getColumnName($columnNameField);
        if (!$columnNameField.is(":last-child") && name.length < 3 || $columnNameField.is(":last-child") && name && name.length < 3) {
            errors.push({
                field: $columnNameField,
                msg: t("export.columnMapping.error.nameToShort")
            });
            return;
        }
        if (!$columnNameField.is(":last-child") && !/^[a-zA-Z0-9_]{3,}$/.test(name) || $columnNameField.is(":last-child") && name && !/^[a-zA-Z0-9_]{3,}$/.test(name)) {
            errors.push({
                field: $columnNameField,
                msg: t("export.columnMapping.error.invalidColName")
            });
        }
    }
    function checkColumnNameUnique(name, allCustomColumnNames, errors, $columnNameField) {
        if (name && allCustomColumnNames.indexOf(name.toLowerCase()) >= 0) {
            errors.push({
                field: $columnNameField,
                msg: t("export.columnMapping.error.duplicate")
            });
        }
        if (getProfileFieldColumnNames().indexOf(name.toLowerCase()) >= 0) {
            errors.push({
                field: $columnNameField,
                msg: t("export.columnMapping.error.exist")
            });
        }
    }
    function getColumnName($row) {
        return $row.val().trim();
    }
    function getProfileFieldColumnNames() {
        return $.map($('select[name="columns"] option'), function(option) {
            return option.value.toLowerCase();
        });
    }
})();

AGN.Lib.CoreInitializer.new("import-profile-mappings-validator", function() {
    const DATE_FORMAT = "dd.mm.yyyy";
    const DONT_IMPORT_COL_OPTION = "do-not-import-column";
    var config;
    AGN.Lib.Validator.new("import-profile-mappings/form", {
        init: function() {
            const $config = $("#config\\:import-profile-mappings-validator");
            config = $config.exists() ? $config.json() : {};
        },
        valid: function($e, options) {
            return !this.errors($e, options).length;
        },
        errors: function($e, options) {
            const errors = [];
            if ($("#columnMappings").length) {
                validateDefaultValues(errors);
            }
            return errors;
        }
    });
    function isValidDataLength(columnInfo, value) {
        return value.length <= columnInfo.maxDataSize;
    }
    function getDefValFieldValue($defValField) {
        var value = $defValField.val();
        if (value[0] == "'" && value[value.length - 1] == "'") {
            value = value.substring(1, value.length - 1);
        }
        return value;
    }
    function validateDefValField($defValField, errors) {
        const value = getDefValFieldValue($defValField);
        if (value && getColNameByDefValField($defValField) !== DONT_IMPORT_COL_OPTION) {
            const columnInfo = getValFieldColumnInfo($defValField);
            const dataType = columnInfo.dataType.toLowerCase();
            if (columnInfo.column === "email" && !AGN.Lib.Helpers.isValidEmail(value)) {
                errors.push({
                    field: $defValField,
                    msg: t("import.columnMapping.error.invalidEmail")
                });
            } else if (dataType === "date" || dataType === "datetime") {
                if (isDbDateFunction($defValField.val().trim())) {
                    return;
                }
                validateDateOrDateTimeValue(dataType, value, errors, $defValField);
            } else if (!isValidValueForDataType(dataType, value)) {
                errors.push({
                    field: $defValField,
                    msg: t("import.columnMapping.error.type", dataType)
                });
            } else if (!isValidDataLength(columnInfo, value)) {
                errors.push({
                    field: $defValField,
                    msg: t("import.columnMapping.error.length", columnInfo.maxDataSize)
                });
            }
        }
    }
    function validateDateOrDateTimeValue(dataType, value, errors, $defValField) {
        if (!value || !isValidValueForDataType(dataType, value)) {
            errors.push({
                field: $defValField,
                msg: t("import.columnMapping.error.dateFormat", dataType === "datetime" ? DATE_FORMAT + " hh:mm" : DATE_FORMAT)
            });
        }
    }
    function validateNewMappingDefVal(errors) {
        const $defValField = $("[name=default-value-new]");
        if (getColNameByDefValField($defValField) !== DONT_IMPORT_COL_OPTION && !isCurrentTimeChecked()) {
            validateDefValField($defValField, errors);
        }
    }
    function validateDefaultValues(errors) {
        _.each($("#columnMappings tbody").find("[data-mapping-defaultValue]"), function(defValueField) {
            validateDefValField($(defValueField), errors);
        });
        validateNewMappingDefVal(errors);
    }
    function getValFieldColumnInfo($defValField) {
        return config.columns[getColNameByDefValField($defValField)];
    }
    function getColNameByDefValField($defValField) {
        return $defValField.attr("name") === "default-value-new" ? $("#database-column-new").val() : $defValField.closest("tr").find("[data-mapping-db-column]").first().val();
    }
    function isValidValueForDataType(dataType, value) {
        switch (dataType) {
          case "numeric":
          case "float":
          case "double":
            return isNumeric(value);

          case "integer":
            return isInteger(value);

          case "date":
            return isValidDate(value);

          case "datetime":
            return isValidDateTime(value);

          default:
            return true;
        }
    }
    function isDbDateFunction(val) {
        return /^(now|now\(\)|sysdate|sysdate\(\)|current_timestamp|current_timestamp\(\)|today)\s*([+\-]\s*\d+\s*)?$/im.test(val);
    }
    function isValidDate(value) {
        return moment(value, DATE_FORMAT.toUpperCase(), true).isValid();
    }
    function isValidDateTime(value) {
        const dateAndTime = value.split(" ");
        return isValidDate(dateAndTime[0]) && /^(0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$/.test(dateAndTime[1]);
    }
    function isNumeric(n) {
        return !isNaN(parseFloat(n)) && isFinite(n);
    }
    function isInteger(value) {
        return /^-?\d+$/.test(value);
    }
    function isCurrentTimeChecked() {
        const currentTimeCheckbox = $("[data-action=change-date-input]");
        return currentTimeCheckbox.length && currentTimeCheckbox.is(":checked");
    }
});

AGN.Lib.Validator.new("length", {
    valid: function($e, options) {
        return !this.errors($e, options).length;
    },
    errors: function($e, options) {
        var content = $e.val();
        var errors = [];
        if (content) {
            if (options.min >= 0 && content.length < options.min) {
                errors.push({
                    field: $e,
                    msg: t("fields.errors.string_exceed_min_length", options.min)
                });
            } else if (options.max >= 0 && content.length > options.max) {
                errors.push({
                    field: $e,
                    msg: t("fields.errors.string_exceed_max_length", options.max)
                });
            }
        } else if (options.min > 0 || options.required === true) {
            errors.push({
                field: $e,
                msg: t("fields.required.errors.missing")
            });
        }
        return errors;
    }
});

AGN.Lib.Validator.new("logon-new-password/form", {
    valid: function() {
        return !this.errors().length;
    },
    errors: function() {
        var errors = [];
        var $input1 = $("#password");
        var $input2 = $("#password-repeat");
        var password = $input1.val();
        if (!$.trim(password)) {
            errors.push({
                field: $input1,
                msg: t("fields.required.errors.missing")
            });
        } else if (password != $input2.val()) {
            errors.push({
                field: $input2,
                msg: t("fields.password.errors.notMatching")
            });
        }
        return errors;
    }
});

AGN.Lib.Validator.new("mailing-priorities/form", {
    valid: function() {
        if ($("#priorityCount").val() > 0) {
            return true;
        }
        AGN.Lib.Messages(t("defaults.error"), t("error.mailing.invalidPriorityCount"), "alert");
        return false;
    },
    errors: function() {
        return [];
    }
});

AGN.Lib.Validator.new("mailinglist-exist", {
    valid: function($e, options) {
        return !this.errors($e, options).length;
    },
    errors: function($e, options) {
        var content = $e.val();
        var errors = AGN.Lib.Validator.get("required-id").errors($e, options);
        if (errors && errors.length <= 0 && options && content && options.removedMailinglistId == content.trim()) {
            errors.push({
                field: $e,
                msg: t("fields.mailinglist.errors.removed")
            });
        }
        return errors;
    }
});

AGN.Lib.Validator.new("max-length-validator", {
    valid: function($e, options) {
        return !this.errors($e, options).length;
    },
    errors: function($e, options) {
        var content = $e.val();
        var errors = [];
        if ($e.hasClass("js-wysiwyg") && !content) {
            content = $("#cke_" + $e.attr("id")).find("iframe").contents().find("body").text();
        }
        if (content) {
            if (content.length > options.max) {
                errors.push({
                    field: $e,
                    msg: t("fields.errors.contentLengthExceedsLimit", options.max)
                });
            }
        } else if (options.required === true) {
            errors.push({
                field: $e,
                msg: t("fields.required.errors.missing")
            });
        }
        return errors;
    }
});

(function() {
    AGN.Lib.Validator.new("number", {
        valid: function($e, options) {
            return !this.errors($e, options).length;
        },
        errors: function($e, options) {
            var errors = [];
            if (options.excludeHidden && $e.is(":hidden")) {
                return [];
            }
            var exactValue = $e.val();
            if (exactValue) {
                var value = options.float === true ? parseFloat(exactValue) : parseInt(exactValue);
                if (isNaN(value)) {
                    errors.push({
                        field: $e,
                        msg: t("fields.errors.number_nan")
                    });
                } else {
                    if (value < options.min) {
                        errors.push({
                            field: $e,
                            msg: t("fields.errors.number_exceed_min", options.min - 1)
                        });
                    } else if (value > options.max) {
                        errors.push({
                            field: $e,
                            msg: t("fields.errors.number_exceed_max", options.max)
                        });
                    } else if (options.strict === true) {
                        if ($.trim(exactValue) !== value.toString()) {
                            if (options.float === true) {
                                errors.push({
                                    field: $e,
                                    msg: t("fields.errors.number_not_double")
                                });
                            } else {
                                errors.push({
                                    field: $e,
                                    msg: t("fields.errors.number_not_integer")
                                });
                            }
                        }
                    }
                }
            } else if (options.required === true) {
                errors.push({
                    field: $e,
                    msg: t("fields.required.errors.missing")
                });
            }
            return errors;
        }
    });
})();

AGN.Lib.Validator.new("phone-number", {
    valid: function($e, options) {
        return !this.errors($e, options).length;
    },
    errors: function($e, options) {
        var content = $.trim($e.val());
        var errors = [];
        var TOKEN_BEGIN = 0;
        var TOKEN_PLUS = 1;
        var TOKEN_DIGIT = 3;
        var TOKEN_SEPARATOR = 4;
        var TOKEN_LPAREN = 5;
        var TOKEN_RPAREN = 6;
        if (content) {
            var previousToken = TOKEN_BEGIN;
            var hasViolations = false;
            var insideParentheses = false;
            var digitsCount = 0;
            for (var i = 0; i < content.length; i++) {
                var c = content.charAt(i);
                if (c >= "0" && c <= "9") {
                    digitsCount++;
                    previousToken = TOKEN_DIGIT;
                } else if (c == "." || c == "-" || c == "/") {
                    if (previousToken == TOKEN_DIGIT || previousToken == TOKEN_RPAREN) {
                        previousToken = TOKEN_SEPARATOR;
                    } else {
                        hasViolations = true;
                        break;
                    }
                } else if (c == "(") {
                    if (insideParentheses) {
                        hasViolations = true;
                        break;
                    }
                    previousToken = TOKEN_LPAREN;
                    insideParentheses = true;
                } else if (c == ")") {
                    if (previousToken == TOKEN_DIGIT && insideParentheses) {
                        previousToken = TOKEN_RPAREN;
                        insideParentheses = false;
                    } else {
                        hasViolations = true;
                        break;
                    }
                } else if (c == "+") {
                    if (previousToken == TOKEN_BEGIN) {
                        previousToken = TOKEN_PLUS;
                    } else {
                        hasViolations = true;
                        break;
                    }
                } else if (!/\s/.test(c)) {
                    hasViolations = true;
                    break;
                }
            }
            if (hasViolations || insideParentheses || digitsCount < 3 || digitsCount > 20) {
                errors.push({
                    field: $e,
                    msg: t("fields.errors.phone_number_invalid")
                });
            }
        } else if (options.required === true) {
            errors.push({
                field: $e,
                msg: t("fields.required.errors.missing")
            });
        }
        return errors;
    }
});

(function() {
    AGN.Lib.Validator.new("reference-table/form", {
        valid: function($e, options) {
            return !this.errors($e, options).length;
        },
        errors: function($e, options) {
            var errors = [];
            var $name = $('[name="shortname"]');
            var $keyColumn = $('[name="keyColumn"]');
            if ($name.length) validateTextField($name, errors, 5, options.isVoucher ? 27 : 29, new RegExp("^[a-z]*$", "i"), "referenceTables.table.error.name");
            if ($keyColumn.length) validateTextField($keyColumn, errors, 3, 30, /^(?![0-9_])[a-z0-9_]*$/, "referenceTables.table.error.keyColumn");
            return errors;
        }
    });
    function validateTextField($field, errors, minLength, maxLength, regex, errorMessage) {
        if (!validateFieldLength($field, errors, minLength, maxLength)) {
            return;
        }
        validateFieldPattern($field, errors, regex, errorMessage);
    }
    function validateFieldLength($field, errors, min, max) {
        var lengthErrors = AGN.Lib.Validator.get("length").errors($field, {
            min: min,
            max: max,
            required: true
        });
        if (lengthErrors.length) {
            lengthErrors.forEach(function(error) {
                errors.push(error);
            });
            return false;
        }
        return true;
    }
    function validateFieldPattern($field, errors, regex, errorMessage) {
        if (!$field.val().match(regex)) {
            errors.push({
                field: $field,
                msg: t(errorMessage)
            });
        }
    }
})();

AGN.Lib.Validator.new("reject-script-element", {
    valid: function($e, options) {
        return !this.errors($e, options).length;
    },
    errors: function($e, options) {
        var errors = [];
        var scriptElement = new DOMParser().parseFromString($e.val(), "text/html").querySelector("script");
        if (scriptElement) {
            errors.push({
                field: $e,
                msg: t("fields.errors.illegal_script_element")
            });
        }
        return errors;
    }
});

AGN.Lib.Validator.new("required-id", {
    valid: function($e, options) {
        return !this.errors($e, options).length;
    },
    errors: function($e, options) {
        if ($e.data("select2") && !$e.parent().find(".select2-container").is(":visible")) {
            return [];
        }
        var content = $e.val();
        var value = parseInt(content);
        var errors = [];
        if (isNaN(value) || value.toString() !== content.toString().trim() || value <= 0 && options.positive !== false) {
            errors.push({
                field: $e,
                msg: t("fields.required.errors.missing")
            });
        }
        return errors;
    }
});

AGN.Lib.Validator.new("unique-mobile-base", {
    valid: function($e, options) {
        return !this.errors($e, options).length;
    },
    errors: function($e, options) {
        var value = AGN.Lib.Select.get($e).getSelectedValue();
        var id = $e.attr("id");
        var errors = [];
        if (!this.isUniqueMobileBase(value, id)) {
            errors.push({
                field: $e,
                msg: t("fields.mediapool.errors.mobile_base_duplicate")
            });
        }
        return errors;
    },
    isUniqueMobileBase: function(value, excludeId) {
        if (value == "") {
            return true;
        }
        var duplicates = $("[id^=image-mobile-base]:not(#" + excludeId + ")").filter(function() {
            var $elem = $(this);
            return AGN.Lib.Select.get($elem).getSelectedValue() === value;
        });
        return duplicates.length === 0;
    }
});

AGN.Lib.Validator.new("upload-file/form", {
    valid: function(uploadForm, options) {
        var isSuccessfully = true;
        var $upload = $('[data-initializer="upload"]');
        if ($upload.exists() && $upload.data("upload-selection").length < 1) {
            AGN.Lib.Messages(t("defaults.error"), t("error.upload.file"), "alert");
            isSuccessfully = false;
        }
        return isSuccessfully && !this.errors(uploadForm, options).length;
    },
    errors: function(uploadForm, options) {
        const NAME_TOO_SHORT_MSG_KEY = "error.workflow.shortName";
        const REQUIRED_MSG_KEY = "fields.required.errors.missing";
        var validationRules = [ {
            field: $("#name"),
            minLength: {
                val: 3,
                msgKey: NAME_TOO_SHORT_MSG_KEY
            },
            maxLength: 99
        }, {
            field: $("#firstName"),
            minLength: {
                val: 3,
                msgKey: NAME_TOO_SHORT_MSG_KEY
            },
            maxLength: 99
        }, {
            field: $("#phone"),
            minLength: {
                val: 3,
                msgKey: REQUIRED_MSG_KEY
            },
            maxLength: 99
        }, {
            field: $("#email"),
            maxLength: 99,
            regexpRules: [ {
                regexp: /\S+@\S+\.\S{2,}/,
                message: t("error.upload.email")
            } ]
        } ];
        var errors = [];
        validationRules.forEach(function(rule) {
            var field = rule.field;
            var value = field.val();
            if (!value || value.length < 1) {
                errors.push({
                    field: field,
                    msg: t(REQUIRED_MSG_KEY)
                });
                return;
            }
            if (rule.minLength && value.length < rule.minLength.val) {
                errors.push({
                    field: field,
                    msg: t(rule.minLength.msgKey)
                });
                return;
            }
            if (rule.maxLength && value.length > rule.maxLength) {
                errors.push({
                    field: field,
                    msg: t("fields.errors.contentLengthExceedsLimit", rule.maxLength)
                });
                return;
            }
            if (rule.regexpRules && rule.regexpRules.length > 0) {
                for (var i = 0; i < rule.regexpRules.length; ++i) {
                    var regexpRule = rule.regexpRules[i];
                    if (!value.match(regexpRule.regexp)) {
                        errors.push({
                            field: field,
                            msg: regexpRule.message
                        });
                        return;
                    }
                }
            }
        });
        return errors;
    }
});

AGN.Lib.Validator.new("userform-edit/form", {
    valid: function($e, options) {
        return !this.errors($e, options).length;
    },
    errors: function($e, options) {
        var errors = [];
        var formName = $('[name="formName"]');
        if (!formName.val().match(/^[a-zA-Z0-9-_]+$/gi)) {
            errors.push({
                field: formName,
                msg: t("userform.error.invalid_name")
            });
        }
        this.validateTemplateField(errors, $("#successTemplate"), "SUCCESS");
        this.validateTemplateField(errors, $("#errorTemplate"), "ERROR");
        return errors;
    },
    validateTemplateField: function(errors, field, type) {
        if (!this.validateDirectives(errors, field)) {
            return false;
        }
        if (!this.validateHrefPattern(errors, field, type)) {
            return false;
        }
    },
    validateDirectives: function(errors, field) {
        var res = field.val().match(/#(?:include|parse)/gi);
        if (res) {
            errors.push({
                field: field,
                msg: t("userform.error.illegal_directive", res.join(", "))
            });
            return false;
        }
        return true;
    },
    validateHrefPattern: function(errors, field, type) {
        var value = field.val();
        var res = value.search(/\shref\s*=\s*(["'])\s/gi);
        if (res != -1) {
            var lineNumber = value.slice(0, res).match(/\r?\n/g).length + 1;
            errors.push({
                field: field,
                msg: t("userform.error.invalid_link", type, lineNumber)
            });
            return false;
        }
        return true;
    }
});

AGN.Lib.Controller.new("action-view", function() {
    var activeModules = [];
    var moduleList;
    var operationTypes = {};
    const Select = AGN.Lib.Select;
    function ModuleList() {
        var self = this;
        self.$container = $("#module-list");
        self.$container.on("remove-module", function() {
            var list = self.$container.find("[data-action-module] .headline span.module-count");
            $.each(list, function(index, el) {
                $(el).html(index + 1 + ".");
            });
        });
        self.$container.on("add-new-module", function() {
            var allModules = self.$container.find("[data-action-module]");
            var lastModule = allModules.last();
            lastModule.find(".headline span.module-count").html(allModules.length + ".");
        });
    }
    ModuleList.prototype.clean = function() {
        this.$container.empty();
    };
    ModuleList.prototype.getNextIndex = function() {
        var list = this.$container.find("[data-module-content");
        var index = 0;
        if (list.length > 0) {
            var lastIndex = list.last().data("module-content");
            index = lastIndex + 1;
        }
        return index;
    };
    ModuleList.prototype.addModule = function(module) {
        if (module && module.type) {
            var self = this;
            module.index = self.getNextIndex();
            var moduleTile = AGN.Lib.Template.dom("common-module-data", {
                moduleName: t("triggerManager.operation." + module.type)
            });
            var moduleContent = AGN.Lib.Template.text("module-" + module.type, module.getParameters());
            moduleTile.filter(".inline-tile").append(moduleContent);
            self.$container.append(moduleTile);
            AGN.runAll(moduleTile);
            self.$container.trigger("add-new-module");
        }
    };
    ModuleList.prototype.deleteModule = function(index) {
        if (index >= 0) {
            var content = this.$container.find("[data-module-content=" + index + "]");
            var module = content.parent("[data-action-module]");
            var separator = module.next(".tile-separator");
            module.remove();
            separator.remove();
            this.$container.trigger("remove-module");
            activeModules = activeModules.filter(function(module) {
                return module.index !== index;
            });
        }
    };
    ModuleList.prototype.toJson = function() {
        var json = [];
        this.$container.find("[data-module-content]").each(function(index, m) {
            json.push(Module.toJson($(m), index));
        });
        return json;
    };
    ModuleList.prototype.getSubmissionJson = function() {
        var self = this;
        return JSON.stringify(self.toJson());
    };
    function Module(type, data, count) {
        this.type = type;
        this.index = count || 0;
        this.id = data.id || 0;
        this.data = $.extend(Module.defaults(type), data);
    }
    Module.defaults = function(type) {
        var data = {};
        switch (type) {
          case "ActivateDoubleOptIn":
            data.forAllLists = false;
            data.mediaTypeCode = 0;
            break;

          case "ContentView":
            data.tagName = "";
            break;

          case "ExecuteScript":
            data.script = "";
            break;

          case "GetArchiveList":
            data.campaignID = 0;
            break;

          case "GetArchiveMailing":
            data.expireDate = null;
            break;

          case "GetCustomer":
            data.loadAlways = false;
            break;

          case "IdentifyCustomer":
            data.keyColumn = "";
            data.passColumn = "";
            break;

          case "SendMailing":
            data.mailingID = 0;
            data.delayMinutes = 0;
            data.bcc = "";
            data.userStatusesOption = 1;
            break;

          case "ServiceMail":
            data.toAddress = "";
            data.fromAddress = "";
            data.replyAddress = "";
            data.subjectLine = "";
            data.mailtype = 0;
            data.textMail = "";
            data.htmlMail = "";
            break;

          case "SubscribeCustomer":
            data.doubleCheck = false;
            data.keyColumn = "";
            data.doubleOptIn = false;
            break;

          case "UnsubscribeCustomer":
            data.mailinglistIds = [];
            data.allMailinglistsSelected = false;
            data.additionalMailinglists = false;
            break;

          case "UpdateCustomer":
            data.useTrack = false;
            data.columnName = "";
            data.updateValue = "";
            data.updateType = 1;
            data.trackingPointId = -1;
            break;
        }
        data.readonly = false;
        return data;
    };
    Module.toJson = function($module, index) {
        var moduleJson = {};
        moduleJson.index = index;
        $module.find('[name^="modules[]"]').each(function(i, field) {
            var $field = $(field);
            var name = $field.prop("name") || "";
            var fieldName = name.replace("modules[].", "");
            var value = "";
            if ($field.is("select")) {
                value = Select.get($field).getSelectedValue();
            } else if ($field.is("input") && $field.prop("type") === "checkbox") {
                value = $field.prop("checked");
            } else {
                value = $field.val();
            }
            moduleJson[fieldName] = value;
        });
        return $.extend(Module.defaults(moduleJson.type), moduleJson);
    };
    Module.prototype.getParameters = function() {
        var extraData = {
            type: this.type,
            index: this.index,
            id: this.id
        };
        return _.merge({}, this.data, extraData);
    };
    Module.create = function(type) {
        return new Module(type, {});
    };
    Module.deserialize = function(object, count) {
        var type = operationTypes[object.operationType];
        return new Module(type, object, count);
    };
    this.addDomInitializer("action-view", function() {
        var $form = $(this.el);
        var form = AGN.Lib.Form.get($form);
        form.loader().show();
        var config = this.config;
        operationTypes = this.config.operationTypes;
        moduleList = new ModuleList();
        moduleList.clean();
        var modules = [];
        if (config.modules) {
            modules = JSON.parse(config.modules).map(function(object, count) {
                return Module.deserialize(object, count);
            });
        }
        modules.forEach(function(elem) {
            moduleList.addModule(elem);
        });
        form.initFields();
        $form.removeClass("hidden");
        form.loader().hide();
    });
    function getModulesByType(targetType) {
        return activeModules.filter(function(module) {
            return module.type === targetType;
        });
    }
    this.addAction({
        click: "add-new-module"
    }, function() {
        var $elem = $(this.el);
        var config = _.merge({}, {}, AGN.Lib.Helpers.objFromString($elem.data("config")));
        var typeSelector = $(config.moduleTypeSelector);
        var module = Module.create(typeSelector.val());
        if (module.type === "SendMailing") {
            if (getModulesByType("ActivateDoubleOptIn").length > 0) {
                module.data.userStatusesOption = 0;
            }
        }
        moduleList.addModule(module);
        activeModules.push(module);
        AGN.Lib.Form.get($elem).initFields();
        if (module.type === "ActivateDoubleOptIn") {
            const sendMailingModules = getModulesByType("SendMailing");
            sendMailingModules.forEach(function(module) {
                const idSelector = "#module-" + module.index + "-userStatusesOption";
                const $userStatusesSelect = $(idSelector);
                Select.get($userStatusesSelect).selectFirstValue();
            });
        }
    });
    this.addAction({
        click: "action-delete-module"
    }, function() {
        var $elem = $(this.el);
        moduleList.deleteModule($elem.data("property-id"));
    });
    this.addAction({
        submission: "save-action-data"
    }, function() {
        var form = AGN.Lib.Form.get($(this.el));
        form.setValueOnce("modulesSchema", moduleList.getSubmissionJson());
        form.submit();
    });
    this.addDomInitializer("update-customer-module", function() {
        var $el = $(this.el);
        var checkedUseTrack = $el.find('[data-action="toggle-if-first"]:checked');
        toggleTrackingPointData($el, checkedUseTrack.exists());
    });
    this.addAction({
        click: "toggle-if-first"
    }, function() {
        var $el = $(this.el);
        toggleTrackingPointData($el, $el.prop("checked"));
    });
    function toggleTrackingPointData($el, isEnabled) {
        var $elModule = $($el.closest("[data-action-module]"));
        var trackingPointField = $elModule.find("[data-useTrack-trackingPointId]");
        var updateValueField = $elModule.find("[data-useTrack-updateValue]");
        if (!trackingPointField.exists()) {
            updateValueField.show();
            return;
        }
        if ($elModule.index() === 0) {
            if (isEnabled) {
                trackingPointField.show();
                updateValueField.hide();
            } else {
                trackingPointField.hide();
                updateValueField.show();
            }
        }
    }
});

AGN.Lib.Controller.new("admin-enabling", function() {
    this.addAction({
        click: "save-approved-mailing-lists"
    }, function() {
        var $element = this.el;
        var $form = AGN.Lib.Form.getWrapper($element);
        prepareDisabledMailinglistsBeforeSaving($form);
        var formObj = AGN.Lib.Form.get($form);
        formObj.submit().done(function(resp) {
            if (resp.success === true) {
                AGN.Lib.JsonMessages(resp.popups, true);
                AGN.Lib.Modal.getWrapper($element).modal("hide");
            } else {
                AGN.Lib.JsonMessages(resp.popups, true);
            }
        });
    });
    function prepareDisabledMailinglistsBeforeSaving($form) {
        $("input[name*='disabledMailinglistsIds']").remove();
        disabledCheckboxes("mailinglist").each(function() {
            $("<input>").attr({
                type: "hidden",
                name: "disabledMailinglistsIds",
                value: $(this).data("mailinglist")
            }).appendTo($form);
        });
    }
    function disabledCheckboxes(scope) {
        if (scope) {
            return $("input:checkbox:not(:checked)[data-enabling=" + scope + "]");
        } else {
            return $("input:checkbox:not(:checked)[data-enabling]");
        }
    }
});

AGN.Lib.Controller.new("ai-text-generation", function() {
    const Form = AGN.Lib.Form;
    const Select = AGN.Lib.Select;
    var $modal;
    var lastGeneratedText;
    this.addDomInitializer("ai-text-generation", function() {
        $modal = this.el.closest(".modal");
        initListeners();
        const languageSelect = Select.get($("#ai-language"));
        if (languageSelect.hasOption(window.adminLocale)) {
            languageSelect.selectValue(window.adminLocale);
        }
    });
    function initListeners() {
        $modal.on("modal:enlarged", function(e, $enlargedModal) {
            syncSettings($modal, $enlargedModal);
        });
        $modal.on("modal:enlarged:apply", function(e, $enlargedModal) {
            syncSettings($enlargedModal, $modal);
        });
        $modal.on("saveDynTag", function(e, currentDynTag) {
            const $aiTextGenerationBlock = $("#tab-content-ai-text-generation");
            if ($aiTextGenerationBlock.is(":visible")) {
                if (lastGeneratedText) {
                    const promise = AGN.Lib.Confirm.createFromTemplate({
                        dynTagName: currentDynTag.name
                    }, "mailing-ai-text-generation-apply-question");
                    promise.done(function() {
                        const event = $.Event("saveDynTagContent");
                        $modal.trigger(event, [ lastGeneratedText ]);
                        lastGeneratedText = null;
                    });
                } else {
                    $modal.modal("toggle");
                }
                e.preventDefault();
            }
        });
    }
    this.addAction({
        enterdown: "skip-form-submit"
    }, function() {
        this.event.preventDefault();
    });
    this.addAction({
        click: "generateText"
    }, function() {
        const form = Form.get(this.el);
        const $tile = this.el.closest(".tile");
        if (validateSettings(form, $tile)) {
            const settings = getSettingsFromUi($tile);
            $.post(AGN.url("/mailing/content/generateText.action"), settings).done(function(resp) {
                lastGeneratedText = resp.data;
                displayGeneratedText(resp.data, $tile);
            }).fail(function() {
                AGN.Lib.Messages(t("Error"), t("defaults.error"), "alert");
            });
        }
    });
    function validateSettings(form, $tile) {
        var isValid = true;
        var $numberOfWords = $tile.find("[id^='ai-numberOfWords']");
        var $contentDescription = $tile.find("[id^='ai-content-description']");
        const numberOfWordsErrors = AGN.Lib.Validator.get("number").errors($numberOfWords, {
            min: 1,
            required: true
        });
        if (numberOfWordsErrors.length > 0) {
            isValid = false;
            numberOfWordsErrors.forEach(function(error, index) {
                form.showFieldError($numberOfWords.attr("name"), error.msg);
            });
        } else {
            form.cleanFieldError($numberOfWords.attr("name"));
        }
        if (!$.trim($contentDescription.val())) {
            isValid = false;
            form.showFieldError($contentDescription.attr("name"), t("fields.required.errors.missing"));
        } else {
            form.cleanFieldError($contentDescription.attr("name"));
        }
        return isValid;
    }
    this.addAction({
        click: "assumeGeneratedText"
    }, function() {
        const $tile = this.el.closest(".tile");
        const tabId = $tile.data("tab-id");
        const text = $tile.find(".ai-generated-text").val();
        openEditorTab(tabId);
        setEditorContent(text, $tile, tabId);
    });
    function openEditorTab(tabId) {
        const $wysiwygTab = $('[data-toggle-tab*="wysiwyg' + tabId + '"]');
        if ($wysiwygTab.exists()) {
            $wysiwygTab.trigger("click");
            return;
        }
        const $htmlTab = $('[data-toggle-tab*="html' + tabId + '"]');
        if ($htmlTab.exists()) {
            $htmlTab.trigger("click");
        }
    }
    function setEditorContent(content, $tile, tabId) {
        const $textArea = $tile.parent().parent().find(".js-wysiwyg");
        if ($("#tab-content-wysiwyg").is(":visible") || $("[id^='tab-grid-wysiwyg" + tabId + "']").is(":visible")) {
            var editor = CKEDITOR.instances[$textArea.attr("id")];
            if (editor.status === "ready") {
                editor.setData(content);
            } else {
                editor.on("instanceReady", function(event) {
                    event.editor.setData(content);
                });
            }
        }
        if ($("#contentEditor").is(":visible") || $("[id^='tab-grid-html" + tabId + "']").is(":visible")) {
            ace.edit($textArea.attr("name") + "Editor").setValue(content);
        }
    }
    function syncSettings($srcModal, $destModal) {
        const settings = getSettingsFromUi($srcModal);
        displaySettings($destModal, settings);
        const generatedText = $srcModal.find(".ai-generated-text").val();
        if (generatedText) {
            displayGeneratedText(generatedText, $destModal);
        }
    }
    function getSettingsFromUi($scope) {
        return {
            language: $scope.find('[id^="ai-language"]').val(),
            numberOfWords: $scope.find('[id^="ai-numberOfWords"]').val(),
            tonality: $scope.find('[id^="ai-tonality"]').val(),
            contentDescription: $scope.find('[id^="ai-content-description"]').val()
        };
    }
    function displayGeneratedText(text, $scope) {
        $scope.find(".ai-generated-text").val(text);
        $scope.find("#ai-assume-generated-text").removeClass("hidden");
    }
    function displaySettings($modal, settings) {
        if (settings) {
            Select.get($modal.find("#ai-language")).selectValue(settings.language);
            $modal.find("#ai-numberOfWords").val(settings.numberOfWords);
            Select.get($modal.find("#ai-tonality")).selectValue(settings.tonality);
            $modal.find("#ai-content-description").val(settings.contentDescription);
        }
    }
});

AGN.Lib.Controller.new("allowed-profile-field-values", function() {
    var controller = this;
    this.addInitializer("allowed-values", function($scope) {
        if (!$scope) {
            $scope = $(document);
        }
        var $controller = $scope.find('[data-controller="allowed-profile-field-values"]');
        if ($controller.length == 0) {
            return;
        }
        controller.container = $controller.find("table .js-allowed-value").first().parent();
    });
    this.addAction({
        click: "addNewValue"
    }, function() {
        var $row = controller.getRow(this.el);
        var value = controller.getField($row).val();
        $row.remove();
        controller.appendRow(false, value);
        controller.appendRow(true);
    });
    this.addAction({
        click: "deleteValue"
    }, function() {
        controller.getRow(this.el).remove();
    });
    this.appendRow = function(isLastRow, value) {
        var $row = AGN.Lib.Template.dom("allowed-value-new-row", {
            isLastRow: isLastRow
        });
        if (value) {
            this.getField($row).val(value);
        }
        this.container.append($row);
    };
    this.getRow = function($e) {
        return $e.closest("tr.js-allowed-value");
    };
    this.getField = function($row) {
        return $row.find('input[name="allowedValues"]');
    };
});

AGN.Lib.Controller.new("auto-import-export", function() {
    var checkConnectionUrl;
    var isWorkflowDriven;
    this.addDomInitializer("auto-export", function() {
        checkConnectionUrl = this.config.urls.checkConnection;
        displayProperExportProfileBtn();
    });
    function displayProperExportProfileBtn() {
        const $editProfileBtn = $("#edit-profile-btn");
        const $addProfileBtn = $("#add-profile-btn");
        const selectedProfile = $("#export-profile").val();
        const profileSelected = parseInt(selectedProfile) > 0;
        $addProfileBtn.toggle(!profileSelected);
        $editProfileBtn.toggle(profileSelected).attr("href", AGN.url("/export/" + selectedProfile + "/view.action"));
    }
    this.addDomInitializer("auto-import", function() {
        checkConnectionUrl = this.config.urls.checkConnection;
        isWorkflowDriven = this.config.isWorkflowDriven;
        if (contentSourceTypeExists()) {
            selectContentSource(this.config.contentSourceIdentifier);
        }
    });
    function selectContentSource(identifier) {
        const contentSourceSelect = AGN.Lib.Select.get($("#contentSourceId"));
        if (contentSourceSelect.hasOption(identifier)) {
            contentSourceSelect.selectValue(identifier);
        }
    }
    this.addInitializer("optionsChangeable", function() {
        if ($("#recipient-autoimport-csvdescription").length) {
            $('[data-action="options-availability"][value="ReferenceTable"]').prop("disabled", false);
        }
    });
    this.addAction({
        click: "select-customer-fields"
    }, function() {
        AGN.Lib.Modal.createFromTemplate({}, "modal-select-customer-fields");
        $("#modalSelectedProfileFields").select2("val", $("#selectedProfileFields").val());
    });
    this.addAction({
        click: "save-selected-customer-fields"
    }, function() {
        $("#selectedProfileFields").select2("val", $("#modalSelectedProfileFields").val());
    });
    this.addAction({
        change: "select-export-profile"
    }, function() {
        displayProperExportProfileBtn();
    });
    this.addAction({
        click: "check-connection"
    }, function() {
        const form = AGN.Lib.Form.get(this.el);
        $.ajax(checkConnectionUrl, {
            type: "POST",
            dataType: "html",
            enctype: "multipart/form-data",
            processData: false,
            contentType: false,
            data: form.data()
        }).done(function(resp) {
            AGN.Lib.Page.render(resp);
        });
    });
    var profileMailinglists = {}, isAutoImportNew = false;
    this.addDomInitializer("import-profile-mailing-lists", function() {
        const profileConfig = this.config;
        isAutoImportNew = profileConfig.isAutoImportNew;
        profileMailinglists = profileConfig.profileMailinglists;
        const currentProfileId = $('[name="importProfileId"]').val();
        setMailinglists(currentProfileId, isAutoImportNew);
    });
    this.addAction({
        change: "change-import-profile"
    }, function() {
        const selectedProfile = AGN.Lib.Select.get($(this.el)).getSelectedValue();
        setMailinglists(selectedProfile, isAutoImportNew);
    });
    const setMailinglists = function(profileId, isNew) {
        if (isNew) {
            const mailingLists = profileMailinglists[profileId];
            $('input[type=checkbox][name^="mailinglists"]').prop("checked", false);
            _.each(mailingLists, function(id) {
                $('input[type=checkbox][name="mailinglists[' + id + ']"]').prop("checked", true);
            });
        }
    };
    const ScheduleTimeTable = AGN.Lib.ScheduleTimeTable, DayRow = AGN.Lib.ScheduleTimeTable.DayRow;
    function getScheduleTimeTable($el) {
        const $controller = $el.closest("[data-controller]");
        return $controller.data("_schedule_table");
    }
    function setScheduleTimeTable($el, scheduleTable) {
        const $controller = $el.closest("[data-controller]");
        $controller.data("_schedule_table", scheduleTable);
    }
    this.addDomInitializer("auto-import-export-scheduler", function() {
        const $el = $(this.el);
        const config = this.config;
        const data = config.intervalAsJson || [];
        const $scheduleTimeContainer = $("#tile-importexport-schedule-time");
        const scheduleTable = new ScheduleTimeTable($scheduleTimeContainer);
        setScheduleTimeTable($el, scheduleTable);
        var period = [];
        if (!_.isEmpty(data)) {
            period = JSON.parse(data).map(function(object) {
                return DayRow.deserialize(object);
            });
        }
        period.forEach(function(day) {
            scheduleTable.addRow(day);
        });
        if (period.length === 0) {
            scheduleTable.addEmptyDayRow();
        }
        const form = AGN.Lib.Form.get($el);
        form.initFields();
        if (!form.editable) {
            $scheduleTimeContainer.find(":input, button").prop("disabled", true);
            $scheduleTimeContainer.find("a").attr("disabled", "disabled");
        }
    });
    this.addAction({
        click: "add-day"
    }, function() {
        getScheduleTimeTable($(this.el)).addEmptyDayRow();
    });
    this.addAction({
        click: "remove-day"
    }, function() {
        const $el = $(this.el);
        getScheduleTimeTable($el).deleteRow(DayRow.get($(this.el)));
    });
    this.addAction({
        click: "add-schedule"
    }, function() {
        DayRow.get($(this.el)).addSchedule();
    });
    this.addAction({
        click: "remove-schedule"
    }, function() {
        DayRow.get($(this.el)).removeSchedule($(this.el));
    });
    this.addAction({
        click: "time-checkbox-toggle"
    }, function() {
        const $toggle = $(this.el);
        const row = DayRow.get($toggle);
        row.timeCheckboxToggle($toggle);
    });
    this.addAction({
        click: "hour-checkbox-toggle"
    }, function() {
        const $toggle = $(this.el);
        const row = DayRow.get($toggle);
        row.hourCheckboxToggle($toggle);
    });
    this.addAction({
        change: "validate-changes"
    }, function() {
        const $el = $(this.el);
        const row = DayRow.get($el);
        validateRow(row);
    });
    function validateRow(row) {
        if (row.isValidTimeIntervals()) {
            row.hideTimeScheduleErrors();
            return true;
        } else {
            row.showTimeScheduleErrors(t("error.delay.60"));
            return false;
        }
    }
    this.addAction({
        submission: "save-scheduler-data"
    }, function() {
        const $el = $(this.el);
        const scheduleTable = getScheduleTimeTable($el);
        const valid = scheduleTable.getAllDayRows().every(function(row) {
            return validateRow(row);
        });
        if (valid) {
            const form = AGN.Lib.Form.get($(this.el));
            form.setValueOnce("intervalAsJson", scheduleTable.getSubmissionJson("day"));
            form.submit();
        }
    });
    this.addAction({
        click: "save-auto-import"
    }, function() {
        const $form = $("#recipient-autoimport-form");
        const scheduleTable = getScheduleTimeTable($form);
        const valid = scheduleTable.getAllDayRows().every(function(row) {
            return validateRow(row);
        });
        if (valid) {
            const form = AGN.Lib.Form.get($form);
            const intervalJson = scheduleTable.getSubmissionJson("day");
            var contentSourceDataParts = getContentSourceDataParts();
            if (isWorkflowDriven) {
                form.setValue("intervalAsJson", intervalJson);
                if (contentSourceDataParts.length) {
                    form.setValue("contentSourceID", contentSourceDataParts[0]);
                    form.setValue("contentSourceType", contentSourceDataParts[1]);
                }
            } else {
                form.setValueOnce("intervalAsJson", intervalJson);
                if (contentSourceDataParts.length) {
                    form.setValueOnce("contentSourceID", contentSourceDataParts[0]);
                    form.setValueOnce("contentSourceType", contentSourceDataParts[1]);
                }
            }
            form.submit();
        }
    });
    function getContentSourceDataParts() {
        if (contentSourceTypeExists()) {
            return $("#contentSourceId").val().split("/");
        }
        return [];
    }
    function contentSourceTypeExists() {
        const $contentSourceId = $("#contentSourceId");
        return $contentSourceId.exists();
    }
    function getExportTypeHandler($el) {
        const $controller = $el.closest("[data-controller]");
        return $controller.data("_export_type_handler");
    }
    function setExportTypeHandler($el, handler) {
        const $controller = $el.closest("[data-controller]");
        $controller.data("_export_type_handler", handler);
    }
    this.addDomInitializer("mailing-options-attribute-resolver", function() {
        const $el = $(this.el);
        setExportTypeHandler($el, new ExportTypeHandler($el, this.config));
    });
    function ExportTypeHandler($element, options) {
        if (!$element.exists()) {
            console.error("ExportTypeHandler could not instantiate, element is not defined");
            return false;
        }
        this.$element = $element;
        this.exportType = options.exportType || "";
        this.mailingType = options.mailingType || -1;
        const $oneTimeCheckbox = $('input[name="' + options.oneTimeOption + '"]');
        this.$oneTimeCheckbox = $oneTimeCheckbox;
        this.initialOneTimeValues = {
            checked: $oneTimeCheckbox.is(":checked"),
            disabled: $oneTimeCheckbox.is(":disabled")
        };
        this.toggleOneTimeCheckbox();
    }
    ExportTypeHandler.prototype.isAfterMailingDeliveryType = function() {
        return this.exportType == "Mailing" && this.mailingType == 0;
    };
    ExportTypeHandler.prototype.resolve = function(exportType, mailingType) {
        this.exportType = exportType || "";
        this.mailingType = mailingType || -1;
        this.toggleOneTimeCheckbox();
    };
    ExportTypeHandler.prototype.toggleOneTimeCheckbox = function() {
        const isAfterMailingDeliveryType = this.isAfterMailingDeliveryType();
        const checked = this.initialOneTimeValues.checked;
        const disabled = this.initialOneTimeValues.disabled;
        this.$oneTimeCheckbox.prop("checked", isAfterMailingDeliveryType || checked);
        this.$oneTimeCheckbox.prop("disabled", isAfterMailingDeliveryType || disabled);
    };
    this.addAction({
        change: "change-mailing-type"
    }, function() {
        const $el = $(this.el);
        const mailingType = AGN.Lib.Select.get($el).getSelectedValue();
        var exportType;
        if ($("#exportType").is("select")) {
            exportType = AGN.Lib.Select.get($("#exportType select")).getSelectedValue();
        } else {
            exportType = $("#exportType [type=radio]:checked").val();
        }
        getExportTypeHandler($el).resolve(exportType, mailingType);
    });
    this.addAction({
        change: "export-type-resolver"
    }, function() {
        const $el = $(this.el);
        var exportType;
        if ($("#exportType").is("select")) {
            exportType = AGN.Lib.Select.get($("#exportType select")).getSelectedValue();
        } else {
            exportType = $el.find("[type=radio]:checked").val();
        }
        const mailingType = AGN.Lib.Select.get($("#exportMailing select")).getSelectedValue();
        getExportTypeHandler($el).resolve(exportType, mailingType);
    });
});

AGN.Lib.Controller.new("available-building-blocks", function() {
    var changedBlockStatuses;
    var blockStatuses;
    var pageForm;
    function init() {
        changedBlockStatuses = {};
        blockStatuses = {};
    }
    this.addDomInitializer("available-building-blocks", function() {
        init();
        var element = this.el;
        pageForm = AGN.Lib.Form.get(element);
        if (this.config.changedBlockStatus) {
            changedBlockStatuses = JSON.parse(this.config.changedBlockStatus);
        }
    });
    this.addDomInitializer("available-building-blocks-table", function() {
        var containerList = this.config.divContainerList;
        _.each(containerList, function(block) {
            var id = block.id;
            var status = block.active;
            if (id in blockStatuses) {
                if (id in changedBlockStatuses) {
                    $("input:checkbox[data-block-id=" + id + "]").prop("checked", !!changedBlockStatuses[id]);
                }
            } else {
                blockStatuses[id] = status;
            }
        });
        updateTableControls();
    });
    this.addAction({
        click: "update-changed-data"
    }, function() {
        var element = this.el;
        updateTableControls();
        updateFormData();
        pageForm.setActionOnce(element.data("form-url"));
        pageForm.setResourceSelectorOnce(element.data("form-resource"));
        pageForm.submit();
    });
    this.addAction({
        change: "change-activation"
    }, function() {
        var checkbox = this.el;
        var divContainerId = checkbox.data("block-id");
        var checked = checkbox.is(":checked");
        if (checked == blockStatuses[divContainerId]) {
            if (divContainerId in changedBlockStatuses) {
                delete changedBlockStatuses[divContainerId];
            }
        } else {
            changedBlockStatuses[divContainerId] = checked;
        }
    });
    this.addAction({
        change: "activate-all"
    }, function() {
        var activeAll = this.el;
        var $checkboxes = $("input:checkbox[data-block-id]");
        $checkboxes.prop("checked", activeAll.is(":checked"));
        $checkboxes.change();
    });
    function updateTableControls() {
        var controls = $(pageForm.form).find(".table-controls .well");
        controls.first().html(controls.last().html());
    }
    this.updateTableControls = updateTableControls;
    function updateFormData() {
        if (!!pageForm) {
            pageForm.setValue("changedBlockStatusJson", JSON.stringify(changedBlockStatuses, function(key, value) {
                if (value != null) {
                    return value;
                }
            }));
        }
    }
    this.updateFormData = updateFormData;
});

AGN.Lib.Controller.new("birt-reports", function() {
    var config = {}, reportType = 0, ARCHIVE_LIST = [], MAILINGLIST_LIST = [], TARGETS_LIST = [], AFTER_MAILING_TYPE_ID, MAILING_ID, $form;
    this.addDomInitializer("birt-reports", function() {
        config = this.config;
        MAILING_ID = config.constant.MAILING_ID;
        AFTER_MAILING_TYPE_ID = config.constant.AFTER_MAILING_TYPE_ID;
        ARCHIVE_LIST = config.filtered.FILTER_ARCHIVE;
        MAILINGLIST_LIST = config.filtered.FILTER_MAILINGLIST;
        TARGETS_LIST = config.filtered.FILTER_TARGET;
        reportType = config.reportType;
        $form = this.el;
    });
    function disableTabs() {
        _.each($(config.reportSettingsId).find("[data-toggle-tab]"), function(tab) {
            var $tab = $(tab);
            var tabId = $tab.data("toggle-tab");
            if (tabId.endsWith(MAILING_ID)) {
                $tab.trigger("click");
                return;
            }
            $tab.parent("li").addClass("disabled");
            AGN.Lib.Tab.hide($(tabId));
        });
    }
    function enableTabs() {
        _.each($(config.reportSettingsId).find("[data-toggle-tab]"), function(tab) {
            $(tab).parent("li").removeClass("disabled");
        });
    }
    AGN.Lib.Action.new({
        change: "input[type=radio][name=type]"
    }, function() {
        var actualReportType = $(this.el).val();
        var isAfterMailingType = actualReportType == AFTER_MAILING_TYPE_ID;
        if (isAfterMailingType) {
            disableTabs();
        } else if (reportType == AFTER_MAILING_TYPE_ID) {
            enableTabs();
        }
        reportType = actualReportType;
        return false;
    });
    this.addDomInitializer("report-settings", function() {
        var el = this.el;
        var config = this.config;
        new ReportSettings(el, config);
    });
    var ReportSettings = function(container, config) {
        var self = this;
        this.container = container;
        this.config = config;
        this.settingsType = config.settingsType;
        this.select = AGN.Lib.Select.get(container.find(config.selectors.filterBlockId));
        this.mailingSelect = AGN.Lib.Select.get(container.find(config.selectors.normalMailing));
        self.init(config);
        container.find(config.selectors.mailingType).on("change", function(event) {
            self.handleMailingTypeChanges($(event.target));
        });
        container.find(config.selectors.mailingFilter).on("change", function(event) {
            self.handleMailingFilterChanges($(event.target));
        });
        container.find(config.selectors.filterBlockId).on("change", function(event) {
            self.handleMailingFilterValueChanges($(event.target));
        });
    };
    ReportSettings.prototype.init = function(config) {
        var mailingType = config.data.mailingType;
        var mailingFilter = config.data.mailingFilter;
        var predefineMailing = config.data.predefineMailing;
        var selectedMailings = config.data.selectedMailings;
        const jqXHR = this.updateAllComparisonDependentFields(mailingType, mailingFilter, predefineMailing, selectedMailings);
        jqXHR.done(function() {
            $form.dirty("setAsClean");
        });
    };
    ReportSettings.prototype.handleMailingTypeChanges = function(el) {
        var report = this;
        var mailingFilter = report.getMailingFilter();
        var mailingFilterValue = report.getMailingFilterValue();
        report.updateNormalMailingField(el.val(), mailingFilter, mailingFilterValue);
    };
    ReportSettings.prototype.handleMailingFilterChanges = function(el) {
        var report = this;
        var mailingType = report.getMailingType();
        report.updateAllComparisonDependentFields(mailingType, el.val());
    };
    ReportSettings.prototype.handleMailingFilterValueChanges = function(el) {
        var report = this;
        var mailingFilter = report.getMailingFilter();
        var mailingType = report.getMailingType();
        report.updateNormalMailingField(mailingType, mailingFilter, el.val());
    };
    ReportSettings.prototype.updateAllComparisonDependentFields = function(mailingType, mailingFilter, predefinedMailing, selectedMailings) {
        var self = this;
        self.select.resetOptions();
        if (mailingFilter > 0) {
            var data = [];
            if (mailingFilter == 1) {
                data = ARCHIVE_LIST;
            } else if (mailingFilter == 2) {
                data = MAILINGLIST_LIST;
            } else if (mailingFilter == 4) {
                data = TARGETS_LIST;
            }
            _.each(data, function(item) {
                self.select.addFormattedOption('<option value="' + item.id + '">' + item.shortname + "</option>");
            });
            self.select.selectValueOrSelectFirst(predefinedMailing);
            predefinedMailing = self.select.getSelectedValue();
        }
        return self.updateNormalMailingField(mailingType, mailingFilter, predefinedMailing, selectedMailings);
    };
    ReportSettings.prototype.updateNormalMailingField = function(mailingType, mailingFilter, predefinedMailing, selectedMailings) {
        const deferred = $.Deferred();
        var self = this;
        self.mailingSelect.resetOptions();
        if (self.settingsType == config.constant.COMPARISON_SETTINGS && mailingType == 2 || self.settingsType == config.constant.MAILING_SETTINGS && mailingType == 3) {
            $.ajax({
                type: "GET",
                url: config.urls.FILTERED_MAILING_URL,
                data: {
                    type: mailingFilter,
                    value: predefinedMailing ? predefinedMailing : 0,
                    mailingType: config.constant.NORMAL_MAILING_TYPE
                }
            }).done(function(data) {
                _.each(data, function(item) {
                    self.mailingSelect.addFormattedOption('<option value="' + item.id + '">' + item.shortname + "</option>");
                });
                self.mailingSelect.selectValue(selectedMailings ? selectedMailings : "");
                deferred.resolve();
            });
        }
        return deferred.promise();
    };
    ReportSettings.prototype.getMailingFilter = function() {
        var filter = this.container.find(this.config.selectors.mailingFilter);
        return parseInt(filter.val()) | 0;
    };
    ReportSettings.prototype.getMailingFilterValue = function() {
        var filterValue = this.select.getSelectedValue();
        return parseInt(filterValue) | 0;
    };
    ReportSettings.prototype.getMailingType = function() {
        var mailingType = this.container.find(this.config.selectors.mailingType + ":checked");
        return parseInt(mailingType.val()) | 0;
    };
    this.addAction({
        click: "confirm-deactivate-deliveries"
    }, function() {
        AGN.Lib.Confirm.createFromTemplate({
            action: AGN.url("/statistics/report/" + config.reportId + "/deactivateAllDeliveries.action"),
            method: "POST",
            title: t("birtreport.deactivateAll"),
            content: t("birtreport.deactivateAllQuestion")
        }, "modal-yes-no-cancel").done(function(resp) {
            AGN.Lib.Form.get($("#birtreportForm")).updateHtml(resp);
        });
    });
});

AGN.Lib.Controller.new("blacklist-list", function() {
    var $blacklistSaveElement;
    this.addDomInitializer("blacklist-list-init", function() {
        $blacklistSaveElement = this.el;
    });
    this.addAction({
        click: "saveBlacklist"
    }, function() {
        var $element = this.el;
        var form = AGN.Lib.Form.get($element);
        var saveActionUrl = $element.data("url");
        $.ajax(saveActionUrl, {
            type: "POST",
            data: {
                email: $blacklistSaveElement.find("#new-entry-email").val(),
                reason: $blacklistSaveElement.find("#new-entry-reason").val()
            },
            success: function(resp) {
                if (resp.success === true) {
                    form.submit().done(function() {
                        AGN.Lib.JsonMessages(resp.popups, true);
                    });
                } else if (resp.popups) {
                    AGN.Lib.JsonMessages(resp.popups, true);
                } else {
                    AGN.Lib.RenderMessages($(resp));
                }
            }
        });
    });
});

AGN.Lib.Controller.new("edit-modal-blacklist-list", function() {
    this.addAction({
        click: "saveChanges"
    }, function() {
        var $element = this.el;
        var updateForm = AGN.Lib.Form.get($element);
        updateForm.submit().done(function(resp) {
            if (resp.success === true) {
                AGN.Lib.Form.get($("#blacklistListView")).submit().done(function() {
                    AGN.Lib.JsonMessages(resp.popups, true);
                });
                AGN.Lib.Modal.getWrapper($element).modal("hide");
            } else if (resp.popups) {
                AGN.Lib.JsonMessages(resp.popups, true);
            } else {
                AGN.Lib.RenderMessages($(resp));
            }
        });
    });
});

AGN.Lib.Controller.new("email-list-controller", function() {
    var targetFieldName = "";
    var separator = " ";
    var emailsListManager;
    var dataList = function() {
        var result = [ "" ];
        var stringValue = $('input[name="' + targetFieldName + '"]').val();
        if (stringValue) {
            result = stringValue.split(separator);
        }
        return result;
    };
    var saveDataToField = function() {
        var jsonData = emailsListManager.getJsonData();
        $('input[name="' + targetFieldName + '"]').val(jsonData.join(separator));
    };
    this.addDomInitializer("email-list-initializer", function() {
        var scope = $(this.el);
        targetFieldName = scope.data("target-field") || "";
        separator = scope.data("data-emails-separator") || separator;
        emailsListManager = AGN.Lib.EmailsListManager.initialize(scope, dataList());
    });
    this.addAction({
        click: "delete-email"
    }, function() {
        emailsListManager.deleteRow($(this.el));
        saveDataToField();
    });
    this.addAction({
        click: "create-email"
    }, function() {
        emailsListManager.createRowAfter($(this.el));
        saveDataToField();
    });
    this.addAction({
        change: "change-trigger"
    }, function() {
        saveDataToField();
    });
});

AGN.Lib.Controller.new("company-view", function() {
    this.addAction({
        click: "create-postal-field"
    }, function() {
        const url = this.el.attr("href");
        const form = AGN.Lib.Form.get(this.el);
        form.jqxhr().done(function(resp) {
            AGN.Lib.Page.reload(url);
        });
    });
});

AGN.Lib.Controller.new("content-source-view", function() {
    var Select = AGN.Lib.Select;
    var Template = AGN.Lib.Template;
    var form;
    var $urlsContainer;
    var urlResources = [];
    var linkForSettings;
    var htmlSourcesAllowed;
    var availableMailings = [];
    var resourceType;
    function UrlResource(index, address) {
        this.address = address;
        this.contentBlockName = "";
        this.targetGroup = 0;
        this.index = index;
    }
    UrlResource.create = function(index, address) {
        return new UrlResource(index, address);
    };
    this.addDomInitializer("content-source-view", function() {
        $urlsContainer = $("#urlsContainer");
        form = AGN.Lib.Form.get($("#content-source-form"));
        resourceType = $("#resource-type").val();
        urlResources = [];
        updateUiBasedOnType();
        if (this.config.urlResources) {
            showExistingUrlResources(this.config.urlResources);
        }
        linkForSettings = this.config.urls.linkForSettings;
        htmlSourcesAllowed = this.config.htmlSourcesAllowed;
    });
    function updateUiBasedOnType() {
        var $container = $("#dynamic-container");
        $urlsContainer.empty();
        $container.empty();
        if (resourceType === "HTML" && htmlSourcesAllowed) {
            var $addBtn = $(Template.text("add-url-btn", {}));
            $container.append($addBtn);
        } else if (resourceType === "XML") {
            var $xmlUrlInput = $(Template.text("xml-source-url"));
            $container.append($xmlUrlInput);
        }
    }
    this.addAction({
        change: "change-resource-type"
    }, function() {
        resourceType = this.el.val();
        updateUiBasedOnType();
        urlResources = [];
    });
    function showExistingUrlResources(urlResources) {
        if (resourceType === "XML") {
            if (urlResources.length > 0) {
                $("#xml-url-address").val(urlResources[0].url);
            }
        } else if (resourceType === "HTML") {
            _.each(urlResources, function(inputUrlResource) {
                var urlResource = pushNewUrlResource(inputUrlResource);
                var $newDataBlock = $(Template.text("html-source-url", {
                    index: urlResource.index,
                    address: urlResource.address
                }));
                var $configureBtn = $newDataBlock.find("button[data-action='configure-url']");
                var $addressInput = $newDataBlock.find("input[data-source-url]");
                showInfoLabel($newDataBlock, ".content-block-info", inputUrlResource.contentBlockName, ".content-name-value", inputUrlResource.contentBlockName);
                showInfoLabel($newDataBlock, ".target-group-info", inputUrlResource.targetGroupName, ".target-group-value", inputUrlResource.targetGroupName);
                $urlsContainer.append($newDataBlock);
                addAddressInputListener($addressInput, $configureBtn);
            });
        }
    }
    function pushNewUrlResource(inputUrlResource) {
        var urlResource = UrlResource.create(urlResources.length);
        urlResource.address = inputUrlResource.url;
        urlResource.contentBlockName = inputUrlResource.contentBlockName;
        urlResource.targetGroup = inputUrlResource.targetGroup;
        urlResources.push(urlResource);
        return urlResource;
    }
    this.addDomInitializer("content-sources-mailings", function() {
        availableMailings = this.config;
        var $mailingSelect = $("#mailing-name");
        fillMailingSelect($mailingSelect);
        addChangeHandlerOnMailingSelect($mailingSelect);
    });
    function fillMailingSelect($mailingSelect) {
        availableMailings.forEach(function(mailing) {
            var $option = $("<option>", {
                value: mailing.name,
                text: mailing.name
            });
            $mailingSelect.append($option);
        });
    }
    function addChangeHandlerOnMailingSelect($mailingSelect) {
        var $contentBlockSelect = $("#content-block-name");
        $mailingSelect.on("change", function() {
            $contentBlockSelect.empty();
            fillBlockSelect($(this).val(), $contentBlockSelect);
            Select.get($contentBlockSelect).selectFirstValue();
        });
    }
    function fillBlockSelect(selectedMailingName, $contentBlockSelect) {
        var foundMailing = availableMailings.find(function(mailing) {
            return mailing.name === selectedMailingName;
        });
        foundMailing.blocks.forEach(function(contentBlock) {
            var $option = $("<option>", {
                value: contentBlock,
                text: contentBlock
            });
            $contentBlockSelect.append($option);
        });
    }
    this.addAction({
        click: "add-url-resource"
    }, function() {
        var index = urlResources.length;
        var $newUrlBlock = $(Template.text("html-source-url", {
            index: index,
            address: ""
        }));
        var $configureBtn = $newUrlBlock.find("button[data-action='configure-url']");
        var $addressInput = $newUrlBlock.find("input[data-source-url]");
        $urlsContainer.append($newUrlBlock);
        $configureBtn.hide();
        addAddressInputListener($addressInput, $configureBtn);
        urlResources.push(UrlResource.create(index));
    });
    function addAddressInputListener($addressInput, $configureBtn) {
        if ($addressInput && $configureBtn) {
            $addressInput.on("change keyup paste", function() {
                if ($(this).val()) {
                    $configureBtn.show();
                } else {
                    $configureBtn.hide();
                }
            });
        }
    }
    this.addAction({
        click: "configure-url"
    }, function() {
        var $formGroup = this.el.closest(".form-group");
        var $urlInput = $formGroup.find(".form-control");
        var inputIndex = $formGroup.data("url-index");
        var params = {
            url: $urlInput.val(),
            index: inputIndex
        };
        var foundUrlResource = urlResources.find(function(sourceUrl) {
            return sourceUrl.index === inputIndex;
        });
        loadConfigurationModal(params, foundUrlResource);
    });
    this.addAction({
        click: "remove-url"
    }, function() {
        var $formGroup = this.el.closest(".form-group");
        var foundIndex = $formGroup.data("url-index");
        $formGroup.remove();
        urlResources = urlResources.filter(function(urlResource) {
            return urlResource.index !== foundIndex;
        });
    });
    function loadConfigurationModal(params, urlResource) {
        var jqxhr = $.get(linkForSettings);
        jqxhr.done(function(resp) {
            var modalHtml = _.template(resp)(params);
            form.updateHtml(modalHtml);
            initModalSettings(urlResource);
            initModalSaveHandler();
        });
    }
    function initModalSettings(urlResource) {
        var $configurationModal = $('div[data-modal-index="' + urlResource.index + '"]');
        if (urlResource.contentBlockName) {
            var $blockNameSelect = $configurationModal.find("#content-block-name");
            var $firstOption = $blockNameSelect.find("option:first-child");
            $firstOption.val(urlResource.contentBlockName);
            $firstOption.text(urlResource.contentBlockName);
            $blockNameSelect.change();
        }
        if (urlResource.targetGroup > 0) {
            var $targetGroupSelect = $configurationModal.find("#target-group-select");
            $targetGroupSelect.find("option[value=" + urlResource.targetGroup + "]").attr("selected", "selected");
            $targetGroupSelect.change();
        }
    }
    function initModalSaveHandler() {
        $("[data-confirm-positive]").on("click", function() {
            var $modal = $(this).closest(".modal");
            var modalIndex = $modal.data("modal-index");
            var configurableUrlResource = urlResources.find(function(urlResource) {
                return urlResource.index === modalIndex;
            });
            var $targetGroupSelect = $modal.find("#target-group-select");
            configurableUrlResource.targetGroup = $targetGroupSelect.val();
            configurableUrlResource.contentBlockName = $modal.find("#content-block-name").val();
            showUrlConfiguredData(configurableUrlResource, $targetGroupSelect);
            form.handleErrors();
        });
    }
    function showUrlConfiguredData(urlResource, $targetGroupSelect) {
        var $groupContainer = $("div[data-url-index='" + urlResource.index + "']");
        var targetGroupText = $targetGroupSelect.find("option:selected").text();
        showInfoLabel($groupContainer, ".content-block-info", urlResource.contentBlockName, ".content-name-value", urlResource.contentBlockName);
        showInfoLabel($groupContainer, ".target-group-info", urlResource.targetGroup, ".target-group-value", targetGroupText);
    }
    function showInfoLabel($parent, containerSelector, canShow, valueSelector, value) {
        var $container = $parent.find(containerSelector);
        if (canShow) {
            $container.find(valueSelector).text(value);
            $container.show();
        } else {
            $container.hide();
        }
    }
    this.addAction({
        submission: "content-source-save"
    }, function() {
        form.initFields();
        prepareDataForSave();
        if (form.valid()) {
            _.each(urlResources, function(urlResource, index) {
                var targetGroupValue = urlResource.targetGroup ? urlResource.targetGroup : 0;
                form.setValue("urls[" + index + "].url", urlResource.address);
                form.setValue("urls[" + index + "].contentBlockName", urlResource.contentBlockName);
                form.setValue("urls[" + index + "].targetGroup", targetGroupValue);
            });
        }
        form.submit();
    });
    function prepareDataForSave() {
        if (resourceType === "XML") {
            var xmlUrlResource = UrlResource.create(0, $("#xml-url-address").val());
            urlResources = [];
            urlResources.push(xmlUrlResource);
        } else if (resourceType === "HTML") {
            fillResourcesAddresses();
        }
    }
    function fillResourcesAddresses() {
        _.each($urlsContainer.find("[data-source-url]"), function(addressInput) {
            var $addressInput = $(addressInput);
            var urlIndex = $addressInput.closest(".form-group").data("url-index");
            var foundSourceUrl = urlResources.find(function(sourceUrl) {
                return sourceUrl.index === urlIndex;
            });
            foundSourceUrl.address = $addressInput.val();
        });
    }
    AGN.Lib.Validator.new("mailing-content-block", {
        valid: function($e, options) {
            return !this.errors($e, options).length;
        },
        errors: function($e, options) {
            var errors = [];
            var index = $e.closest(".form-group").data("url-index");
            var foundUrlResource = urlResources.find(function(sourceUrl) {
                return sourceUrl.index === index;
            });
            if (!foundUrlResource.contentBlockName) {
                errors.push({
                    field: $e,
                    msg: t("contentSource.error.block_not_set")
                });
            }
            return errors;
        }
    });
});

AGN.Lib.Controller.new("custom-thumbnail-view", function() {
    this.addAction({
        change: "use-custom-thumbnail"
    }, function() {
        var $file = $("#customThumbnailFile");
        $file.prop("name", this.el.is(":checked") ? "customThumbnailFile" : "");
    });
    this.addAction({
        change: "custom-thumbnail-image"
    }, function() {
        var $file = this.el;
        var files = $file.prop("files");
        if (files && files.length) {
            var file = files[0];
            if (file.type == "image" || file.type.match("image/.*")) {
                var reader = new FileReader();
                reader.onload = function(e) {
                    showCustomThumbnailPreview($file, file.name, e.target.result);
                };
                reader.readAsDataURL(file);
            } else {
                AGN.Lib.Helpers.clearFormField($file);
                showCustomThumbnailPreview($file, "", "");
            }
        } else {
            showCustomThumbnailPreview($file, "", "");
        }
    });
    function showCustomThumbnailPreview($file, name, content) {
        var targets;
        targets = $file.data("preview-name");
        if (targets) {
            $(targets).text(name);
        }
        targets = $file.data("preview-image");
        if (targets) {
            if (content) {
                $(targets).prop("src", content);
            } else {
                $(targets).each(function() {
                    var $target = $(this);
                    $target.prop("src", $target.data("no-preview-src") || "");
                });
            }
        }
    }
});

AGN.Lib.Controller.new("device-statistic", function() {
    var HTML_URL_PREFIX, htmlBlockSelector, exportBlockSelector, typeFieldName;
    this.addDomInitializer("device-statistic-initializer", function() {
        var config = this.config;
        var active = config.activeStatisticId;
        HTML_URL_PREFIX = config.HTML_URL;
        htmlBlockSelector = config.htmlBlockSelector;
        exportBlockSelector = config.exportBlockSelector;
        typeFieldName = config.typeFieldName;
        _.each($('[data-action="switch-device-tab"]'), function(el) {
            if ($(el).data("type") === active) {
                $(el).trigger("click");
            }
        });
    });
    this.addAction({
        click: "switch-device-tab"
    }, function() {
        var type = $(this.el).data("type");
        $(htmlBlockSelector).find("iframe").attr("src", getHtmlLink(type));
        $(exportBlockSelector).html(getExportLink(type));
        $('[name="' + typeFieldName + '"]').val(type);
    });
    function getExportLink(type) {
        return AGN.Lib.Template.text("statistic-csv-view", {
            type: type
        });
    }
    function getHtmlLink(type) {
        return HTML_URL_PREFIX.replace("{stat-type}", type);
    }
});

AGN.Lib.Controller.new("emc-template-preview-controller", function() {
    this.addDomInitializer("emc-template-preview-initializer", function() {
        if ($('[name="view-state"]').length) {
            modifyPreviewHeaderForBlockView();
        }
    });
    function modifyPreviewHeaderForBlockView() {
        $("#preview").find(".tile-header").removeAttr("data-sizing");
        $("#content_wrapper").removeAttr("data-sizing");
        $("#previewTabsMenu").replaceWith('<h2 class="headline">' + t("defaults.previewMode") + "</h2>");
    }
});

AGN.Lib.Controller.new("emm-activeness", function() {
    function include(states, id, value) {
        states[id] = value;
        updateSaveButtonState(states);
    }
    function exclude(states, id) {
        delete states[id];
        updateSaveButtonState(states);
    }
    function excludeAll(states) {
        for (var id in states) {
            delete states[id];
        }
        updateSaveButtonState(states);
    }
    function updateSaveButtonState(states) {
        var $saveButton = $('[data-action="save"]');
        var count = 0;
        for (var id in states) {
            if (states.hasOwnProperty(id)) {
                count++;
                break;
            }
        }
        if (count > 0) {
            $saveButton.removeClass("disabled");
        } else {
            $saveButton.addClass("disabled");
        }
    }
    this.addAction({
        click: "save"
    }, function() {
        var $element = $(this.el);
        var $form = AGN.Lib.Form.get($element);
        var $controller = $element.closest("[data-controller]");
        var states = $controller.data("_states") || {};
        if ($form && $form.form) {
            for (var id in states) {
                if (states.hasOwnProperty(id)) {
                    $form.setValueOnce("activeness[" + id + "]", states[id]);
                }
            }
            $form.submit();
        } else {
            var table = AGN.Lib.Table.get($element);
            if (table) {
                var rowsData = [];
                $.ajax($element.data("form-url"), {
                    method: "POST",
                    traditional: false,
                    data: {
                        activeness: states
                    }
                }).done(function(resp) {
                    if (resp && resp.success === true) {
                        rowsData = saveStates(table, states);
                    } else {
                        rowsData = resetStates(table, states);
                    }
                    AGN.Lib.JsonMessages(resp.popups);
                }).fail(function() {
                    rowsData = resetStates(table, states);
                    AGN.Lib.Messages(t("Error"), t("defaults.error"), "alert");
                }).always(function() {
                    table.api.updateRowData({
                        update: rowsData
                    });
                    excludeAll(states);
                });
            }
        }
    });
    function saveStates(table, states) {
        applyStates(table, states, false);
    }
    function resetStates(table, states) {
        applyStates(table, states, true);
    }
    function applyStates(table, states, invert) {
        var rows = [];
        table.api.forEachNodeAfterFilterAndSort(function(rowNode, index) {
            var id = rowNode.data.id;
            if (states.hasOwnProperty(id)) {
                var state = invert ? !states[id] : states[id];
                rowNode.data.activeStatus = state ? "ACTIVE" : "INACTIVE";
                rows.push(rowNode.data);
            }
        });
        return rows;
    }
    this.addAction({
        change: "toggle-active"
    }, function() {
        var $element = $(this.el);
        var $controller = $element.closest("[data-controller]");
        var states = $controller.data("_states") || {};
        var itemId = $element.data("item-id");
        var state = $element.is(":checked");
        if (state == $element.data("initial-state")) {
            exclude(states, itemId);
        } else {
            include(states, itemId, state);
        }
        $controller.data("_states", states);
    });
});

AGN.Lib.Controller.new("enlarged-content-editor-controller", function() {
    var Modal = AGN.Lib.Modal;
    var Confirm = AGN.Lib.Confirm;
    var content;
    this.addDomInitializer("enlarged-content-editor-initializer", function($modal) {
        var config = Modal.get($modal);
        content = config.content;
        synchronizeEditorTab(config.editorType);
        displayCharCounter();
    });
    function displayCharCounter() {
        if (getActiveEditor() === "html") {
            showCharCounter();
        } else {
            hideCharCounter();
        }
    }
    this.addAction({
        click: "updateContent"
    }, function() {
        var $button = $(this.el);
        var deferred = Confirm.get($button);
        deferred.positive(updateContentCallback());
        $("#enlarged_content_modal").modal("toggle");
    });
    var updateContentCallback = function() {
        return {
            content: getContent(),
            editorType: getActiveEditor()
        };
    };
    var getContent = function() {
        var $wysiwygEditorBlock = $("#tab-enlargedContent-wysiwyg");
        var $htmlEditorBlock = $("#enlargedContentEditor");
        if ($wysiwygEditorBlock.is(":visible")) {
            var wysiwygEditor = CKEDITOR.instances["enlargedContent"];
            return wysiwygEditor.getData();
        }
        if ($htmlEditorBlock.is(":visible")) {
            var htmlEditor = ace.edit("enlargedContentEditor");
            return htmlEditor.getValue();
        }
    };
    var getActiveEditor = function() {
        var $wysiwygEditorBlock = $("#tab-enlargedContent-wysiwyg");
        if ($wysiwygEditorBlock.is(":visible")) {
            return "wysiwyg";
        }
        var $htmlEditorBlock = $("#enlargedContentEditor");
        if ($htmlEditorBlock.is(":visible")) {
            return "html";
        }
        return "";
    };
    var synchronizeEditorTab = function(editorType) {
        if (!editorType || editorType === "") {
            return;
        }
        var tabLink = $('[data-toggle-tab$="' + editorType + '"]');
        if (tabLink) {
            tabLink.trigger("click");
        }
    };
    const updateCharsCounter = function($el) {
        const count = $el.val().length;
        $('[data-enlarged-char-counter-for="' + $el.attr("id") + '"]').find("span:first").text(t("fields.content.charactersEntered", count));
    };
    this.addAction({
        "editor:create": "count-enlarged-textarea-chars",
        "editor:change": "count-enlarged-textarea-chars"
    }, function() {
        updateCharsCounter(this.el);
    });
    this.addAction({
        click: "hide-enlarged-char-counter"
    }, function() {
        hideCharCounter();
    });
    this.addAction({
        click: "show-enlarged-char-counter"
    }, function() {
        showCharCounter();
    });
    function showCharCounter() {
        $("[data-enlarged-char-counter-for]").first().show();
    }
    function hideCharCounter() {
        $("[data-enlarged-char-counter-for]").first().hide();
    }
});

AGN.Lib.Controller.new("export-view", function() {
    var adminHasOwnColumnPermission;
    var columnMappingRowTemplate;
    var bounceUserStatusCode;
    var $columnMappingsTable;
    this.addDomInitializer("export-view", function() {
        adminHasOwnColumnPermission = this.config.adminHasOwnColumnPermission;
        bounceUserStatusCode = this.config.bounceUserStatusCode;
        updateBouncesColumnOptionVisibility();
        if (adminHasOwnColumnPermission) {
            initColumnMappingTable(getColumnMappingSortedByName(this.config.customColumns));
        }
    });
    this.addAction({
        click: "save"
    }, function() {
        submitForm();
    });
    this.addAction({
        click: "evaluate"
    }, function() {
        submitForm();
    });
    this.addAction({
        change: "add-bounce-col-to-choose"
    }, updateBouncesColumnOptionVisibility);
    this.addAction({
        click: "add-column-mapping",
        enterdown: "mapping-enterdown"
    }, function() {
        var form = AGN.Lib.Form.get($("#exportForm"));
        var $lastRowNameInput = getMappingTableLastRow().find("[data-column-name]");
        this.event.preventDefault();
        if (form.valid({})) {
            if ($lastRowNameInput.val()) {
                form.cleanErrors();
                replaceNewButtonWithDeleteButton();
                appendRowToColumnMappingTable("", "");
                getMappingTableLastRow().find("[data-column-name]").focus();
            } else {
                $lastRowNameInput.focus();
            }
        } else {
            form.handleErrors();
        }
    });
    this.addAction({
        click: "delete-column-mapping"
    }, function() {
        this.el.closest("tr").remove();
    });
    function initColumnMappingTable(mappings) {
        $columnMappingsTable = $("#columnMappings tbody");
        columnMappingRowTemplate = AGN.Lib.Template.prepare("column-mapping-table-row");
        _.each(mappings, function(mapping) {
            appendRowToColumnMappingTable(mapping.dbColumn, mapping.defaultValue);
        });
        appendRowToColumnMappingTable("", "");
        if (!AGN.Lib.Form.get($("#exportForm")).editable) {
            $columnMappingsTable.find(":input, button").prop("disabled", true);
            $columnMappingsTable.find("a").attr("disabled", "disabled");
        }
    }
    function getColumnName($row) {
        return $row.find("[data-column-name]").val().trim();
    }
    function getColumnValue($row) {
        return $row.find("[data-column-value]").val().trim();
    }
    function appendRowToColumnMappingTable(name, value) {
        $columnMappingsTable.append(columnMappingRowTemplate({
            name: name,
            value: value
        }));
    }
    function replaceNewButtonWithDeleteButton() {
        var btn = $columnMappingsTable.find('[data-action="add-column-mapping"]');
        btn.after("<a href='#' class='btn btn-regular btn-alert' data-action='delete-column-mapping'>" + "<i class='icon icon-trash-o'></i></a>");
        btn.remove();
    }
    function getMappingTableLastRow() {
        return $columnMappingsTable.find("[data-column-mapping-row]:last-child");
    }
    function collectColumnMapping() {
        var mappings = [];
        _.each($columnMappingsTable.find("[data-column-mapping-row]"), function(row) {
            var $row = $(row);
            var name = getColumnName($row);
            if (name) {
                mappings.push([ name, getColumnValue($row) ]);
            }
        });
        return mappings;
    }
    function setColumnMappingToForm(form) {
        _.each(collectColumnMapping(), function(mapping, index) {
            form.setValue("customColumns[" + index + "].dbColumn", mapping[0]);
            form.setValue("customColumns[" + index + "].defaultValue", mapping[1]);
        });
    }
    function getColumnMappingSortedByName(mappings) {
        return mappings.sort(function(a, b) {
            if (a.dbColumn < b.dbColumn) {
                return -1;
            }
            if (a.dbColumn > b.dbColumn) {
                return 1;
            }
            return 0;
        });
    }
    function updateBouncesColumnOptionVisibility() {
        var $bounceOption = $("#mailing-bounce-column-option");
        var selectedRecipientStatus = $("#recipient-export-recipientstatus").find(":selected").val();
        if (selectedRecipientStatus == bounceUserStatusCode) {
            $bounceOption.removeAttr("disabled");
        } else {
            var $columnsSelect = $('[name="userColumns"]');
            var options = $columnsSelect.val();
            var optionsWithoutBounceOption = options.filter(function(option) {
                return option != "mailing_bounce";
            });
            $columnsSelect.val(optionsWithoutBounceOption);
            $columnsSelect.trigger("change");
            $bounceOption.attr("disabled", "disabled");
        }
    }
    function submitForm() {
        var form = AGN.Lib.Form.get($("#exportForm"));
        if (form.valid({})) {
            setColumnMappingToForm(form);
            form.submit();
        } else {
            form.handleErrors();
        }
    }
});

AGN.Lib.Controller.new("facebook-leadads", function() {
    var Login = AGN_FACEBOOK.Login, LeadAds = AGN_FACEBOOK.LeadAds, SDK = AGN_FACEBOOK.SDK, Select = AGN.Lib.Select;
    var config = {};
    this.addDomInitializer("facebook-leadads", function() {
        config = this.config;
        AGN.Lib.Storage.delete("fblst_" + config.FACEBOOK_LEADADS_APP_ID);
        SDK.load_sdk(config.FACEBOOK_LEADADS_APP_ID, afterInit);
    });
    var enableMailinglist = function(enable) {
        $("#mailinglistId").prop("disabled", !enable);
    };
    var enableDOIMailinglist = function(enable) {
        $("#doiMailingId").prop("disabled", !enable);
    };
    var enablePageConnection = function(enable) {
        $('[data-action="connect-page"]').prop("disabled", !enable);
    };
    var hideInfoForLogged = function() {
        $('[data-action="authorized-info"]:not(.hidden)').addClass("hidden");
    };
    var showInfoForLogged = function() {
        $('[data-action="authorized-info"].hidden').removeClass("hidden");
    };
    var afterInit = function() {
        var loginCallback = function(accessToken) {
            var onError = function() {
                AGN.Lib.Messages(t("defaults.error"), t("messages.error.reload"), "alert");
            };
            setGuiAccordingLoginState();
            LeadAds.list_manageable_pages(accessToken, config.URL.LIST_FACEBOOK_PAGE_BINDINGS_AJAX_URL, "#facebook-pages-table", onError);
        };
        Login.attach_login_function(".facebook-login-btn", loginCallback, "pages_read_engagement, leads_retrieval");
        setGuiAccordingLoginState();
    };
    var setGuiAccordingLoginState = function() {
        Login.doByLoginStatus(null, function() {
            $(".facebook-login-btn").show();
        });
        Login.doByLoginStatus(onLoggedIn, onNotLoggedIn);
    };
    var onNotLoggedIn = function() {
        Select.get($("#mailinglistId")).selectFirstValue();
        enableMailinglist(false);
        enableDOIMailinglist(false);
        enablePageConnection(false);
        hideInfoForLogged();
    };
    var onLoggedIn = function(accessToken) {
        showInfoForLogged();
        enableMailinglist(true);
        LeadAds.list_manageable_pages(accessToken, config.URL.LIST_FACEBOOK_PAGE_BINDINGS_AJAX_URL, "#facebook-pages-table");
        $('[data-action="connect-page"]').data("fbAccessToken", accessToken);
        LeadAds.renew_page_access_tokens(accessToken, config.URL.RENEW_FACEBOOK_PAGE_ACCESS_TOKENS_AJAX_URL, function(result) {
            var json = JSON.parse(result);
            if (json.count > 0) {
                AGN.Lib.Messages(t("defaults.success"), t("facebook.leadAds.renewedPageAccessTokens", json.count), "success");
            }
        });
    };
    this.addAction({
        change: "mailinglist-change"
    }, function() {
        enablePageConnection(false);
        enableDOIMailinglist(false);
        var $el = $(this.el);
        var selectedMailinglist = Select.get($el).getSelectedValue();
        updateDOIMailings(selectedMailinglist);
        enableDOIMailinglist(selectedMailinglist !== 0);
    });
    var updateDOIMailings = function(mailinglistId) {
        var doiMailingsSelect = Select.get($('[data-action="doi-mailing-change"]'));
        doiMailingsSelect.resetOptions();
        doiMailingsSelect.setOptions([ {
            id: 0,
            text: "---"
        } ]);
        doiMailingsSelect.selectFirstValue();
        if (mailinglistId !== 0) {
            enableDOIMailinglist(false);
            $.ajax({
                url: config.URL.LIST_ACTIONBASED_AJAX_URL,
                type: "GET",
                data: {
                    mailinglist: mailinglistId
                },
                success: function(result) {
                    if (result) {
                        var options = _.map(result.mailings, function(mailing) {
                            console.log("mailing " + mailing.id + ": " + mailing.shortname);
                            return {
                                id: mailing.id,
                                text: mailing.shortname
                            };
                        });
                        options.unshift({
                            id: 0,
                            text: "---"
                        });
                        doiMailingsSelect.setOptions(options);
                        doiMailingsSelect.selectFirstValue();
                    }
                },
                error: function(xhr, status, error) {
                    console.log("status = " + status + ", error = " + error);
                    AGN.Lib.Messages(t("defaults.error"), t("messages.error.reload"), "alert");
                },
                statusCode: {
                    500: function() {
                        if (!!onError) {
                            onError();
                        }
                    }
                }
            });
        }
    };
    this.addAction({
        change: "doi-mailing-change"
    }, function() {
        var $el = $(this.el);
        var selectedValue = Select.get($el).getSelectedValue();
        enablePageConnection(selectedValue !== 0);
    });
    this.addAction({
        click: "connect-page"
    }, function() {
        var $el = $(this.el);
        var accessToken = $el.data("fbAccessToken");
        var onSuccess = function() {
            LeadAds.list_manageable_pages(accessToken, config.URL.LIST_FACEBOOK_PAGE_BINDINGS_AJAX_URL, "#facebook-pages-table");
            AGN.Lib.Messages(t("defaults.success"), t("defaults.saved"), "success");
        };
        var mailinglistId = Select.get($('[data-action="mailinglist-change"]')).getSelectedValue();
        var doiMailingId = Select.get($('[data-action="doi-mailing-change"]')).getSelectedValue();
        LeadAds.connect_pages(accessToken, config.URL.CONNECT_FACEBOOK_PAGE_BINDINGS_AJAX_URL, "#facebook-pages-table", mailinglistId, doiMailingId, onSuccess, null, function(json) {
            if (!!json) {
                json.page_names.forEach(function(name) {
                    AGN.Lib.Messages(t("facebook.leadAds.error.already_bound_to_other_company"), name, "alert");
                });
            }
        });
    });
});

AGN.Lib.Controller.new("form-trackable-link", function() {
    var extensionRow;
    AGN.Opt.DefaultExtensions = {};
    this.addDomInitializer("trackable-link-extensions", function() {
        var config = this.config;
        AGN.Opt.DefaultExtensions = config.defaultExtensions;
        extensionRow = AGN.Lib.Template.prepare("extensions-table-row");
        loadExtensionBody(config.extensions);
    });
    this.addAction({
        submission: "bulk-save"
    }, function() {
        var form = $("#userFormTrackableLinksForm");
        var $form = AGN.Lib.Form.get(form);
        collectExtensions($form, "commonExtensions");
        $form.submit();
    });
    this.addAction({
        submission: "save"
    }, function() {
        var form = $("#userFormTrackableLinkForm");
        var $form = AGN.Lib.Form.get(form);
        collectExtensions($form, "extensions");
        $form.submit();
    });
    this.addAction({
        click: "add-default-extensions"
    }, function() {
        _.each(AGN.Opt.DefaultExtensions, function(property) {
            appendLast(property.name, property.value, true);
        });
    });
    this.addAction({
        click: "add-extension"
    }, function() {
        appendLast("", "");
    });
    this.addAction({
        click: "delete-extension"
    }, function() {
        var rowIndex = $(this.el).data("property-id");
        remove(rowIndex);
    });
    this.addAction({
        click: "delete-all-extensions"
    }, function() {
        clean();
    });
    function getName(row) {
        return row.find("[data-extension-name]").val();
    }
    function getValue(row) {
        return row.find("[data-extension-value]").val();
    }
    function isUniqueExtension(name, value) {
        var isUnique = true;
        _.each($("[data-extension-row]"), function(row) {
            var $row = $(row);
            if (isUnique) {
                if (getName($row) == name && getValue($row) == value) {
                    isUnique = false;
                }
            }
        });
        return isUnique;
    }
    function insert(index, name, value) {
        var table = $("#extensions-table tbody");
        if (isUniqueExtension(name, value)) {
            table.append(extensionRow({
                index: index,
                name: name,
                value: value
            }));
        }
    }
    function remove(index) {
        $('[data-extension-row="' + index + '"]').remove();
    }
    function clean() {
        $("[data-extension-row]").remove();
    }
    function appendLast(name, value) {
        var lastIndex = $("#extensions-table tbody [data-extension-row]:last-child").data("extension-row") || 0;
        insert(++lastIndex, name, value);
    }
    function loadExtensionBody(properties) {
        $("#extensions-table tbody").html("");
        _.each(properties, function(property, index) {
            insert(index, property.name, property.value);
        });
    }
    function collectExtensions(form, fieldName) {
        _.each($("[data-extension-row]"), function(row, index) {
            var $row = $(row);
            form.setValueOnce(fieldName + "[" + index + "].name", getName($row));
            form.setValueOnce(fieldName + "[" + index + "].value", getValue($row));
        });
    }
});

AGN.Lib.Controller.new("grid-building-block-defaults", function() {
    var Confirm = AGN.Lib.Confirm, Form = AGN.Lib.Form, Page = AGN.Lib.Page, Helpers = AGN.Lib.Helpers;
    var config;
    this.addDomInitializer("grid-building-block-defaults", function() {
        config = this.config;
        $("img[id^=preview]").each(function() {
            var $img = $(this);
            var src = $img.attr("src");
            if (src) {
                var newSrc = resolveAgnImageTags(src);
                if (newSrc !== src) {
                    $img.attr("src", $.trim(newSrc));
                }
            }
            $img.style("display", "");
        });
        controlCheckPhChildrenVisibility();
    });
    function controlCheckPhChildrenVisibility() {
        config.placeholders.filter(function(placeholder) {
            return placeholder.placeholderType === config.CHECK_PLACEHOLDER_TYPE;
        }).forEach(function(checkPlaceholder) {
            const $childrenContainer = $('<div id="' + checkPlaceholder.id + '-children" class="col-sm-offset-1 col-sm-11" data-show-by-checkbox="#content-' + checkPlaceholder.id + '"></div>');
            $childrenContainer.insertAfter($("#content-" + checkPlaceholder.id).closest(".form-group"));
            checkPlaceholder.options.split(",").forEach(function(phChildId) {
                $childrenContainer.append($(".ph-" + phChildId));
            });
        });
        AGN.Lib.CoreInitializer.run("checkbox-hider", $("#defaultsForm"));
    }
    function getPlaceholderId($element) {
        var $e = $element.closest("[data-placeholder-id]");
        if ($e.exists()) {
            return parseInt($e.data("placeholder-id"));
        } else {
            return 0;
        }
    }
    function checkHasFileSelected(placeholderId) {
        var $file = $("#file-" + placeholderId);
        if ($file.exists()) {
            return !!$file.val();
        } else {
            return false;
        }
    }
    function chooseImageFile($file, placeholderId) {
        var files = $file.prop("files");
        var $content = $("#content-" + placeholderId);
        var $categoryGroup = $("#image-category-" + placeholderId).closest(".form-group");
        if (files && files.length) {
            var file = files[0];
            if (file.type === "image" || file.type.match("image/.*")) {
                var reader = new FileReader();
                reader.onload = function(e) {
                    $categoryGroup.removeClass("hidden");
                    updateImagePreview(placeholderId, e.target.result, file.name, file.name);
                };
                reader.readAsDataURL(file);
            } else {
                $categoryGroup.addClass("hidden");
                Helpers.clearFormField($file);
                updateImagePreview(placeholderId);
            }
        } else {
            $categoryGroup.addClass("hidden");
            updateImagePreview(placeholderId);
        }
        $content.val("");
    }
    function showMediapoolDialog(placeholderId) {
        Confirm.request(config.urls.MEDIAPOOL_IMAGE_PICK).done(function(image) {
            $("#content-" + placeholderId).val(image.id);
            Helpers.clearFormField($("#file-" + placeholderId));
            updateImagePreview(placeholderId, image.src, image.name, image.title);
        });
    }
    function deleteImage(placeholderId) {
        var $file = $("#file-" + placeholderId);
        var $name = $("#file-name-" + placeholderId);
        var $content = $("#content-" + placeholderId);
        var $img = $("#preview-" + placeholderId);
        Helpers.clearFormField($file);
        $name.text("");
        $content.val("");
        $img.attr("src", config.noPreviewImageLink);
    }
    function updateImagePreview(placeholderId, src, name, title) {
        var $img = $("#preview-" + placeholderId);
        var $name = $("#file-name-" + placeholderId);
        if ($img.attr("src") !== src) {
            $img.attr("src", src || config.noPreviewImageLink);
        }
        $img.attr("title", title || "");
        $name.text(name || "");
    }
    function resolveAgnImageTags(html) {
        return Helpers.replaceAgnTags(html, function(tag, tagHtml) {
            if (tag.name === "agnIMAGE" && tag.attributes["name"]) {
                if (!tag.attributes["source"] || tag.attributes["source"] === "mediapool" || tag.attributes["source"] === "mediapoolbg") {
                    return config.imageByFilenameSrcPattern.replace(":filename:", encodeURIComponent(tag.attributes["name"]));
                }
            }
            return tagHtml;
        });
    }
    var updateImageLinkPreview = _.throttle(function(placeholderId, src) {
        var $img = $("#preview-" + placeholderId);
        if ($img.attr("src") !== src) {
            if (src) {
                $img.attr("src", $.trim(resolveAgnImageTags(src)));
            } else {
                $img.attr("src", src || config.noPreviewImageLink);
            }
        }
    }, 300);
    function ajaxImagesSave() {
        var deferred = $.Deferred();
        var entries = [];
        var $form = $("#defaultsForm");
        var form = Form.get($form);
        var valid = true;
        $form.find("input[type=file]").each(function() {
            var $file = $(this);
            var placeholderId = getPlaceholderId($file);
            var $category = $("#image-category-" + placeholderId);
            var files = $file.prop("files");
            if (files && files.length) {
                var categoryId = $category.val();
                if (categoryId > 0) {
                    entries.push({
                        placeholderId: placeholderId,
                        image: files[0],
                        categoryId: categoryId
                    });
                    form.cleanFieldError$($category);
                } else {
                    valid = false;
                    form.showFieldError$($category, t("error.grid.noCategorySelected"));
                }
            } else {
                form.cleanFieldError$($category);
            }
        });
        if (valid) {
            if (entries.length) {
                var data = new FormData();
                entries.forEach(function(e, index) {
                    data.append("images[" + index + "].file", e.image);
                    data.append("images[" + index + "].fileName", e.image.name);
                    data.append("images[" + index + "].title", e.image.name);
                    data.append("images[" + index + "].categoryId", e.categoryId);
                });
                $.ajax(config.urls.MEDIAPOOL_IMAGE, {
                    type: "POST",
                    dataType: "json",
                    accepts: [ "application/json" ],
                    enctype: "multipart/form-data",
                    processData: false,
                    contentType: false,
                    data: data
                }).done(function(resp) {
                    if (resp.success === true) {
                        resp.data.forEach(function(imageId, index) {
                            var placeholderId = entries[index].placeholderId;
                            $("#content-" + placeholderId).val(imageId);
                            Helpers.clearFormField($("#file-" + placeholderId));
                        });
                        deferred.resolve();
                    } else {
                        AGN.Lib.JsonMessages(resp.popups);
                        deferred.reject();
                    }
                }).fail(function() {
                    deferred.reject();
                });
            } else {
                deferred.resolve();
            }
        } else {
            deferred.reject();
        }
        return deferred.promise();
    }
    this.addAction({
        click: "delete"
    }, function() {
        var jqxhr = $.post(config.urls.CONFIRM_DELETE);
        return Confirm.request(jqxhr).done(function(resp) {
            if (resp.success === true) {
                Page.reload(config.urls.BACK, true).done(function() {
                    AGN.Lib.JsonMessages(resp.popups);
                });
            } else {
                AGN.Lib.JsonMessages(resp.popups);
            }
        });
    });
    this.addAction({
        click: "chooseImage"
    }, function() {
        var placeholderId = getPlaceholderId(this.el);
        if (placeholderId > 0) {
            if (checkHasFileSelected(placeholderId)) {
                $("#file-" + placeholderId).trigger("click");
            } else {
                showMediapoolDialog(placeholderId);
            }
        }
    });
    this.addAction({
        click: "showMediapoolDialog"
    }, function() {
        var placeholderId = getPlaceholderId(this.el);
        if (placeholderId > 0) {
            showMediapoolDialog(placeholderId);
        }
    });
    this.addAction({
        change: "chooseImageFile"
    }, function() {
        var placeholderId = getPlaceholderId(this.el);
        if (placeholderId > 0) {
            chooseImageFile(this.el, placeholderId);
        }
    });
    this.addAction({
        click: "deleteImage"
    }, function() {
        var placeholderId = getPlaceholderId(this.el);
        if (placeholderId > 0) {
            deleteImage(placeholderId);
        }
    });
    this.addAction({
        change: "previewImageLink",
        keyup: "previewImageLink",
        mouseup: "previewImageLink"
    }, function() {
        var placeholderId = getPlaceholderId(this.el);
        if (placeholderId > 0) {
            updateImageLinkPreview(placeholderId, $.trim(this.el.val()));
        }
    });
    this.addAction({
        click: "chooseImageLink"
    }, function() {
        var placeholderId = getPlaceholderId(this.el);
        if (placeholderId > 0) {
            $("#content-" + placeholderId).trigger("focus");
        }
    });
    this.addAction({
        click: "save"
    }, function() {
        ajaxImagesSave().done(function() {
            $("#defaultsForm").submit();
        });
    });
});

AGN.Lib.Controller.new("grid-building-block", function() {
    var Confirm = AGN.Lib.Confirm, Page = AGN.Lib.Page;
    var config;
    this.addDomInitializer("grid-building-block", function() {
        config = this.config;
    });
    this.addAction({
        click: "delete"
    }, function() {
        var jqxhr = $.post(config.urls.CONFIRM_DELETE);
        return Confirm.request(jqxhr).done(function(resp) {
            if (resp.success === true) {
                Page.reload(config.urls.BACK, true).done(function() {
                    AGN.Lib.JsonMessages(resp.popups);
                });
            } else {
                AGN.Lib.JsonMessages(resp.popups);
            }
        });
    });
});

AGN.Lib.Controller.new("grid-building-blocks-new", function() {
    var Confirm = AGN.Lib.Confirm, Form = AGN.Lib.Form;
    var config;
    var Dom = {
        setSaveButtonEnabled: function(enabled) {
            var $saveButton = $("#save-button");
            if (enabled) {
                $saveButton.removeClass("disabled");
            } else {
                $saveButton.addClass("disabled");
            }
        },
        getActivenessToggles: function() {
            return $("#containers").find("input.js-activeness-toggle");
        },
        getActivenessTogglesMap: function() {
            var map = {};
            Dom.getActivenessToggles().each(function() {
                var $e = $(this);
                map[$e.data("container-id")] = $e;
            });
            return map;
        },
        getActivenessTogglesStateMap: function() {
            var map = {};
            Dom.getActivenessToggles().each(function() {
                var $e = $(this);
                map[$e.data("container-id")] = $e.prop("checked");
            });
            return map;
        },
        getBulkIds: function() {
            var bulkIds = [];
            $("#containers").find(".js-bulk-ids:checked").each(function() {
                var id = parseInt($(this).val());
                if (id > 0) {
                    bulkIds.push(id);
                }
            });
            return bulkIds.length ? bulkIds : null;
        },
        resetBulkIds: function() {
            $("#containers").find(".js-bulk-ids").prop("checked", false);
        }
    };
    function ActivenessChangeMap() {
        this.map = {};
    }
    ActivenessChangeMap.prototype.include = function(id, value) {
        this.map[id] = value;
    };
    ActivenessChangeMap.prototype.exclude = function(id) {
        delete this.map[id];
    };
    ActivenessChangeMap.prototype.excludeAll = function(ids) {
        for (var i = 0; i < ids.length; i++) {
            delete this.map[ids[i]];
        }
    };
    ActivenessChangeMap.prototype.clear = function() {
        this.map = {};
    };
    ActivenessChangeMap.prototype.size = function() {
        return Object.keys(this.map).length;
    };
    ActivenessChangeMap.prototype.get = function() {
        return _.clone(this.map);
    };
    function ajaxBulkSetActive(ids, active) {
        var activenessMap = {};
        if (arguments.length < 2) {
            active = true;
        } else {
            active = !!active;
        }
        for (var i = 0; i < ids.length; i++) {
            activenessMap[ids[i]] = active;
        }
        return ajaxSetActiveness(activenessMap).done(function(resp) {
            if (resp.success === true) {
                var togglesMap = Dom.getActivenessTogglesMap();
                for (var i = 0; i < ids.length; i++) {
                    var id = ids[i];
                    togglesMap[id].prop("checked", active);
                    config.activenessInitialStateMap[id] = active;
                }
                config.activenessChangeMap.excludeAll(ids);
                Dom.resetBulkIds();
                Dom.setSaveButtonEnabled(config.activenessChangeMap.size() > 0);
            }
        });
    }
    function ajaxSetActiveness(activenessMap) {
        return $.post(config.urls.SET_ACTIVENESS, {
            activeness: activenessMap
        }).done(function(resp) {
            AGN.Lib.JsonMessages(resp.popups);
        });
    }
    function ajaxDelete(id) {
        var jqxhr = $.post(config.urls.CONFIRM_DELETE.replace(":containerId:", id));
        return Confirm.request(jqxhr).done(function(resp) {
            AGN.Lib.JsonMessages(resp.popups);
        });
    }
    function ajaxBulkDelete(ids) {
        var jqxhr = $.ajax(config.urls.CONFIRM_BULK_DELETE, {
            method: "POST",
            traditional: true,
            data: {
                bulkIds: ids
            }
        });
        return Confirm.request(jqxhr).done(function(resp) {
            AGN.Lib.JsonMessages(resp.popups);
        });
    }
    this.addDomInitializer("grid-building-blocks-new", function() {
        config = this.config;
        if (location.hash) {
            var containerId = parseInt(location.hash.substr(1));
            if (containerId > 0) {
                var $containers = $("#containers");
                var $tr = $containers.find('[data-container-id="' + containerId + '"]').closest("tr");
                if ($tr.exists()) {
                    var position = $tr.position().top;
                    $containers.scrollTop(position - 10);
                }
            }
        }
        config.activenessChangeMap = new ActivenessChangeMap();
        config.activenessInitialStateMap = Dom.getActivenessTogglesStateMap();
    });
    this.addAction({
        click: "save"
    }, function() {
        var form = Form.get(this.el);
        ajaxSetActiveness(config.activenessChangeMap.get()).done(function(resp) {
            if (resp.success === true) {
                config.activenessChangeMap.clear();
                config.activenessInitialStateMap = Dom.getActivenessTogglesStateMap();
                Dom.setSaveButtonEnabled(false);
                form.submit();
            }
        });
    });
    this.addAction({
        change: "toggle-activated"
    }, function() {
        var $toggle = $(this.el);
        var id = $toggle.data("container-id");
        var state = $toggle.is(":checked");
        if (config.activenessInitialStateMap[id] == state) {
            config.activenessChangeMap.exclude(id);
        } else {
            config.activenessChangeMap.include(id, state);
        }
        Dom.setSaveButtonEnabled(config.activenessChangeMap.size() > 0);
    });
    this.addAction({
        click: "delete-building-block"
    }, function() {
        var id = this.el.data("container-id");
        var form = Form.get(this.el);
        if (id > 0) {
            ajaxDelete(id).done(function(resp) {
                if (resp.success === true) {
                    form.submit();
                }
            });
        }
    });
    this.addAction({
        click: "bulk-delete"
    }, function() {
        var ids = Dom.getBulkIds();
        var form = Form.get(this.el);
        if (ids) {
            ajaxBulkDelete(ids).done(function(resp) {
                if (resp.success === true) {
                    form.submit();
                }
            });
        } else {
            AGN.Lib.Messages(t("Error"), t("messages.error.nothing_selected"), "alert");
        }
    });
    this.addAction({
        click: "bulk-export"
    }, function() {
        const ids = Dom.getBulkIds();
        const form = Form.get(this.el);
        if (ids) {
            form.setActionOnce(config.urls.BULK_EXPORT);
            form.setValueOnce("bulkIds", ids);
            form.submit("static");
        } else {
            AGN.Lib.Messages(t("Error"), t("messages.error.nothing_selected"), "alert");
        }
    });
    this.addAction({
        click: "bulk-activate"
    }, function() {
        var ids = Dom.getBulkIds();
        var form = Form.get(this.el);
        if (ids) {
            ajaxBulkSetActive(ids, true).done(function(resp) {
                if (resp.success === true) {
                    form.submit();
                }
            });
        } else {
            AGN.Lib.Messages(t("Error"), t("messages.error.nothing_selected"), "alert");
        }
    });
    this.addAction({
        click: "bulk-deactivate"
    }, function() {
        var ids = Dom.getBulkIds();
        var form = Form.get(this.el);
        if (ids) {
            ajaxBulkSetActive(ids, false).done(function(resp) {
                if (resp.success === true) {
                    form.submit();
                }
            });
        } else {
            AGN.Lib.Messages(t("Error"), t("messages.error.nothing_selected"), "alert");
        }
    });
    this.addAction({
        click: "back"
    }, function() {
        history.back();
    });
});

AGN.Lib.Controller.new("grid-edit", function() {
    const self = this, Form = AGN.Lib.Form;
    this.addDomInitializer("grid-edit", function() {
        self.isGridInUse = this.config.isGridInUse;
        self.maxColumnsCount = this.config.maxColumnsCount;
        self.gridView = new AGN.Lib.GridView($("[data-grid-view]"));
        self.gridColumnView = new AGN.Lib.GridColumnView($("[data-column-view]"));
        self.updateViews();
    });
    this.addAction({
        submission: "createTemplate"
    }, function() {
        $("#templateCreationForm").submit();
    });
    this.addAction({
        submission: "saveGrid"
    }, function() {
        const $form = $("#gridForm");
        Form.get($form).submit();
    });
    this.addAction({
        change: "updateColnum"
    }, function() {
        self.validateRequiredNumber(this.el, 1, self.maxColumnsCount);
        $('[name="columnWidth"]').val(self.calculateColumnWidth());
        self.updateViews();
    });
    this.addAction({
        change: "updateTemplateWidth"
    }, function() {
        self.validateRequiredNumber(this.el, 50, 2e3);
        $('[name="columnWidth"]').val(self.calculateColumnWidth());
        self.updateViews();
    });
    this.addAction({
        change: "updateColumnWidth"
    }, function() {
        self.validateRequiredNumber(this.el, 10, 2e3);
        $('[name="templateWidth"]').val(self.calculateTemplateWidth());
        self.updateViews();
    });
    this.addAction({
        change: "updateGutterWidth"
    }, function() {
        self.validateRequiredNumber(this.el, 0, 500);
        $('[name="columnWidth"]').val(self.calculateColumnWidth());
        self.updateViews();
    });
    this.addAction({
        click: "enableEditing"
    }, function() {
        $(this.el).hide();
        $('[name="gridName"]').prop("disabled", false);
        if (!self.isGridInUse) {
            $.each([ "columnNum", "columnWidth", "gutter", "templateWidth" ], function(index, name) {
                const $e = $('[name="' + name + '"]');
                $e.prop("disabled", false);
                $e.attr("type", "number");
            });
        }
        $("#createTemplateButton").addClass("hidden");
        $("#saveAndCreateTemplateButton").removeClass("hidden");
        $("#gridForm").attr("data-action", "saveGrid");
    });
    this.addAction({
        click: "back"
    }, function() {
        window.history.back();
    });
    this.validateRequiredNumber = function(el, min, max) {
        const val = parseInt(el.val());
        if (val != el.val() || val < min) {
            el.val(min);
        }
        if (val > max) {
            el.val(max);
        }
    };
    this.updateViews = function() {
        const viewConfig = {
            columnNum: this.columnNum(),
            columnWidth: this.columnWidth(),
            gutter: this.gutterWidth(),
            templateWidth: this.templateWidth()
        };
        self.gridView.update(viewConfig);
        self.gridColumnView.update(viewConfig);
    };
    this.calculateColumnWidth = function() {
        return Math.floor(this.templateWidth() / this.columnNum() - this.gutterWidth());
    };
    this.calculateTemplateWidth = function() {
        return Math.ceil((this.columnWidth() + this.gutterWidth()) * this.columnNum());
    };
    this.columnNum = function() {
        return parseInt($('[name="columnNum"]').val());
    };
    this.columnWidth = function() {
        return parseInt($('[name="columnWidth"]').val());
    };
    this.gutterWidth = function() {
        return parseInt($('[name="gutter"]').val());
    };
    this.templateWidth = function() {
        return parseInt($('[name="templateWidth"]').val());
    };
});

AGN.Lib.Controller.new("grid-layout-view", function() {
    var Template = AGN.Lib.Template, Tooltip = AGN.Lib.Tooltip, Popover = AGN.Lib.Popover, Modal = AGN.Lib.Modal, Confirm = AGN.Lib.Confirm, Form = AGN.Lib.Form, Action = AGN.Lib.Action, Load = AGN.Lib.Load, Helpers = AGN.Lib.Helpers, Select = AGN.Lib.Select, AutoSave = AGN.Lib.AutoSave;
    var editor;
    var ALL_ENTRIES = -1;
    var ALL_RECIPIENTS = 0;
    var TOP_Z = 500;
    var EMPTY_ROW_HEIGHT = 80;
    var SIDEBAR_BUTTON_HEIGHT = 30;
    var COLLAPSED_BLOCK_SIZE = 10;
    var UNCOLLAPSIBLE_GUTTER_SIZE = 2;
    var CONTROLS_STATE_DISABLED = 0;
    var CONTROLS_STATE_HIDDEN = 1;
    var CONTROLS_STATE_POPOVER = 2;
    var CONTROLS_STATE_INLINE = 3;
    var CONTROLS_POPOVER_TEMPLATE = '<div class="popover popover-wide" role="tooltip" style="margin-top: -5px;"><div class="popover-content"></div><div class="bottom-space"></div></div>';
    var MARKUP_SPAN_TEXT = "Text";
    var MARKUP_SPAN_PLACEHOLDER = "Placeholder";
    var MARKUP_SPAN_TOC_AREA = "TocArea";
    var MARKUP_SPAN_TOC_PLACEHOLDER = "TocPlaceholder";
    var PLACEHOLDER_TYPE_LABEL = "Label";
    var PLACEHOLDER_TYPE_TEXT = "Text";
    var PLACEHOLDER_TYPE_LINK = "Link";
    var PLACEHOLDER_TYPE_IMAGE = "Image";
    var PLACEHOLDER_TYPE_IMAGE_SRC = "ImageLink";
    var PLACEHOLDER_TYPE_SELECT = "Select";
    var PLACEHOLDER_TYPE_COLOR = "Color";
    var PLACEHOLDER_TYPE_CHECK = "Check";
    var TOC_PLACEHOLDER_TYPE_ID = "Id";
    var TOC_PLACEHOLDER_TYPE_NAME = "Name";
    var TOC_ID_PREFIX = "toc_";
    var DIRECTION_NONE = "";
    var DIRECTION_EAST = "e";
    var DIRECTION_WEST = "w";
    var DIRECTION_NORTH = "n";
    var DIRECTION_SOUTH = "s";
    var IS_BASIC_LB = false;
    var EDITABLE_CONTAINER = 0;
    var ANCHORED_CONTAINER = 2;
    var FIXED_AND_ANCHORED_CONTAINER = 3;
    var Ui = {
        setShown: function($e, isShown) {
            if (isShown) {
                $e.removeClass("hidden");
            } else {
                $e.addClass("hidden");
            }
        },
        setTooltip: function($e, tip) {
            $e.data("tooltip", tip);
            Tooltip.createTip($e, tip);
        },
        removeTooltip: function($e) {
            Tooltip.remove($e);
        },
        checkHoverState: function($e) {
            if ($e.is(":hover")) {
                $e.trigger("mouseleave").trigger("mouseenter");
            }
        },
        setLoading: function(isLoading) {
            $("#editor-progress").toggle(!!isLoading);
            $("#disabled-save-button").toggle(!!isLoading);
            $("#save-button").toggle(!isLoading);
            $("#navbar-disabled-save-button").toggle(!!isLoading);
            $("#navbar-save-button").toggle(!isLoading);
        },
        setEditable: function(isEditable) {
            $("#save-button").toggle(!!isEditable);
            $("#navbar-save-button").toggle(!!isEditable);
            $("#building-blocks-search").toggleClass("disabled", !isEditable);
            $("#update-text-version").toggle(!!isEditable);
            $("#grid-tile-content").toggleClass("translucent", !isEditable);
            if (isEditable) {
                $("#visibleTargets").select2("enabled");
            } else {
                $("#visibleTargets").select2("disable");
            }
        },
        setTargetId: function(targetId) {
            $("#visibleTargets").select2("val", targetId);
        },
        getAvailableTargetIds: function() {
            return $("#visibleTargets").children("option").get().map(function(option) {
                return parseInt($(option).val());
            });
        },
        setAvailableTargetIds: function(targets) {
            var exTargets = this.getAvailableTargetIds();
            var $targets = $("#visibleTargets");
            $targets.empty();
            targets.push({
                id: ALL_ENTRIES,
                name: t("filter.reset")
            });
            _.sortBy(targets, function(e) {
                if (e.id > ALL_RECIPIENTS) {
                    return exTargets.indexOf(parseInt(e.id));
                } else if (e.id == ALL_RECIPIENTS) {
                    return 1e6;
                } else {
                    return 1000001;
                }
            }).forEach(function(e) {
                $("<option></option>").val(e.id).text(e.name).appendTo($targets);
            });
        },
        imagesAdjusted: function($e, ignorePreAdjustment) {
            var deferred = $.Deferred();
            var width = undefined, height = undefined;
            if (ignorePreAdjustment === true) {
                width = $e.outerWidth();
                height = $e.outerHeight();
            }
            var callback = function() {
                var w = $e.outerWidth(), h = $e.outerHeight();
                if (width !== w || height !== h) {
                    width = w;
                    height = h;
                    deferred.notify();
                }
            };
            $e.imagesLoaded().progress(callback).always(callback);
            return deferred.promise();
        },
        getHeightAccurate: function($e) {
            return $e[0].getBoundingClientRect().height;
        },
        getResizeHandleDirection: function($e) {
            if ($e.hasClass("ui-resizable-ne")) {
                return new ResizingDirection("ne");
            }
            if ($e.hasClass("ui-resizable-se")) {
                return new ResizingDirection("se");
            }
            if ($e.hasClass("ui-resizable-nw")) {
                return new ResizingDirection("nw");
            }
            if ($e.hasClass("ui-resizable-sw")) {
                return new ResizingDirection("sw");
            }
            if ($e.hasClass("ui-resizable-e")) {
                return new ResizingDirection("e");
            }
            if ($e.hasClass("ui-resizable-w")) {
                return new ResizingDirection("w");
            }
            if ($e.hasClass("ui-resizable-n")) {
                return new ResizingDirection("n");
            }
            if ($e.hasClass("ui-resizable-s")) {
                return new ResizingDirection("s");
            }
            console.error("Invalid resizing direction handle");
            return new ResizingDirection("");
        }
    };
    window.onbeforeunload = function(e) {
        if ($('[data-controller="grid-layout-view"]').exists()) {
            var message = t("grid.layout.leaveQuestion");
            e = e || window.event;
            if (editor && editor.isChanged()) {
                if (e) {
                    e.returnValue = message;
                }
                return message;
            }
        }
        AGN.Lib.Loader.show();
    };
    this.addDomInitializer("grid-layout-view", function($e) {
        if (!editor) {
            editor = new Editor();
        }
        var config = $e.json();
        IS_BASIC_LB = config.IS_BASIC_LB;
        var restoreFromAutoSave = function(savedData) {
            var newConfig = $.extend(config, {
                children: savedData.children
            });
            editor.setup(newConfig);
            editor.setChanged(true);
        };
        var autoSavePromise = AutoSave.initialize("template-components/" + config.templateId, _.bind(editor.getDataForAutoSave, editor), _.bind(editor.checkIfDataRestoreNeeded, editor), restoreFromAutoSave, 0);
        autoSavePromise.fail(function() {
            editor.setup(config);
        });
        editor.controlRssBtn();
    });
    this.addDomInitializer("available-building-blocks-menu", function($menu) {
        var $cache = $("#div-containers-cache");
        var samples = {};
        $cache.children("[data-container-id]").each(function() {
            var $e = $(this);
            var sample = new ChildSample($e.json());
            samples[sample.getContainerId()] = sample;
        });
        $menu.find("[data-building-block]").each(function() {
            var $block = $(this);
            var containerId = $block.data("container-id");
            var sample = samples[containerId];
            if (sample) {
                Child.set($block, sample);
                if (editor.isEditable()) {
                    $block.draggable(ChildSample.draggableOptions());
                }
            }
        });
        $cache.remove();
    });
    this.addDomInitializer("mailing-building-blocks-menu", function($menu) {
        const $cache = $("#mailing-div-containers-cache");
        const children = {};
        $cache.children("[data-child-id]").each(function() {
            const $e = $(this);
            const child = new Child($e.json());
            children[child.getId()] = child;
        });
        $menu.find("[data-building-block]").each(function() {
            const $block = $(this);
            const childId = $block.data("child-id");
            const child = children[childId];
            if (child) {
                Child.set($block, child);
                if (editor.isEditable()) {
                    $block.draggable(ChildSample.draggableOptions());
                }
            }
        });
        $cache.remove();
    });
    this.addAction({
        click: "clear-recycle-bin"
    }, function() {
        if (!editor.isEditable()) {
            return;
        }
        const children = editor.getRecycledChildren();
        if (children.length) {
            $.ajax(this.el.attr("href"), {
                method: "POST",
                traditional: true,
                data: {
                    children: children
                }
            }).done(function(resp) {
                if (resp.success) {
                    editor.clearRecycleBin();
                }
            });
        } else {
            editor.clearRecycleBin();
        }
    });
    this.addAction({
        change: "visibleTargets"
    }, function() {
        if (editor.isEditable()) {
            editor.setTargetId(parseInt(this.el.val()));
        }
    });
    this.addAction({
        "select2-open": "visibleTargets"
    }, function() {
        if (editor.isEditable()) {
            var $select = this.el;
            var $results = $select.select2("dropdown").find(".select2-results");
            $results.css("overflow", "hidden");
            $results.children(".select2-result").each(function() {
                var $this = $(this);
                if ($this.data("select2-data").id > 0) {
                    $this.addClass("sortable");
                }
            });
            $results.sortable({
                items: ".select2-result.sortable",
                containment: "parent",
                tolerance: "pointer",
                distance: 5,
                opacity: .4,
                cursor: "move",
                start: function(event, ui) {
                    ui.item.removeClass("select2-result-selectable");
                },
                stop: function(event, ui) {
                    ui.item.addClass("select2-result-selectable");
                },
                update: function(event, ui) {
                    var d = ui.item.data("select2-data");
                    var $prev = ui.item.prev();
                    var $next = ui.item.next();
                    if ($prev.length) {
                        var prev = $prev.data("select2-data");
                        $(prev.element[0]).after($(d.element[0]));
                    } else if ($next.length) {
                        var next = $next.data("select2-data");
                        $(next.element[0]).before($(d.element[0]));
                    }
                    editor.setLayeringByTargets(Ui.getAvailableTargetIds());
                }
            });
        }
    });
    this.addAction({
        "select2-close": "visibleTargets"
    }, function() {
        if (editor.isEditable()) {
            this.el.select2("dropdown").find(".select2-results").sortable("destroy");
        }
    });
    this.addAction({
        change: "setTemplateReleased"
    }, function() {
        if (editor.isEditable()) {
            $("#is-released").val(this.el.is(":checked") ? "true" : "false");
            editor.setChanged(true);
        }
    });
    this.addAction({
        click: "toggleGutter"
    }, function() {
        if (editor.isEditable()) {
            var row = Row.get(this.el);
            row.setGuttered(!row.isGuttered());
            editor.setChanged(true);
            editor.adjust();
        }
    });
    this.addAction({
        click: "insertRow"
    }, function() {
        if (editor.isEditable()) {
            editor.addRowBefore(Row.get(this.el));
        }
    });
    this.addAction({
        click: "addRow"
    }, function() {
        if (editor.isEditable()) {
            editor.addRow();
        }
    });
    this.addAction({
        click: "deleteRow"
    }, function() {
        if (editor.isEditable()) {
            editor.removeRow(Row.get(this.el));
        }
    });
    this.addAction({
        click: "edit"
    }, function() {
        if (editor.isEditable()) {
            const child = Child.get(this.el);
            if (child) {
                editor.editChild(child);
            }
        }
    });
    this.addAction({
        click: "clone"
    }, function() {
        if (editor.isEditable()) {
            var child = Child.get(this.el);
            if (child) {
                editor.cloneChild(child);
            }
        }
    });
    this.addAction({
        click: "remove"
    }, function() {
        if (editor.isEditable()) {
            var child = Child.get(this.el);
            if (child) {
                editor.removeChild(child);
            }
        }
    });
    this.addAction({
        change: "previewImageSrc",
        keyup: "previewImageSrc",
        mouseup: "previewImageSrc"
    }, function() {
        if (editor.isEditable()) {
            ChildDialog.get(this.el).updateImageSrc(this.el);
        }
    });
    this.addAction({
        change: "chooseImageFile"
    }, function() {
        if (editor.isEditable()) {
            ChildDialog.get(this.el).updateImage(this.el, false);
        }
    });
    this.addAction({
        change: "changeImageCategory"
    }, function() {
        if (editor.isEditable()) {
            const placeholderId = this.el.data("placeholder-id");
            ChildDialog.get(this.el).syncImageCategories(placeholderId, this.el.val());
        }
    });
    this.addAction({
        change: "chooseMobileImageFile"
    }, function() {
        if (editor.isEditable()) {
            ChildDialog.get(this.el).updateImage(this.el, true);
        }
    });
    this.addAction({
        click: "chooseImage"
    }, function() {
        if (editor.isEditable()) {
            var placeholderId = this.el.data("placeholder-id");
            ChildDialog.get(this.el).chooseImage(placeholderId);
        }
    });
    this.addAction({
        click: "deleteImage"
    }, function() {
        if (editor.isEditable()) {
            const placeholderId = this.el.data("placeholder-id");
            ChildDialog.get(this.el).deleteImage(placeholderId, false);
        }
    });
    this.addAction({
        click: "deleteMobileImage"
    }, function() {
        if (editor.isEditable()) {
            const placeholderId = this.el.data("placeholder-id");
            ChildDialog.get(this.el).deleteImage(placeholderId, true);
        }
    });
    this.addAction({
        click: "showMediapoolDialog"
    }, function() {
        if (editor.isEditable()) {
            var placeholderId = this.el.data("placeholder-id");
            ChildDialog.get(this.el).showMediapoolDialog(placeholderId);
        }
    });
    this.addAction({
        submission: "saveChildContents"
    }, function() {
        if (editor.isEditable()) {
            ChildDialog.get(this.el).save(Form.get(this.el));
        }
    });
    $(document).on("ckeditor-save", function() {
        const form = Form.get($("#child-save-button"));
        form.submit("event");
    });
    this.addAction({
        change: "changeContentPool"
    }, function() {
        const $stub = $("#content-pool-stub");
        const $menu = $("#availableMailingsBuildingBlocksArea");
        const mailingId = parseInt(this.el.val());
        if (mailingId > 0) {
            const src = "/mailing/{mailingId}/buildingBlocks.action".replace("{mailingId}", mailingId);
            $menu.removeData();
            $menu.attr("data-load", AGN.url(src));
            Load.load($menu, true);
        } else {
            $menu.empty();
        }
        Ui.setShown($stub, mailingId === 0);
    });
    this.addAction({
        submission: "save-content"
    }, function() {
        if (editor.isEditable()) {
            var isForceGenerateTextVersion = false;
            if (editor.isTextVersionGenerationAllowed()) {
                var updateTextVersion = $("#update-text-version input:checked");
                isForceGenerateTextVersion = updateTextVersion.length > 0;
            }
            editor.saveMadeChoice(isForceGenerateTextVersion);
            editor.save(isForceGenerateTextVersion);
        }
    });
    this.addAction({
        click: "import-from-content-source"
    }, function() {
        new RssImporter().import();
    });
    function RssImporter() {
        RssImporter.prototype.import = function() {
            const self = this;
            this.getRssChildrenToReplaceWithNewContent().forEach(function(rssContainerChild) {
                self._importContent(rssContainerChild);
            });
        };
        RssImporter.prototype.getRssChildrenToReplaceWithNewContent = function() {
            return _.union(this._getRssImportedStartChildren(), this.getRssTemplateChildren());
        };
        RssImporter.prototype._importContent = function(child) {
            const self = this;
            $.get(AGN.url("/layoutbuilder/container/" + child.getContainerId() + "/importRss.action")).done(function(rssChildrenSamples) {
                self.insertRssChildren(self.getRssChildrenFromSamples(rssChildrenSamples), child);
            });
        };
        RssImporter.prototype.insertRssChildren = function(rssChildren, placeholderChild) {
            if (!rssChildren.length) {
                return;
            }
            var col = placeholderChild.getColumn();
            var row = placeholderChild.getRow();
            editor.replaceChildren(placeholderChild, rssChildren[0]);
            rssChildren.slice(1).forEach(function(rssChild) {
                rssChild.setColumn(col);
                rssChild.setRow(row);
                const clone = editor.cloneChild(rssChild);
                col = clone.getColumn();
                row = clone.getRow();
            });
        };
        RssImporter.prototype.getRssChildrenFromSamples = function(samples) {
            return samples.map(function(sample) {
                return new ChildSample(sample).instantiate();
            });
        };
        RssImporter.prototype.getImportedRssChildren = function() {
            return _.groupBy(editor.children.active().children.filter(function(child) {
                return child.isRssImportedChild();
            }), function(child) {
                return child.data.type || child.data.container.type;
            });
        };
        RssImporter.prototype.getRssTemplateChildren = function() {
            return editor.children.active().children.filter(function(child) {
                return child.isRssTemplateChild();
            });
        };
        RssImporter.prototype._removeRssChildrenAndGetPlaceholder = function(children) {
            children.slice(1).forEach(function(child) {
                const rowIndex = child.getRow();
                editor.removeChild(child);
                if (Row.isEmpty(rowIndex)) {
                    editor.removeRow(editor.grid.getRow(rowIndex));
                }
            });
            return children[0];
        };
        RssImporter.prototype._getRssImportedStartChildren = function() {
            const self = this;
            return _.map(this.getImportedRssChildren(), function(child) {
                return self._removeRssChildrenAndGetPlaceholder(child);
            });
        };
    }
    Action.new({
        "form:loadershow": "form"
    }, function() {
        Ui.setLoading(true);
    });
    Action.new({
        "form:loaderhide": "form"
    }, function() {
        Ui.setLoading(false);
    });
    function Editor() {
        var self = this;
        this.templateId = 0;
        this.targetId = ALL_ENTRIES;
        this.targets = new Targets();
        this.categories = new Categories();
        this.children = new Children([]);
        this.imageUriPattern = "{image-id}";
        this.imageByFilenameUriPattern = ":filename:";
        this.watcher = new PromiseProgressWatcher();
        this.removedChildren = [];
        this.adjust = _.throttle(this.adjust, 200);
        this.watcher.promise().progress(function() {
            self.adjust(false);
        });
    }
    Editor.prototype.setup = function(data) {
        data = $.extend({
            templateId: 0,
            targetId: ALL_ENTRIES,
            grid: {},
            children: [],
            imageUriPattern: "{image-id}",
            imageByFilenameUriPattern: ":filename:",
            noPreviewImageLink: "#",
            mobileImagePrefix: "mobile_",
            isTextVersionGenerationAllowed: false,
            isEmptyTextVersion: false,
            targets: [],
            interestGroups: [],
            categories: [],
            translations: {},
            urls: {},
            actions: {}
        }, data);
        $.i18n.load(data.translations);
        this.changesNotSaved = false;
        this.templateId = data.templateId;
        this.targetId = data.targetId;
        this.imageUriPattern = data.imageUriPattern;
        this.imageByFilenameUriPattern = data.imageByFilenameUriPattern;
        this.noPreviewImageLink = data.noPreviewImageLink;
        this.textVersionGenerationAllowed = data.isTextVersionGenerationAllowed;
        this.emptyTextVersion = data.isEmptyTextVersion;
        this.noImageLink = data.noImageLink;
        this.targets = new Targets(data.targets);
        this.interestGroups = data.interestGroups;
        this.categories = new Categories(data.categories);
        this.children = new Children(data.children);
        this.urls = data.urls;
        this.actions = data.actions;
        this.mailingId = data.mailingId;
        this.mobileSuffix = "-mobile";
        this.mobileImagePrefix = data.mobileImagePrefix;
        var children = this.children.active();
        this.grid = new Grid(data.grid, Math.max(1, children.calculateRowsCount()));
        children.rebuildStatic({
            imageUriPattern: this.imageUriPattern,
            imageByFilenameUriPattern: this.imageByFilenameUriPattern,
            noImageLink: this.noImageLink
        });
        children.adjustLayering();
        this.updateAvailableTargets();
        if (this.mailingId > 0) {
            this.editable = AGN.Opt.Components.MailingContentLock.manageLock(this.mailingId, data.isMailingExclusiveLockingAcquired, data.anotherLockingUserName);
        } else {
            this.editable = true;
        }
        Ui.setTargetId(this.targetId);
        this.setTargetId(this.targetId);
        if (this.editable) {
            this.setupInteractions();
            this.updateRecycleBin();
            this.restoreUpdateTextVersionCheckbox(data.mailingId);
            Ui.setLoading(false);
        } else {
            children.each(function(child) {
                child.setDraggable(false);
                child.setControlsEnabled(false);
                child.setResizable(false);
            });
            Ui.setLoading(false);
            Ui.setEditable(false);
        }
        var $menu = $("#availableBuildingBlocksArea");
        var src = "/layoutbuilder/template/{templateId}/activeBuildingBlocks.action".replace("{templateId}", this.templateId);
        $menu.attr("data-load", AGN.url(src));
        Load.load($menu, true);
    };
    Editor.prototype.restoreUpdateTextVersionCheckbox = function() {
        $("#update-text-version").attr("checked", this.getMadeChoice());
    };
    Editor.prototype.setupInteractions = function() {
        var self = this;
        this.children.recycled().each(function(child) {
            child.setRows(1);
            child.setColumns(1);
        });
        function onResizingModeChanged(resizingChild, isEnabled) {
            self.children.active().matching(self.targetId).each(function(child) {
                if (child !== resizingChild) {
                    child.setControlsEnabled(isEnabled);
                    if (!child.isContainerDeleted()) {
                        child.setResizable(isEnabled);
                    }
                    if (child.data.container.modeEdit === ANCHORED_CONTAINER || child.data.container.modeEdit === FIXED_AND_ANCHORED_CONTAINER) {
                        child.setResizable(false);
                    }
                }
            });
        }
        this.grid.setOnResizingStarted(function(resizingChild) {
            onResizingModeChanged(resizingChild, false);
        });
        this.grid.setOnResizingStopped(function(resizingChild) {
            onResizingModeChanged(resizingChild, true);
            self.children.active().stick(resizingChild.getArea());
        });
        var childrenHovered = null;
        this.grid.setOnAreaHovered(function(area) {
            var children = self.children.active().matching(self.targetId);
            if (area) {
                children = children.select(function(child) {
                    return child.isInArea(area);
                });
                if (childrenHovered) {
                    childrenHovered.each(function(child) {
                        if (!children.contains(child)) {
                            child.setHighlighted(false);
                        }
                    });
                }
                children.setHighlighted(true);
                childrenHovered = children;
            } else {
                children.setHighlighted(false);
                childrenHovered = null;
            }
        });
        this.grid.setOnDrop(function(child, droppable, area) {
            var children = self.children.active();
            var isAddedNew = false;
            if (!children.contains(child)) {
                isAddedNew = true;
                if (child instanceof ChildSample) {
                    child = child.instantiate();
                    self.children.add(child);
                } else if (child.isRecycled()) {
                    child.setRecycled(false);
                    self.updateRecycleBin();
                } else {
                    child = child.clone();
                    self.children.add(child);
                }
                if (self.targetId !== ALL_ENTRIES) {
                    child.setTargetId(self.targetId);
                }
                children = self.children.active();
                if (!child.isToc()) {
                    child.rebuild({
                        imageUriPattern: self.imageUriPattern,
                        imageByFilenameUriPattern: self.imageByFilenameUriPattern,
                        noImageLink: self.noImageLink
                    });
                }
            }
            child.setArea(area);
            children.active().stick(area);
            children.matching(self.targetId).rebuildToc({
                imageUriPattern: this.imageUriPattern,
                imageByFilenameUriPattern: this.imageByFilenameUriPattern,
                noImageLink: this.noImageLink
            });
            child.adjustSize(self.grid);
            child.adjustCoordinates(self.grid);
            if (isAddedNew) {
                var containerModeEdit = child.data.container.modeEdit;
                child.setShown(true);
                if (containerModeEdit === ANCHORED_CONTAINER || containerModeEdit === FIXED_AND_ANCHORED_CONTAINER) {
                    child.setDraggable(false);
                    child.setResizable(false);
                }
                self.adjust();
                self.watcher.bind(children.matching(self.targetId).pulse());
            } else {
                self.adjust();
            }
            self.updateAvailableTargets();
            self.setChanged(true);
        });
        $("#children").on("dblclick", "[data-building-block]", function(e) {
            var $target = $(e.target);
            if ($target.is("button") || $target.is(".ui-resizable-handle") || $target.closest("button").exists()) {
                return;
            }
            var $e = $(this);
            var child = Child.get($e);
            var containerEditMode = child.data.container.modeEdit;
            if (child) {
                if (containerEditMode === EDITABLE_CONTAINER || containerEditMode === ANCHORED_CONTAINER) {
                    editor.editChild(child);
                }
            }
        });
    };
    Editor.prototype.updateAvailableTargets = function() {
        var children = this.children.active();
        var targets = this.targets;
        var availableTargets = children.collectTargetIds();
        var precedence = [];
        children.groups().forEach(function(group) {
            var precedenceMap = {};
            group.sort(function(c1, c2) {
                return c1.getZ() - c2.getZ();
            }).forEach(function(child, index) {
                precedenceMap[child.getTargetId()] = index;
            });
            precedence.push(precedenceMap);
        });
        availableTargets.sort(function(targetId1, targetId2) {
            var res = 0;
            precedence.forEach(function(map) {
                if (targetId1 in map && targetId2 in map) {
                    var delta = map[targetId1] - map[targetId2];
                    if (delta < 0) {
                        res++;
                    } else if (delta > 0) {
                        res--;
                    }
                }
            });
            return res;
        });
        Ui.setAvailableTargetIds(availableTargets.map(function(targetId) {
            return {
                id: targetId,
                name: targets.name(targetId)
            };
        }));
        if (availableTargets.indexOf(this.targetId) < 0) {
            this.targetId = ALL_ENTRIES;
        }
        Ui.setTargetId(this.targetId);
    };
    Editor.prototype.getTemplateId = function() {
        return this.templateId;
    };
    Editor.prototype.isTextVersionGenerationAllowed = function() {
        return this.textVersionGenerationAllowed;
    };
    Editor.prototype.saveMadeChoice = function(value) {
        AGN.Lib.WebStorage.set("updateTextVersion_" + this.mailingId, value);
    };
    Editor.prototype.getMadeChoice = function() {
        return AGN.Lib.WebStorage.get("updateTextVersion_" + this.mailingId);
    };
    Editor.prototype.isEmptyTextVersion = function() {
        return this.emptyTextVersion;
    };
    Editor.prototype.isChanged = function() {
        return this.changesNotSaved;
    };
    Editor.prototype.isEditable = function() {
        return this.editable;
    };
    Editor.prototype.setChanged = function(isChanged) {
        if (!!isChanged) {
            this.controlRssBtn();
        }
        this.changesNotSaved = !!isChanged;
    };
    Editor.prototype.getGrid = function() {
        return this.grid;
    };
    Editor.prototype.getTargetName = function(targetId) {
        return this.targets.name(targetId);
    };
    Editor.prototype.setTargetId = function(targetId) {
        var children = this.children.active();
        this.targetId = targetId;
        children.unmatching(this.targetId).setShown(false);
        children = children.matching(this.targetId);
        children.rebuildToc({
            imageUriPattern: this.imageUriPattern,
            imageByFilenameUriPattern: this.imageByFilenameUriPattern,
            noImageLink: this.noImageLink
        });
        children.setShown(true);
        this.adjust();
        this.watcher.bind(children.pulse());
    };
    Editor.prototype.setLayeringByTargets = function(targets) {
        var updateToc = false;
        this.children.active().groups().forEach(function(group) {
            if (group.length > 1) {
                Children.make(group).setLayeringByTargets(targets);
                updateToc = true;
            }
        });
        if (updateToc) {
            this.updateToc(true);
        }
        this.setChanged(true);
        this.adjust(false);
    };
    Editor.prototype.setChildrenControlsEnabled = function(isEnabled) {
        this.children.active().matching(this.targetId).setControlsEnabled(isEnabled);
    };
    Editor.prototype.updateToc = function(adjust) {
        var children = this.children.active().matching(this.targetId);
        if (children.rebuildToc({
            imageUriPattern: this.imageUriPattern,
            imageByFilenameUriPattern: this.imageByFilenameUriPattern,
            noImageLink: this.noImageLink
        }) && adjust) {
            this.adjustSizes(children);
            this.adjustCoordinates(children);
        }
    };
    Editor.prototype.adjustSizes = function(children) {
        if (children === undefined) {
            children = this.children.active().matching(this.targetId);
        }
        children.adjustSizes(this.grid);
        this.grid.adjustRows(children);
    };
    Editor.prototype.adjustCoordinates = function(children) {
        if (children === undefined) {
            children = this.children.active().matching(this.targetId);
        }
        this.grid.adjustSidebars();
        children.adjustCoordinates(this.grid);
    };
    Editor.prototype.adjustLayering = function(children) {
        var self = this;
        if (children === undefined) {
            children = this.children.active().matching(this.targetId);
        }
        var map = children.groupsMap();
        this.grid.each(function(row, rowIndex) {
            row.each(function(droppable, columnIndex) {
                var k = rowIndex + 1 + ":" + (columnIndex + 1);
                var group = Children.make(map[k]);
                if (group.size() > 1) {
                    var index = 1;
                    group.setBorderHighlighted(true);
                    group.each((child, index) => {
                        child.setShown(index === 0);
                    });
                    droppable.setLayeringIndex(index);
                    droppable.setOnLayeringRotate(function() {
                        self.setChanged(true);
                        index = index % group.size() + 1;
                        group.rotateLayering();
                        this.setLayeringIndex(index);
                        self.updateToc(true);
                        self.adjust(false);
                    });
                } else {
                    group.setBorderHighlighted(false);
                    group.each(function(child) {
                        child.setShown(true);
                    });
                    droppable.setLayeringIndex(null);
                    droppable.setOnLayeringRotate(null);
                    self.adjust(false);
                }
            });
        });
    };
    Editor.prototype.adjust = function(adjustLayering) {
        var children = this.children.active().matching(this.targetId);
        if (adjustLayering !== false) {
            this.adjustLayering(children);
        }
        this.adjustSizes(children);
        this.adjustCoordinates(children);
    };
    Editor.prototype.addRowBefore = function(row, adjust) {
        var rowIndex = this.grid.addRowBefore(row);
        var children = this.children.active();
        var isChildrenEnlarged = false;
        children.each(function(child) {
            var rows = child.getRows();
            var minRow = child.getRow();
            var maxRow = minRow + rows - 1;
            if (rowIndex <= minRow) {
                child.setRow(minRow + 1);
            } else if (rowIndex > minRow && rowIndex <= maxRow) {
                isChildrenEnlarged = true;
                child.setRows(rows + 1);
            }
        });
        if (adjust !== false) {
            if (isChildrenEnlarged) {
                this.adjust();
            } else {
                this.adjustCoordinates(children.matching(this.targetId));
            }
        }
        this.setChanged(true);
    };
    Editor.prototype.addRowAfter = function(row) {
        if (!this.isEditable()) {
            return;
        }
        if (this.grid.rows.indexOf(row) == this.grid.getRows() - 1) {
            this.addRow();
        } else {
            const rowIndex = this.grid.rows.indexOf(row);
            this.addRowBefore(this.grid.rows[rowIndex + 1]);
        }
    };
    Editor.prototype.addRow = function(adjust) {
        this.grid.addRow();
        if (adjust !== false) {
            this.grid.adjustSidebars();
        }
        this.setChanged(true);
    };
    Editor.prototype.removeRow = function(row) {
        var rowIndex = this.grid.removeRow(row);
        var children = this.children.active();
        var isChildrenRecycled = false;
        var isChildrenReduced = false;
        children.each(function(child) {
            var rows = child.getRows();
            var minRow = child.getRow();
            var maxRow = minRow + rows - 1;
            if (rowIndex >= minRow && rowIndex <= maxRow) {
                if (rows > 1) {
                    child.setRows(rows - 1);
                    isChildrenReduced = true;
                } else {
                    child.setRecycled(true);
                    isChildrenRecycled = true;
                }
            } else if (rowIndex < minRow) {
                child.setRow(minRow - 1);
            }
        });
        if (isChildrenRecycled) {
            children = this.children.active().matching(this.targetId);
            children.rebuildToc({
                imageUriPattern: this.imageUriPattern,
                imageByFilenameUriPattern: this.imageByFilenameUriPattern,
                noImageLink: this.noImageLink
            });
            this.adjust();
            this.watcher.bind(children.pulse());
            this.updateAvailableTargets();
            this.updateRecycleBin();
        } else if (isChildrenReduced) {
            this.adjust();
        } else {
            this.adjustCoordinates();
        }
        this.setChanged(true);
    };
    Editor.prototype.removeChild = function(child) {
        if (this.children.contains(child)) {
            child.setRecycled(true);
            this.updateToc(false);
            this.adjust();
            this.updateAvailableTargets();
            this.updateRecycleBin();
            this.setChanged(true);
        }
    };
    Editor.prototype.cloneChild = function(child) {
        var self = this;
        var columnsCount = this.grid.getColumns();
        var children = this.children.active();
        function collectMovableGroups(children, rowIndex, columnIndex) {
            var childrenToMove = [];
            var groupingMap = {};
            children.each(function(child) {
                var column = child.getColumn();
                if (rowIndex === child.getRow() && column >= columnIndex) {
                    childrenToMove.push(child);
                    var spans = child.getColumns();
                    groupingMap[column] = Math.min(groupingMap[column] || column, column);
                    for (var n = 1; n < spans; n++) {
                        groupingMap[column + n] = column;
                    }
                }
            });
            var groupsMap = _.groupBy(childrenToMove, function(child) {
                var column = child.getColumn();
                while (groupingMap[column] && groupingMap[column] !== column) {
                    column = groupingMap[column];
                }
                return column;
            });
            var groups = [];
            for (var column = columnIndex; column <= columnsCount; column++) {
                if (groupingMap[column]) {
                    var group = groupsMap[column];
                    if (group) {
                        groups.push(group);
                    }
                } else {
                    groups.push([]);
                }
            }
            return groups;
        }
        function calculateAvailableSpans(movableGroups) {
            var availableSpans = 0;
            movableGroups.forEach(function(group) {
                if (group.length === 0) {
                    availableSpans++;
                }
            });
            return availableSpans;
        }
        function moveGroups(movableGroups, spans) {
            function move(group, steps) {
                var begin = null, end = null;
                group.forEach(function(child) {
                    var b = child.getColumn();
                    var e = b + child.getColumns() - 1;
                    begin = Math.min(begin || b, b);
                    end = Math.max(end || e, e);
                });
                var extraSteps = 0;
                if (end + steps > columnsCount) {
                    extraSteps = columnsCount + 1 - begin - steps;
                    steps = steps + extraSteps;
                }
                group.forEach(function(child) {
                    var column = child.getColumn() + steps;
                    if (column > columnsCount) {
                        child.setRow(child.getRow() + 1);
                        child.setColumn(column - columnsCount);
                    } else {
                        child.setColumn(column);
                    }
                });
                return extraSteps;
            }
            for (var i = 0; i < movableGroups.length && spans > 0; i++) {
                var group = movableGroups[i];
                if (group.length > 0) {
                    spans += move(group, spans);
                } else {
                    spans--;
                }
            }
        }
        function insertRow(rowIndex) {
            var row = self.grid.getRow(rowIndex);
            if (row) {
                self.addRowBefore(row, false);
            } else {
                self.addRow(false);
            }
        }
        function allocateSpaceAndDropClone(children, origin, clone) {
            var row = origin.getRow();
            var cloneSpans = origin.getColumns();
            var nextColumn = origin.getColumn() + cloneSpans;
            var movableGroups = collectMovableGroups(children, row, nextColumn);
            var rightSpans = columnsCount - nextColumn + 1;
            if (rightSpans >= cloneSpans) {
                if (calculateAvailableSpans(movableGroups) >= cloneSpans) {
                    moveGroups(movableGroups, cloneSpans);
                } else {
                    insertRow(row + 1);
                    moveGroups(movableGroups, cloneSpans);
                }
                clone.setRow(row);
                clone.setColumn(nextColumn);
            } else {
                insertRow(row + 1);
                moveGroups(movableGroups, rightSpans + cloneSpans);
                clone.setRow(row + 1);
                clone.setColumn(1);
            }
        }
        var clone = child.clone();
        allocateSpaceAndDropClone(children, child, clone);
        clone.rebuild({
            imageUriPattern: this.imageUriPattern,
            imageByFilenameUriPattern: this.imageByFilenameUriPattern,
            noImageLink: this.noImageLink
        });
        clone.setShown(true);
        this.children.add(clone);
        this.updateToc(false);
        this.watcher.bind(this.children.active().matching(this.targetId).pulse());
        this.adjust();
        this.setChanged(true);
        return clone;
    };
    Editor.prototype.replaceChildren = function(toReplace, replacement) {
        this.removeChild(toReplace);
        replacement.setRow(toReplace.getRow());
        replacement.setColumn(toReplace.getColumn());
        replacement.rebuild({
            imageUriPattern: this.imageUriPattern,
            imageByFilenameUriPattern: this.imageByFilenameUriPattern,
            noImageLink: this.noImageLink
        });
        replacement.setShown(true);
        this.children.add(replacement);
        this.updateToc(false);
        this.watcher.bind(this.children.active().matching(this.targetId).pulse());
        this.adjust();
        this.setChanged(true);
    };
    Editor.prototype.editChild = function(child) {
        if (this.isEditable()) {
            var imageByFilenameUriPattern = this.imageByFilenameUriPattern;
            var options = {
                child: {
                    name: child.getName(),
                    containerName: child.getContainerName(),
                    isToc: child.isToc(),
                    isSortable: child.isSortable(),
                    interestGroup: child.getInterestGroup(),
                    targetId: child.getTargetId(),
                    asTocItem: child.asTocItem(),
                    placeholders: child.getPlaceholders()
                },
                targets: this.targets.list(),
                interestGroups: this.interestGroups.slice(),
                categories: this.categories.list(),
                imageUriPattern: this.imageUriPattern,
                noPreviewImageLink: this.noPreviewImageLink,
                noImageLink: this.noImageLink,
                urls: this.urls,
                mailingId: this.mailingId,
                mobileSuffix: this.mobileSuffix,
                mobileImagePrefix: this.mobileImagePrefix,
                resolveAgnImageTags: function(value) {
                    if (value) {
                        return $.trim(Child.resolveAgnImageTags(value, imageByFilenameUriPattern));
                    } else {
                        return value;
                    }
                }
            };
            if (child.isToc()) {
                options.child.toc = this.children.active().asTocItems(false);
            }
            ChildDialog.create(child, options);
        }
    };
    Editor.prototype.saveChild = function(child, name, targetId, isTocItem, interestGroup, contentMap, includedTocItemsMap) {
        child.setName(name);
        child.setTargetId(targetId);
        child.setTocItem(isTocItem);
        child.setInterestGroup(interestGroup);
        child.setContent(contentMap);
        if (child.isToc()) {
            this.children.active().each(function(child) {
                var isTocItem = includedTocItemsMap[child.getId()];
                if (isTocItem === true || isTocItem === false) {
                    child.setTocItem(isTocItem);
                }
            });
            this.updateToc(false);
        } else {
            child.rebuild({
                imageUriPattern: this.imageUriPattern,
                imageByFilenameUriPattern: this.imageByFilenameUriPattern,
                noImageLink: this.noImageLink
            });
            if (child.isTocItem() || isTocItem || !child.isMatching(this.targetId)) {
                this.updateToc(false);
            }
        }
        if (!child.isMatching(this.targetId)) {
            child.setShown(false);
            this.watcher.bind(this.children.active().matching(this.targetId).pulse());
        }
        this.adjust();
        this.setChanged(true);
        this.updateAvailableTargets();
    };
    Editor.prototype.controlRssBtn = function() {
        $('[data-action="import-from-content-source"]').toggle(this.children.containsRssChildren());
    };
    Editor.prototype.updateRecycleBin = function() {
        var $recyclebin = $("#recyclebin-content");
        var $stub = $("#recyclebin-stub");
        var $clearBtn = $("#recycle-bin-clear-btn");
        this.children.sort(function(c1, c2) {
            if (c1.isRecycled() === c2.isRecycled()) {
                return 0;
            }
            return c1.isRecycled() ? 1 : -1;
        });
        var children = this.children.recycled().get();
        Ui.setShown($stub, children.length === 0);
        Ui.setShown($clearBtn, children.length > 0);
        var $table = Template.dom("recyclebin-table", {
            children: children.map(function(child) {
                return {
                    name: child.getName() || child.getContainerName(),
                    id: child.getId(),
                    containerId: child.getContainerId()
                };
            })
        });
        $recyclebin.html($table);
        $table.find("[data-building-block]").each(function(index) {
            var $e = $(this);
            $e.draggable(ChildSample.draggableOptions());
            Child.set($e, children[index]);
        });
    };
    Editor.prototype.getGuttersAsString = function() {
        var gutters = [];
        this.grid.each(function(row) {
            gutters.push(row.isGuttered() ? "1" : "0");
        });
        return gutters.join("|");
    };
    Editor.prototype.getChildrenAsSubmittable = function() {
        var groups = this.children.active().groups();
        var children = [];
        var targets = Ui.getAvailableTargetIds();
        groups.forEach(function(group) {
            group = _.sortBy(group, function(group) {
                return targets.indexOf(group.getTargetId());
            });
            var zIndex = 0;
            group.forEach(function(child) {
                child.setZ(zIndex++);
                children.push(child.asSubmittable());
            });
        });
        return children;
    };
    Editor.prototype.validateOverlaps = function() {
        var children = this.children.active().select(function(child) {
            return child.getRows() > 1;
        }).get();
        for (var i = 0; i < children.length; i++) {
            var child1 = children[i];
            var minRow1 = child1.getRow();
            var maxRow1 = minRow1 + child1.getRows() - 1;
            for (var j = i + 1; j < children.length; j++) {
                var child2 = children[j];
                var minRow2 = child2.getRow();
                var maxRow2 = minRow2 + child2.getRows() - 1;
                if (minRow2 > minRow1 && minRow2 <= maxRow1 && maxRow2 > maxRow1 || minRow2 < minRow1 && maxRow2 >= minRow1 && maxRow2 < maxRow1) {
                    var minColumn1 = child1.getColumn();
                    var maxColumn1 = minColumn1 + child1.getColumns() - 1;
                    var minColumn2 = child2.getColumn();
                    var maxColumn2 = minColumn2 + child2.getColumns() - 1;
                    if (minColumn2 > maxColumn1 || maxColumn2 < minColumn1) {
                        return false;
                    }
                }
            }
        }
        return true;
    };
    Editor.prototype.save = function(isForceGenerateTextVersion) {
        if (this.validateOverlaps()) {
            var $form = $("#gridTemplateForm");
            var form = Form.get($form);
            this.setChanged(false);
            form.setValue("forceGenerateTextVersion", isForceGenerateTextVersion === true);
            form.setValue("rowGutters", this.getGuttersAsString());
            form.setValue("childrenJson", JSON.stringify(this.getChildrenAsSubmittable()));
            form.setValue("removedChildren", this.removedChildren);
            form.submit("resource");
        } else {
            AGN.Lib.Messages(t("defaults.error"), t("error.template.invalidVerticalSpanning"), "alert");
        }
    };
    Editor.prototype.checkIfDataRestoreNeeded = function(savedData) {
        var currentChildrenData = this.getChildrenData();
        var savedChildrenData = savedData.children;
        if (currentChildrenData.length !== savedChildrenData.length) {
            return true;
        }
        return JSON.stringify(currentChildrenData) !== JSON.stringify(savedChildrenData);
    };
    Editor.prototype.getDataForAutoSave = function() {
        return {
            children: this.getChildrenData()
        };
    };
    Editor.prototype.getChildrenData = function() {
        return this.children.children.map(function(c) {
            return c.data;
        });
    };
    Editor.prototype.clearEmptyAddedOnTheFlyRows = function() {
        const self = this;
        this.grid.each(function(row) {
            row.preventAddOnTheFly = false;
            if (row.isEmptyRowAddedOnTheFly) {
                self.removeRow(row);
            }
        });
    };
    Editor.prototype.processAddedOnTheFlyRows = function(dragEvent) {
        const self = this;
        this.grid.rows.filter(function(row) {
            return row.isAllowedToAppendNewRowOnTheFly(dragEvent.pageX, dragEvent.pageY);
        }).forEach(function(row) {
            self.appendRowOnTheFlyAfter(row);
        });
    };
    Editor.prototype.appendRowOnTheFlyAfter = function(row) {
        this.clearEmptyAddedOnTheFlyRows();
        this.addRowAfter(row);
        const addedOnTheFlyRow = this.grid.rows[editor.grid.rows.indexOf(row) + 1];
        addedOnTheFlyRow.animateAppearance();
        addedOnTheFlyRow.isEmptyRowAddedOnTheFly = true;
        row.preventAddOnTheFly = true;
    };
    Editor.prototype.clearRecycleBin = function() {
        const self = this;
        const recycledChildren = this.children.recycled();
        recycledChildren.each(function(child) {
            if (child.getId() > 0) {
                self.removedChildren.push(child.getId());
            }
        });
        this.children.removeChilds(recycledChildren.get());
        this.updateRecycleBin();
    };
    Editor.prototype.getRecycledChildren = function() {
        const recycledChildren = this.children.recycled().get();
        return recycledChildren.map(function(child) {
            return child.getId();
        }).filter(function(id) {
            return id > 0;
        });
    };
    function Targets(data) {
        var map = {};
        if (data) {
            this.data = data.slice();
            this.data.forEach(function(target) {
                map[target.id] = target.name;
            });
        } else {
            this.data = [];
        }
        this.map = map;
    }
    Targets.prototype.name = function(id) {
        return this.map[id == ALL_ENTRIES ? ALL_RECIPIENTS : id];
    };
    Targets.prototype.list = function() {
        return this.data.slice();
    };
    function Categories(data) {
        var map = {};
        if (data) {
            this.data = data.slice();
            this.data.forEach(function(category) {
                map[category.id] = category.name;
            });
        } else {
            this.data = [];
        }
        this.map = map;
    }
    Categories.prototype.name = function(id) {
        return this.map[id];
    };
    Categories.prototype.list = function() {
        return this.data.slice();
    };
    function Children(data) {
        if (data[0] instanceof Child) {
            this.children = data.slice();
        } else {
            this.children = data.sort(function(a, b) {
                if (a.z === b.z) {
                    if (a.columns === b.columns) {
                        return a.column - b.column;
                    }
                    return b.columns - a.columns;
                }
                return a.z - b.z;
            }).map(function(d) {
                return new Child(d);
            });
        }
    }
    Children.make = function(children) {
        return new Children(children || []);
    };
    Children.prototype.get = function() {
        return this.children.slice();
    };
    Children.prototype.size = function() {
        return this.children.length;
    };
    Children.prototype.each = function(callback) {
        this.children.forEach(callback);
    };
    Children.prototype.sort = function(callback) {
        this.children.sort(callback);
    };
    Children.prototype.contains = function(child) {
        return this.children.indexOf(child) >= 0;
    };
    Children.prototype.containsToc = function() {
        for (var i = 0; i < this.children.length; i++) {
            if (this.children[i].isToc()) {
                return true;
            }
        }
        return false;
    };
    Children.prototype.matching = function(targetId) {
        return this.select(function(child) {
            return child.isMatching(targetId);
        });
    };
    Children.prototype.unmatching = function(targetId) {
        return this.select(function(child) {
            return !child.isMatching(targetId);
        });
    };
    Children.prototype.containsRssChildren = function() {
        return this.active().children.some(function(child) {
            return child.isRssImportedChild() || child.isRssTemplateChild();
        });
    };
    Children.prototype.active = function() {
        return this.select(function(child) {
            return !child.isRecycled();
        });
    };
    Children.prototype.recycled = function() {
        return this.select(function(child) {
            return child.isRecycled();
        });
    };
    Children.prototype.select = function(predicate) {
        return new Children(this.children.filter(predicate));
    };
    Children.prototype.removeChilds = function(childs) {
        this.children = this.children.filter(function(child) {
            return childs.indexOf(child) === -1;
        });
    };
    Children.prototype.add = function(child) {
        child.setZ(this.active().calculateMaxZ() + 1);
        this.children.push(child);
    };
    Children.prototype.groupsMap = function() {
        var map = {};
        var childrenRows = _.groupBy(this.children, function(child) {
            return child.getRow();
        });
        $.each(childrenRows, function(row, children) {
            var migrations = {};
            children.forEach(function(child) {
                var spans = child.getColumns();
                if (spans > 1) {
                    var column = child.getColumn();
                    for (var n = 1; n < spans; n++) {
                        migrations[column + n] = column;
                    }
                }
            });
            children.forEach(function(child) {
                var column = child.getColumn();
                while (migrations[column]) {
                    column = migrations[column];
                }
                var k = row + ":" + column;
                if (map[k] === undefined) {
                    map[k] = [];
                }
                map[k].push(child);
            });
        });
        return map;
    };
    Children.prototype.groups = function() {
        var groups = [];
        var map = this.groupsMap();
        $.each(map, function(k, group) {
            if (group.length) {
                groups.push(group);
            }
        });
        return groups;
    };
    Children.prototype.collectTargetIds = function() {
        var ids = {};
        this.each(function(child) {
            ids[child.getTargetId()] = true;
        });
        return Object.keys(ids).sort();
    };
    Children.prototype.calculateMaxZ = function() {
        return this.children.reduce(function(max, child) {
            return Math.max(child.getZ(), max);
        }, 0);
    };
    Children.prototype.calculateRowsCount = function() {
        return this.children.reduce(function(max, child) {
            return Math.max(child.getRow() + child.getRows() - 1, max);
        }, 0);
    };
    Children.prototype.setShown = function(isShown) {
        this.children.forEach(function(child) {
            child.setShown(isShown);
            var containerModeEdit = child.data.container.modeEdit;
            if (containerModeEdit === ANCHORED_CONTAINER || containerModeEdit === FIXED_AND_ANCHORED_CONTAINER) {
                child.setDraggable(false);
                child.setResizable(false);
            }
        });
    };
    Children.prototype.setBorderHighlighted = function(isHighlighted) {
        this.children.forEach(function(child) {
            child.setBorderHighlighted(isHighlighted);
        });
    };
    Children.prototype.setHighlighted = function(isHighlighted) {
        this.children.forEach(function(child) {
            child.setHighlighted(isHighlighted);
        });
    };
    Children.prototype.setControlsEnabled = function(isEnabled) {
        this.children.forEach(function(child) {
            child.setControlsEnabled(isEnabled);
            if (!child.isContainerDeleted()) {
                child.setResizable(isEnabled);
            }
            child.checkHoverState();
        });
    };
    Children.prototype.asTocItems = function(excludeDisabledAndOverlapped) {
        var children;
        if (excludeDisabledAndOverlapped) {
            children = _.map(this.groupsMap(), function(group) {
                return _.maxBy(group, function(child) {
                    return child.getZ();
                });
            });
        } else {
            children = this.children.slice();
        }
        var toc = children.sort(function(a, b) {
            if (a.getRow() === b.getRow()) {
                if (a.getColumn() === b.getColumn()) {
                    return b.getZ() - a.getZ();
                }
                return a.getColumn() - b.getColumn();
            }
            return a.getRow() - b.getRow();
        }).map(function(child) {
            return child.asTocItem();
        }).filter(function(item) {
            return !!item;
        });
        if (excludeDisabledAndOverlapped) {
            return toc.filter(function(item) {
                return item.isEnabled;
            });
        }
        return toc;
    };
    Children.prototype.pulse = function() {
        var promises = this.children.map(function(child) {
            return child.pulse();
        });
        return promises;
    };
    Children.prototype.rebuildStatic = function(options) {
        this.each(function(child) {
            if (!child.isToc()) {
                child.rebuild(options);
            }
        });
    };
    Children.prototype.rebuildToc = function(options) {
        var self = this;
        var done = false;
        this.each(function(child) {
            if (child.isToc()) {
                child.rebuild($.extend({}, options, {
                    toc: self.asTocItems(true)
                }));
                done = true;
            }
        });
        return done;
    };
    Children.prototype.rotateLayering = function() {
        var children = this.children.slice().sort(function(a, b) {
            return a.getZ() - b.getZ();
        });
        var depths = children.map(function(child) {
            return child.getZ();
        });
        children.forEach(function(child, index) {
            child.setShown(index === 1);
            child.setZ(depths[(index + 1) % depths.length]);
        });
    };
    Children.prototype.setLayeringByTargets = function(targets) {
        var children = this.children.slice().sort(function(a, b) {
            return b.getZ() - a.getZ();
        });
        var depths = children.map(function(child) {
            return child.getZ();
        });
        _.sortBy(children, function(child) {
            return targets.indexOf(child.getTargetId());
        }).forEach(function(child, index) {
            child.setShown(index === 0);
            child.setZ(depths[index]);
        });
    };
    Children.prototype.stick = function(area) {
        this.children.forEach(function(child) {
            if (child.isInArea(area)) {
                child.setArea(area);
            }
        });
    };
    Children.prototype.adjustLayering = function() {
        var z = this.children.length;
        this.children.forEach(function(child) {
            child.setZ(--z);
        });
    };
    Children.prototype.adjustSizes = function(grid) {
        this.children.forEach(function(child) {
            child.adjustSize(grid);
        });
    };
    Children.prototype.adjustCoordinates = function(grid) {
        this.children.forEach(function(child) {
            child.adjustCoordinates(grid);
        });
    };
    function Child(data) {
        var defaults = {
            id: 0,
            name: "",
            targetId: 0,
            row: 0,
            column: 0,
            rows: 1,
            columns: 1,
            z: 0,
            isTocItem: false,
            isRecycled: false,
            interestGroup: "",
            container: {
                id: 0,
                name: "",
                isToc: false,
                isSortable: false,
                markup: [],
                content: {},
                tocItemPlaceholderId: 0,
                type: "",
                filter: ""
            },
            content: undefined
        };
        this.data = _.merge(defaults, data);
        if (this.data.content === undefined) {
            this.data.content = _.clone(this.data.container.content);
        }
        this.capsule = new Capsule(this);
        var containerModeEdit = data.container.modeEdit;
        if (this.isContainerDeleted() || containerModeEdit === ANCHORED_CONTAINER || containerModeEdit === FIXED_AND_ANCHORED_CONTAINER) {
            this.setDraggable(false);
            this.setResizable(false);
        }
    }
    Child.get = function($e) {
        return $e.data("agn:child");
    };
    Child.set = function($e, child) {
        $e.data("agn:child", child);
    };
    Child.resolveAgnImageTags = function(html, imageByFilenameUriPattern) {
        return Helpers.replaceAgnTags(html, function(tag, tagHtml) {
            if (tag.name === "agnIMAGE" && tag.attributes["name"]) {
                if (!tag.attributes["source"] || tag.attributes["source"] === "mediapool" || tag.attributes["source"] === "mediapoolbg") {
                    return imageByFilenameUriPattern.replace(":filename:", encodeURIComponent(tag.attributes["name"]));
                }
            }
            return tagHtml;
        });
    };
    Child.render = function(markup, contentMap, options) {
        var string = "";
        markup.forEach(function(span) {
            switch (span.type) {
              case MARKUP_SPAN_TEXT:
                if (span.value) {
                    string += Child.resolveAgnImageTags(span.value, options.imageByFilenameUriPattern);
                } else {
                    string += span.value;
                }
                break;

              case MARKUP_SPAN_PLACEHOLDER:
                var value = contentMap[span.id];
                if (span.markup) {
                    if (value) {
                        string += Child.render(span.markup, contentMap, options);
                    }
                } else {
                    switch (span.placeholderType) {
                      case PLACEHOLDER_TYPE_LABEL:
                      case PLACEHOLDER_TYPE_TEXT:
                      case PLACEHOLDER_TYPE_LINK:
                      case PLACEHOLDER_TYPE_COLOR:
                      case PLACEHOLDER_TYPE_SELECT:
                      case PLACEHOLDER_TYPE_CHECK:
                        if (value) {
                            string += $.trim(Child.resolveAgnImageTags(value, options.imageByFilenameUriPattern));
                        }
                        break;

                      case PLACEHOLDER_TYPE_IMAGE_SRC:
                        if (value) {
                            string += $.trim(Child.resolveAgnImageTags(value, options.imageByFilenameUriPattern));
                        } else {
                            string += options.noImageLink;
                        }
                        break;

                      case PLACEHOLDER_TYPE_IMAGE:
                        string += parseInt(value) > 0 ? options.imageUriPattern.replace("{image-id}", value) : options.noImageLink;
                        break;

                      default:
                        console.error("Unknown placeholder type: " + span.placeholderType);
                    }
                }
                break;

              case MARKUP_SPAN_TOC_AREA:
                options.toc.forEach(function(item) {
                    string += Child.render(span.markup, contentMap, $.extend({
                        tocItem: item
                    }, options));
                });
                break;

              case MARKUP_SPAN_TOC_PLACEHOLDER:
                switch (span.placeholderType) {
                  case TOC_PLACEHOLDER_TYPE_ID:
                    string += TOC_ID_PREFIX + options.tocItem.id;
                    break;

                  case TOC_PLACEHOLDER_TYPE_NAME:
                    string += options.tocItem.name;
                    break;

                  default:
                    console.error("Unknown TOC placeholder type: " + span.placeholderType);
                }
                break;

              default:
                console.error("Unknown span type: " + span.type);
            }
        });
        return Helpers.escapeAgnTags(string);
    };
    Child.collectPlaceholders = function(markup, contentMap, placeholders, set, predicate) {
        markup.forEach(function(span) {
            switch (span.type) {
              case MARKUP_SPAN_PLACEHOLDER:
                if (!predicate || predicate.call(predicate, span)) {
                    if (set[span.id] === undefined) {
                        placeholders.push({
                            id: span.id,
                            type: span.placeholderType,
                            name: span.name,
                            value: contentMap[span.id],
                            options: span.options,
                            help: span.help
                        });
                        set[span.id] = true;
                    }
                }

              case MARKUP_SPAN_TOC_AREA:
                if (span.markup) {
                    Child.collectPlaceholders(span.markup, contentMap, placeholders, set, predicate);
                }
                break;
            }
        });
    };
    Child.draggableOptions = function() {
        return {
            stack: "#children .div-container",
            revert: "invalid",
            distance: 20,
            cursor: "move",
            opacity: .4,
            start: function() {
                editor.setChildrenControlsEnabled(false);
            },
            stop: function() {
                editor.setChildrenControlsEnabled(true);
            }
        };
    };
    Child.resizableOptions = function(child) {
        var resizing = false;
        return {
            handles: "ne, se, sw, nw, w, n, e, s",
            autoHide: true,
            create: function() {
                resizing = new Resizing(child, editor.getGrid());
            },
            start: function(event, ui) {
                if (resizing === false) {
                    resizing = new Resizing(child, editor.getGrid());
                }
                var $e = $(event.originalEvent.target);
                child.setControlsEnabled(false);
                child.capsule.setResizingEnabled(true);
                resizing.start(Ui.getResizeHandleDirection($e));
            },
            stop: function(event, ui) {
                resizing.stop(ui.size.width, ui.size.height);
                child.capsule.setResizingEnabled(false);
                child.setControlsEnabled(true);
                child.checkHoverState();
                editor.updateToc(false);
                editor.adjust();
                editor.setChanged(true);
            },
            resize: function(event, ui) {
                resizing.resize(ui.size.width, ui.size.height);
            }
        };
    };
    Child.prototype.asSubmittable = function() {
        return {
            id: this.data.id,
            containerId: this.data.container.id,
            name: this.data.name,
            targetId: this.data.targetId,
            interestGroup: this.data.container.isSortable ? this.data.interestGroup || "" : "",
            type: this.data.container.type,
            filter: this.data.container.filter,
            row: this.data.row,
            column: this.data.column,
            rows: this.data.rows,
            columns: this.data.columns,
            content: $.extend({}, this.data.content),
            isTocItem: this.data.isTocItem
        };
    };
    Child.prototype.get$ = function() {
        return this.capsule.get$();
    };
    Child.prototype.getId = function() {
        return this.data.id;
    };
    Child.prototype.getName = function() {
        return this.data.name;
    };
    Child.prototype.getContainerName = function() {
        return this.data.container.name;
    };
    Child.prototype.setName = function(name) {
        this.data.name = name || "";
    };
    Child.prototype.getContainerId = function() {
        return this.data.container.id;
    };
    Child.prototype.isRecycled = function() {
        return this.data.isRecycled;
    };
    Child.prototype.setRecycled = function(isRecycled) {
        if (isRecycled) {
            this.setShown(false);
            this.setRows(1);
            this.setColumns(1);
            this.capsule.recycle();
            this.data.isRecycled = true;
        } else {
            this.data.isRecycled = false;
        }
    };
    Child.prototype.isInArea = function(area) {
        return !this.isNotInArea(area);
    };
    Child.prototype.isNotInArea = function(area) {
        var minColumn = area.column, maxColumn = minColumn + area.columns - 1;
        var minRow = area.row, maxRow = minRow + area.rows - 1;
        var c1 = this.data.column;
        var c2 = c1 + this.data.columns - 1;
        var r1 = this.data.row;
        var r2 = r1 + this.data.rows - 1;
        return Math.max(c1, c2) < minColumn || Math.min(c1, c2) > maxColumn || Math.max(r1, r2) < minRow || Math.min(r1, r2) > maxRow;
    };
    Child.prototype.isMatching = function(targetId) {
        if (targetId === ALL_ENTRIES || this.data.targetId === ALL_RECIPIENTS) {
            return true;
        }
        return this.data.targetId === targetId;
    };
    Child.prototype.isToc = function() {
        return this.data.container.isToc;
    };
    Child.prototype.modeEdit = function() {
        return this.data.container.modeEdit;
    };
    Child.prototype.isTocItem = function() {
        return this.data.isTocItem;
    };
    Child.prototype.setTocItem = function(isTocItem) {
        this.data.isTocItem = !!isTocItem;
    };
    Child.prototype.isSortable = function() {
        return this.data.container.isSortable;
    };
    Child.prototype.getInterestGroup = function() {
        if (this.isSortable()) {
            return this.data.interestGroup || "";
        } else {
            return "";
        }
    };
    Child.prototype.setInterestGroup = function(interestGroup) {
        if (this.isSortable()) {
            this.data.interestGroup = interestGroup || "";
        } else {
            this.data.interestGroup = "";
        }
    };
    Child.prototype.getTargetId = function() {
        return this.data.targetId;
    };
    Child.prototype.setTargetId = function(targetId) {
        this.data.targetId = targetId >= 0 ? targetId : ALL_RECIPIENTS;
        this.capsule.updateControls();
    };
    Child.prototype.getRow = function() {
        return this.data.row;
    };
    Child.prototype.setRow = function(row) {
        return this.data.row = row;
    };
    Child.prototype.getColumn = function() {
        return this.data.column;
    };
    Child.prototype.setColumn = function(column) {
        this.data.column = column;
    };
    Child.prototype.getZ = function() {
        return this.capsule.getZ();
    };
    Child.prototype.setZ = function(z) {
        this.capsule.setZ(z);
    };
    Child.prototype.getRows = function() {
        return this.data.rows;
    };
    Child.prototype.setRows = function(rows) {
        this.data.rows = rows;
    };
    Child.prototype.getColumns = function() {
        return this.data.columns;
    };
    Child.prototype.setColumns = function(columns) {
        this.data.columns = columns;
    };
    Child.prototype.getArea = function() {
        return Grid.area(this.data.row, this.data.column, this.data.rows, this.data.columns);
    };
    Child.prototype.setArea = function(area) {
        this.setRow(area.row);
        this.setColumn(area.column);
        this.setRows(area.rows);
        this.setColumns(area.columns);
    };
    Child.prototype.getHeight = function() {
        return this.capsule.getHeight();
    };
    Child.prototype.setShown = function(isShown) {
        this.capsule.setShown(isShown);
        if (!this.isContainerDeleted()) {
            this.setDraggable(isShown);
            this.setResizable(isShown);
        }
    };
    Child.prototype.setBorderHighlighted = function(isHighlighted) {
        this.capsule.setBorderHighlighted(isHighlighted);
    };
    Child.prototype.setHighlighted = function(isHighlighted) {
        this.capsule.setHighlighted(isHighlighted);
    };
    Child.prototype.setSize = function(width, height) {
        this.capsule.setSize(width, height);
    };
    Child.prototype.setCoordinates = function(coordinates) {
        this.capsule.setCoordinates(coordinates);
    };
    Child.prototype.setControlsEnabled = function(isEnabled) {
        this.capsule.setControlsEnabled(isEnabled);
    };
    Child.prototype.checkHoverState = function() {
        Ui.checkHoverState(this.capsule.get$());
    };
    Child.prototype.adjustSize = function(grid, height) {
        this.setSize(grid.getWidthForSpans(this.getColumns()), height || "auto");
    };
    Child.prototype.adjustHeight = function(height) {
        this.capsule.adjustHeight(height);
    };
    Child.prototype.adjustCoordinates = function(grid) {
        this.setCoordinates(grid.getCoordinates(this.getRow(), this.getColumn()));
    };
    Child.prototype.setDraggable = function(isDraggable) {
        var $capsule = this.capsule.get$();
        if (isDraggable) {
            $capsule.draggable(Child.draggableOptions());
        } else {
            try {
                $capsule.draggable("destroy");
            } catch (e) {}
        }
    };
    Child.prototype.setResizable = function(isResizable) {
        var $capsule = this.capsule.get$();
        if (isResizable) {
            $capsule.resizable(Child.resizableOptions(this));
        } else {
            try {
                $capsule.resizable("destroy");
            } catch (e) {}
        }
    };
    Child.prototype.getPlaceholders = function(type) {
        var contentMap = this.data.content;
        var placeholders = [];
        var set = {};
        var predicate = undefined;
        if (type) {
            predicate = function(span) {
                return span.placeholderType === type;
            };
        }
        Child.collectPlaceholders(this.data.container.markup, contentMap, placeholders, set, predicate);
        placeholders.sort(function(a, b) {
            return a.name.localeCompare(b.name);
        });
        return getOrderedPlaceholders(placeholders);
    };
    function getOrderedPlaceholders(placeholders) {
        const checkPhChildren = new Map(placeholders.filter(function(ph) {
            return ph.type === PLACEHOLDER_TYPE_CHECK;
        }).map(function(ph) {
            return [ ph.id, ph.options.split(",").map(function(childId) {
                return placeholders.find(function(ph) {
                    return childId == ph.id;
                });
            }) ];
        }));
        const allCheckPhChildren = Array.from(checkPhChildren.values()).flat();
        const orderedPlaceholders = [];
        placeholders.filter(function(ph) {
            return !allCheckPhChildren.includes(ph);
        }).forEach(function(parentCheckPh) {
            orderedPlaceholders.push(parentCheckPh);
            if (parentCheckPh.type === PLACEHOLDER_TYPE_CHECK) {
                const children = checkPhChildren.get(parentCheckPh.id);
                children.forEach(function(child) {
                    orderedPlaceholders.push(child);
                });
            }
        });
        return orderedPlaceholders;
    }
    Child.prototype.setContent = function(map) {
        $.extend(this.data.content, map);
    };
    Child.prototype.asTocItem = function() {
        var tocItemPlaceholderId = this.data.container.tocItemPlaceholderId;
        if (tocItemPlaceholderId > 0) {
            var contentMap = this.data.content;
            var placeholders = [];
            var set = {};
            function predicate(span) {
                return span.id === tocItemPlaceholderId;
            }
            Child.collectPlaceholders(this.data.container.markup, contentMap, placeholders, set, predicate);
            if (placeholders.length) {
                var placeholder = placeholders[0];
                return {
                    id: this.data.id,
                    name: contentMap[placeholder.id] || "",
                    placeholderName: placeholder.name,
                    isEnabled: this.data.isTocItem
                };
            }
        }
        return null;
    };
    Child.prototype.rebuild = function(options) {
        this.capsule.embrace(Child.render(this.data.container.markup, this.data.content, options));
    };
    Child.prototype.pulse = function() {
        return this.capsule.pulse();
    };
    Child.prototype.clone = function() {
        var clone = new Child(this.data);
        clone.data.id = 0;
        return clone;
    };
    Child.prototype.isContainerDeleted = function() {
        return this.data.container.isDeleted;
    };
    Child.prototype.isRssTemplateChild = function() {
        return !!(this.data.container.type && this.data.container.type.startsWith("rss:contentSourceId="));
    };
    Child.prototype.isRssImportedChild = function() {
        const rssImportChildType = "rss:import";
        return !!(this.data.container.type && this.data.container.type.startsWith(rssImportChildType)) || !!(this.data.type && this.data.type.startsWith(rssImportChildType));
    };
    function ChildSample(data) {
        this.data = $.extend({
            id: 0,
            name: "",
            isToc: false,
            markup: [],
            content: {}
        }, data);
    }
    ChildSample.draggableOptions = function() {
        return {
            stack: "#children .div-container",
            revert: "invalid",
            distance: 20,
            helper: "clone",
            appendTo: "body",
            containment: "window",
            zIndex: TOP_Z,
            refreshPositions: true,
            start: function(event, ui) {
                ui.helper.width($(this).width());
                editor.setChildrenControlsEnabled(false);
            },
            stop: function(event, ui) {
                ui.helper.width("auto");
                editor.setChildrenControlsEnabled(true);
                editor.clearEmptyAddedOnTheFlyRows();
            },
            drag: function(event, ui) {
                editor.processAddedOnTheFlyRows(event);
            }
        };
    };
    ChildSample.prototype.getContainerId = function() {
        return this.data.id;
    };
    ChildSample.prototype.getRows = function() {
        return 1;
    };
    ChildSample.prototype.getColumns = function() {
        return 1;
    };
    ChildSample.prototype.isToc = function() {
        return this.data.isToc;
    };
    ChildSample.prototype.instantiate = function() {
        return new Child({
            name: this.data.name,
            container: this.data
        });
    };
    function ResizingDirection(code) {
        this.horizontal = DIRECTION_NONE;
        this.vertical = DIRECTION_NONE;
        for (var i = 0; i < code.length; i++) {
            var c = code.charAt(i).toLowerCase();
            switch (c) {
              case DIRECTION_EAST:
              case DIRECTION_WEST:
                if (this.horizontal === DIRECTION_NONE) {
                    this.horizontal = c;
                } else {
                    console.error("Ambiguous direction code: " + code);
                }
                break;

              case DIRECTION_NORTH:
              case DIRECTION_SOUTH:
                if (this.vertical === DIRECTION_NONE) {
                    this.vertical = c;
                } else {
                    console.error("Ambiguous direction code: " + code);
                }
                break;

              default:
                console.error("Unknown direction code: " + c);
            }
        }
    }
    ResizingDirection.prototype.isHorizontal = function() {
        return this.horizontal !== DIRECTION_NONE;
    };
    ResizingDirection.prototype.isVertical = function() {
        return this.vertical !== DIRECTION_NONE;
    };
    ResizingDirection.prototype.isEast = function() {
        return this.horizontal === DIRECTION_EAST;
    };
    ResizingDirection.prototype.isWest = function() {
        return this.horizontal === DIRECTION_WEST;
    };
    ResizingDirection.prototype.isNorth = function() {
        return this.vertical === DIRECTION_NORTH;
    };
    ResizingDirection.prototype.isSouth = function() {
        return this.vertical === DIRECTION_SOUTH;
    };
    function Resizing(child, grid) {
        var $child = child.get$();
        this.child = child;
        this.$child = $child;
        this.grid = grid;
    }
    Resizing.prototype.setupConstraints = function() {
        this.setConstraints(this.grid.getConstraints(this.child, this.direction));
    };
    Resizing.prototype.setConstraints = function(constraints) {
        this.$child.resizable({
            minWidth: constraints.minWidth,
            maxWidth: constraints.maxWidth,
            minHeight: constraints.minHeight,
            maxHeight: constraints.maxHeight
        });
    };
    Resizing.prototype.getArea = function(width, height) {
        return this.grid.getArea(this.child, this.direction, width, height);
    };
    Resizing.prototype.start = function(direction) {
        this.direction = direction;
        this.area = {
            row: this.child.getRow(),
            column: this.child.getColumn(),
            rows: this.child.getRows(),
            columns: this.child.getColumns()
        };
        this.z = this.child.getZ();
        this.setupConstraints();
        this.grid.setAreaHovered(this.area);
        this.grid.startResizing(this.child);
        this.child.setZ(TOP_Z);
    };
    Resizing.prototype.resize = function(width, height) {
        var area = this.getArea(width, height);
        if (area.row !== this.area.row || area.column !== this.area.column || area.rows !== this.area.rows || area.columns !== this.area.columns) {
            this.area = area;
            this.grid.setAreaHovered(area);
        }
    };
    Resizing.prototype.stop = function(width, height) {
        this.area = this.getArea(width, height);
        this.child.setZ(this.z);
        this.child.setRow(this.area.row);
        this.child.setColumn(this.area.column);
        this.child.setRows(this.area.rows);
        this.child.setColumns(this.area.columns);
        this.grid.setAreaHovered(null);
        this.grid.stopResizing(this.child);
        this.child.adjustSize(this.grid);
        this.child.adjustCoordinates(this.grid);
    };
    function Capsule(child) {
        var self = this;
        var deferred = $.Deferred();
        var $capsule = Template.dom("div-sandbox");
        this.promise = deferred.promise();
        this.watcher = new PromiseProgressWatcher();
        this.$capsule = $capsule;
        this.$content = Capsule.stub();
        if (child.isContainerDeleted()) {
            this.showIsDeleted();
        }
        $capsule.find("iframe").on("load", function() {
            var doc = $(this).contents().get(0);
            $(doc.head).append(Capsule.style());
            $(doc.body).append(self.$content);
            self.watcher.bind(Ui.imagesAdjusted(self.$content));
            deferred.resolveWith(self);
        });
        $capsule.appendTo("#children");
        Child.set($capsule, child);
        this.controls = new Controls($capsule);
    }
    Capsule.stub = function() {
        return $('<div class="div-container"></div>');
    };
    Capsule.css = function() {
        return $("#template-styles").html();
    };
    Capsule.style = function() {
        return $("<style/>", {
            html: this.css()
        });
    };
    Capsule.prototype.get$ = function() {
        return this.$capsule;
    };
    Capsule.prototype.updateControls = function() {
        this.controls.update();
    };
    Capsule.prototype.setControlsEnabled = function(isEnabled) {
        this.controls.setEnabled(isEnabled);
    };
    Capsule.prototype.ready = function(callback) {
        if (callback !== undefined) {
            this.promise.done(callback);
        }
        return this.promise.state() === "resolved";
    };
    Capsule.prototype.pulse = function() {
        return this.watcher.promise();
    };
    Capsule.prototype.embrace = function(content) {
        var $content = $(content).filter("*");
        if (this.ready()) {
            this.$content.replaceWith($content);
            this.$content = $content;
            var w = this.$capsule.outerWidth();
            if (w > 0) {
                this.setSize(w, "auto");
            }
            this.watcher.bind(Ui.imagesAdjusted($content, true));
        } else {
            this.$content = $content;
        }
    };
    Capsule.prototype.recycle = function() {
        var self = this;
        this.setShown(false);
        this.ready(function() {
            var $content = Capsule.stub();
            self.watcher.bind(false);
            self.$content.replaceWith($content);
            self.$content = $content;
        });
    };
    Capsule.prototype.getZ = function() {
        return this.$capsule.css("z-index");
    };
    Capsule.prototype.setZ = function(z) {
        this.$capsule.css("z-index", z);
    };
    Capsule.prototype.setShown = function(isShown) {
        Ui.setShown(this.$capsule, isShown);
    };
    Capsule.prototype.setBorderHighlighted = function(isHighlighted) {
        if (isHighlighted) {
            this.$capsule.addClass("highlight-border");
        } else {
            this.$capsule.removeClass("highlight-border");
        }
    };
    Capsule.prototype.setHighlighted = function(isHighlighted) {
        if (isHighlighted) {
            this.$capsule.addClass("highlight-cont");
        } else {
            this.$capsule.removeClass("highlight-cont");
        }
    };
    Capsule.prototype.setCoordinates = function(coordinates) {
        this.$capsule.offset(coordinates);
    };
    Capsule.prototype.setSize = function(width, height) {
        if (!IS_BASIC_LB) {
            this.$content.outerWidth(width);
        }
        this.$capsule.outerWidth(width);
        if (this.ready()) {
            this.$content.style("width", function(value) {
                return value;
            }, "important");
            this.$content.style("height", "auto", "important");
            if (height === "auto") {
                height = this.$content.outerHeight();
            }
            this.$capsule.outerHeight(height);
        } else {
            if (height === "auto") {
                this.$capsule.outerHeight(EMPTY_ROW_HEIGHT);
            } else {
                this.$capsule.outerHeight(height);
            }
        }
    };
    Capsule.prototype.adjustHeight = function(height) {
        this.$capsule.outerHeight(height);
    };
    Capsule.prototype.getHeight = function() {
        if (this.ready()) {
            return Ui.getHeightAccurate(this.$content);
        } else {
            return EMPTY_ROW_HEIGHT;
        }
    };
    Capsule.prototype.setResizingEnabled = function(isEnabled) {
        if (isEnabled) {
            this.$capsule.css("box-sizing", "content-box");
            this.$capsule.css("opacity", .4);
            this.$content.style("width", "100%", "important");
            this.$content.style("height", "100%", "important");
        } else {
            this.$capsule.css("box-sizing", "");
            this.$capsule.css("opacity", "");
        }
    };
    Capsule.prototype.showIsDeleted = function() {
        var $sandboxOverlay = this.$capsule.find(".div-sandbox-overlay");
        $sandboxOverlay.addClass("deleted");
        var $deleteBadge = $('<div class="delete-badge" data-tooltip="' + t("grid.container.deleted") + '">' + ' <i class="icon-fa5 icon-trash"/><span class="text">!</span>' + "</div>");
        Tooltip.create($deleteBadge, Tooltip.options($deleteBadge));
        $sandboxOverlay.append($deleteBadge);
    };
    function ControlsFactory(child) {
        this.child = child;
    }
    ControlsFactory.prototype.getOptions = function() {
        return {
            targetName: editor.getTargetName(this.child.getTargetId()),
            isToc: this.child.isToc(),
            containerDeleted: this.child.isContainerDeleted(),
            containerModeEdit: this.child.modeEdit()
        };
    };
    ControlsFactory.prototype.createControls = function(template) {
        var $controls = Template.dom(template, this.getOptions());
        Child.set($controls.find("[data-action]"), this.child);
        AGN.runAll($controls);
        return $controls;
    };
    ControlsFactory.prototype.createInlineControls = function() {
        return this.createControls("child-controls");
    };
    ControlsFactory.prototype.createPopoverControls = function() {
        return this.createControls("child-popover-controls");
    };
    function Controls($capsule) {
        var controls = this;
        var child = Child.get($capsule);
        this.$capsule = $capsule;
        this.factory = new ControlsFactory(child);
        this.timeoutId = null;
        this.state = CONTROLS_STATE_HIDDEN;
        this.update();
        $capsule.on("mouseenter", function() {
            controls.show();
        });
        $capsule.on("mouseleave", function() {
            controls.hide();
        });
    }
    Controls.popoverOptions = function(controls) {
        return {
            trigger: "manual",
            html: true,
            template: CONTROLS_POPOVER_TEMPLATE,
            content: function() {
                return controls.getPopoverContent();
            }
        };
    };
    Controls.prototype.stopHiding = function() {
        if (this.timeoutId) {
            clearTimeout(this.timeoutId);
            this.timeoutId = undefined;
            return true;
        }
        return false;
    };
    Controls.prototype.popoverShow = function() {
        if (!this.stopHiding()) {
            this.popover.show();
        }
        this.state = CONTROLS_STATE_POPOVER;
    };
    Controls.prototype.popoverHide = function(immediate) {
        this.stopHiding();
        if (immediate === true) {
            this.popover.hide();
            this.state = CONTROLS_STATE_HIDDEN;
        } else {
            var self = this;
            this.timeoutId = setTimeout(function() {
                self.popoverHide(true);
            }, 200);
        }
    };
    Controls.prototype.inlineShow = function() {
        this.$inlineControls.show();
        this.state = CONTROLS_STATE_INLINE;
    };
    Controls.prototype.inlineHide = function() {
        this.$inlineControls.hide();
        this.state = CONTROLS_STATE_HIDDEN;
    };
    Controls.prototype.show = function() {
        if (this.state === CONTROLS_STATE_DISABLED) {
            return;
        }
        if (this.$inlineControls.height() < this.$capsule.height()) {
            if (this.state === CONTROLS_STATE_POPOVER) {
                this.popoverHide(true);
            }
            this.inlineShow();
        } else {
            if (this.state === CONTROLS_STATE_INLINE) {
                this.inlineHide();
            }
            this.popoverShow();
        }
    };
    Controls.prototype.hide = function(immediate) {
        switch (this.state) {
          case CONTROLS_STATE_INLINE:
            this.inlineHide();
            break;

          case CONTROLS_STATE_POPOVER:
            this.popoverHide(immediate);
            break;
        }
    };
    Controls.prototype.setEnabled = function(isEnabled) {
        if (isEnabled) {
            if (this.state === CONTROLS_STATE_DISABLED) {
                this.state = CONTROLS_STATE_HIDDEN;
            }
        } else {
            this.hide(true);
            this.state = CONTROLS_STATE_DISABLED;
        }
    };
    Controls.prototype.update = function() {
        if (this.$inlineControls) {
            this.$inlineControls.remove();
        }
        this.$inlineControls = this.factory.createInlineControls();
        this.$capsule.append(this.$inlineControls);
        if (this.popover) {
            this.popover.destroy();
        }
        if (this.$popoverControls) {
            this.$popoverControls = undefined;
        }
        this.popover = Popover.new(this.$capsule, Controls.popoverOptions(this));
        var $tip = this.popover.tip();
        var controls = this;
        $tip.on("mouseenter", function() {
            controls.popoverShow();
        });
        $tip.on("mouseleave", function() {
            controls.popoverHide();
        });
        if (this.state === CONTROLS_STATE_INLINE || this.state === CONTROLS_STATE_POPOVER) {
            this.show();
        }
    };
    Controls.prototype.getPopoverContent = function() {
        if (this.$popoverControls === undefined) {
            this.$popoverControls = this.factory.createPopoverControls();
            var $buttons = this.$popoverControls.find("[data-action]");
            Child.set($buttons, this.child);
            var controls = this;
            $buttons.on("click", function() {
                controls.popoverHide(true);
            });
        }
        var $content = this.$popoverControls.clone(true);
        AGN.runAll($content);
        return $content;
    };
    Controls.prototype.remove = function() {
        this.state = CONTROLS_STATE_DISABLED;
        this.stopHiding();
        this.popover.destroy();
        this.$popoverControls = undefined;
        this.$inlineControls.remove();
        this.$inlineControls = undefined;
    };
    function PromiseProgressWatcher() {
        this.deferred = $.Deferred();
        this.callback = null;
    }
    PromiseProgressWatcher.prototype.promise = function() {
        return this.deferred.promise();
    };
    PromiseProgressWatcher.prototype.bind = function(src) {
        var self = this;
        if (src === false) {
            self.callback = null;
        } else {
            var callback = self.callback = function() {
                if (self.callback === callback) {
                    self.deferred.notifyWith(this, arguments);
                }
            };
            if ($.isArray(src)) {
                src.forEach(function(promise) {
                    promise.progress(callback);
                });
            } else {
                src.progress(callback);
            }
        }
    };
    var Adjustments = {};
    Adjustments.make = function(grid, children) {
        Adjustments.adjustChildren(grid, children);
        children.forEach(function(child) {
            child.adjustHeight(grid.getHeightForSpans(child.getRow(), child.getColumn(), child.getRows(), child.getColumns()));
        });
    };
    Adjustments.getChildrenProjections = function(grid, children) {
        var rows = [];
        grid.each(function(row) {
            rows.push({
                row: row,
                projections: []
            });
        });
        var cascades = [];
        children.forEach(function(child) {
            var spans = [];
            var cascade = {
                child: child,
                height: child.getHeight(),
                spans: spans
            };
            var minRow = child.getRow();
            var maxRow = minRow + child.getRows() - 1;
            for (var row = minRow; row <= maxRow; row++) {
                var span = {
                    cascade: cascade,
                    height: 0,
                    margin: 0,
                    adjusted: false
                };
                spans.push(span);
                rows[row - 1].projections.push(span);
            }
            cascades.push(cascade);
        });
        $.each(rows, function(index, row) {
            var margin = grid.getRowMargin(row.row.isGuttered());
            $.each(row.projections, function(index, span) {
                span.margin = margin;
            });
        });
        $.each(cascades, function(index, cascade) {
            Adjustments.adjustCascade(cascade);
        });
        return rows;
    };
    Adjustments.adjustCascade = function(cascade) {
        var requiredSpace = Math.max(cascade.height, COLLAPSED_BLOCK_SIZE);
        var minAvailableSpace = 0;
        var spans = cascade.spans;
        var adjustableSpans = [];
        for (var i = 0; i < spans.length; i++) {
            var span = spans[i];
            if (span.adjusted === false) {
                span.height = COLLAPSED_BLOCK_SIZE;
                adjustableSpans.push(span);
            }
            minAvailableSpace += span.height;
            if (minAvailableSpace + span.margin >= requiredSpace) {
                for (i = i + 1; i < spans.length; i++) {
                    spans[i].height = 0;
                }
                break;
            }
            if (i + 1 < spans.length) {
                minAvailableSpace += span.margin;
            }
        }
        var spaceLack = requiredSpace - minAvailableSpace;
        if (spaceLack > 0 && adjustableSpans.length) {
            var portion = spaceLack / adjustableSpans.length;
            $.each(adjustableSpans, function(index, span) {
                span.height += portion;
            });
        }
    };
    Adjustments.adjustChildren = function(grid, children) {
        $.each(Adjustments.getChildrenProjections(grid, children), function(index, row) {
            var projections = row.projections;
            if (projections.length) {
                var maxHeight = 0;
                var maxIndex = 0;
                $.each(projections, function(index, span) {
                    if (span.height > maxHeight) {
                        maxHeight = span.height;
                        maxIndex = index;
                    }
                });
                if (maxHeight === 0) {
                    maxHeight = EMPTY_ROW_HEIGHT;
                }
                $.each(projections, function(index, span) {
                    span.adjusted = true;
                    if (index !== maxIndex) {
                        span.height = maxHeight;
                        Adjustments.adjustCascade(span.cascade);
                    }
                });
                row.row.setHeight(maxHeight);
            } else {
                row.row.setHeight(EMPTY_ROW_HEIGHT);
            }
        });
    };
    function Grid(grid, rows) {
        this.$template = $("#template");
        this.columns = grid.columns;
        this.rows = [];
        this.gap = grid.gap;
        this.columnWidth = grid.columnWidth;
        this.callbacks = {};
        this.hoveredDroppable = null;
        for (var i = 1; i <= rows; i++) {
            var row = this.createRow(grid.gutters[i - 1]);
            this.$template.append(row.get$());
            this.rows.push(row);
        }
        this.adjustSidebars();
    }
    Grid.area = function(row, column, rows, columns) {
        return {
            row: row,
            column: column,
            rows: rows,
            columns: columns
        };
    };
    Grid.prototype.createRow = function(isGuttered) {
        var row = new Row(this.columns, isGuttered);
        var self = this;
        row.setOnHoverChange(function(droppable, child, columnIndex, isHovered) {
            var rowIndex = self.rows.indexOf(row) + 1;
            if (rowIndex > 0) {
                if (isHovered) {
                    self.setAreaHovered(Grid.area(rowIndex, columnIndex, child.getRows(), child.getColumns()));
                    self.hoveredDroppable = droppable;
                } else if (self.hoveredDroppable === droppable) {
                    self.setAreaHovered(false);
                }
            } else {
                self.setAreaHovered(false);
            }
        });
        row.setOnDrop(function(child, droppable, columnIndex) {
            if (self.callbacks.onDrop) {
                var rowIndex = self.rows.indexOf(row) + 1;
                if (rowIndex > 0) {
                    var rows = child.getRows();
                    var rowsAvailable = self.getRows() - rowIndex + 1;
                    if (rows > rowsAvailable) {
                        rows = rowsAvailable;
                    }
                    var columns = child.getColumns();
                    var columnsAvailable = self.getColumns() - columnIndex + 1;
                    if (columns > columnsAvailable) {
                        columns = columnsAvailable;
                    }
                    self.callbacks.onDrop.call(self, child, droppable, Grid.area(rowIndex, columnIndex, rows, columns));
                }
            }
        });
        return row;
    };
    Grid.prototype.each = function(callback) {
        this.rows.forEach(callback);
    };
    Grid.prototype.getRows = function() {
        return this.rows.length;
    };
    Grid.prototype.getColumns = function() {
        return this.columns;
    };
    Grid.prototype.getRow = function(rowIndex) {
        return this.rows[rowIndex - 1] || null;
    };
    Grid.prototype.getDroppable = function(rowIndex, columnIndex) {
        var row = this.getRow(rowIndex);
        if (row) {
            return row.getDroppable(columnIndex);
        }
        return null;
    };
    Grid.prototype.getRowMargin = function(isRowGuttered) {
        return UNCOLLAPSIBLE_GUTTER_SIZE + (isRowGuttered ? this.gap : 0);
    };
    Grid.prototype.getCoordinates = function(rowIndex, columnIndex) {
        return this.getDroppable(rowIndex, columnIndex).getCoordinates();
    };
    Grid.prototype.getConstraints = function(child, direction) {
        return $.extend(this.getWidthConstraints(child, direction), this.getHeightConstraints(child, direction));
    };
    Grid.prototype.getWidthConstraints = function(child, direction) {
        var column = child.getColumn();
        var columns = child.getColumns();
        var minWidth = this.getWidthForSpans(1);
        var maxWidth;
        if (direction.isHorizontal()) {
            if (direction.isEast()) {
                maxWidth = this.getWidthForSpans(this.getColumns() - column + 1);
            } else {
                maxWidth = this.getWidthForSpans(column + columns - 1);
            }
        } else {
            maxWidth = minWidth;
        }
        return {
            minWidth: minWidth,
            maxWidth: maxWidth
        };
    };
    Grid.prototype.getHeightConstraints = function(child, direction) {
        var columns = child.getColumns();
        var wColumn = child.getColumn();
        var eColumn = wColumn + columns - 1;
        var rows = child.getRows();
        var nRow = child.getRow();
        var sRow = nRow + rows - 1;
        var minHeight, maxHeight;
        if (direction.isVertical()) {
            if (direction.isSouth()) {
                minHeight = this.getMinHeightConstraint(nRow, wColumn, 1, columns);
                sRow = this.getRows();
                if (direction.isHorizontal()) {
                    if (direction.isEast()) {
                        eColumn = this.getColumns();
                    } else {
                        wColumn = 1;
                    }
                }
            } else {
                minHeight = this.getMinHeightConstraint(sRow, wColumn, 1, columns);
                nRow = 1;
            }
            maxHeight = this.getMaxHeightConstraint(nRow, wColumn, sRow - nRow + 1, eColumn - wColumn + 1);
        } else {
            minHeight = maxHeight = child.getHeight();
        }
        return {
            minHeight: Math.min(minHeight, child.getHeight()),
            maxHeight: maxHeight
        };
    };
    Grid.prototype.getWidthForSpans = function(spans) {
        if (IS_BASIC_LB) {
            return this.columnWidth;
        }
        return this.columnWidth * spans + this.gap * (spans - 1);
    };
    Grid.prototype.getHeightForSpans = function(rowIndex, columnIndex, rows, columns, reduce) {
        var self = this;
        if (reduce === undefined) {
            reduce = function(droppable1, droppable2) {
                return droppable1.getHeight() > droppable2.getHeight() ? droppable1 : droppable2;
            };
        }
        function pick(index) {
            return self.rows[index - 1].getDroppables().slice(columnIndex - 1, columnIndex + columns - 1).reduce(reduce);
        }
        var topIndex = rowIndex;
        var bottomIndex = rowIndex + rows - 1;
        if (topIndex === bottomIndex) {
            return pick(topIndex).getHeight();
        } else {
            var $top = pick(topIndex).get$();
            var $bottom = pick(bottomIndex).get$();
            return $bottom.position().top - $top.position().top + $bottom.outerHeight();
        }
    };
    Grid.prototype.getMinHeightConstraint = function(rowIndex, columnIndex, rows, columns) {
        function reduce(droppable1, droppable2) {
            return droppable1.getHeight() < droppable2.getHeight() ? droppable1 : droppable2;
        }
        return this.getHeightForSpans(rowIndex, columnIndex, rows, columns, reduce);
    };
    Grid.prototype.getMaxHeightConstraint = function(rowIndex, columnIndex, rows, columns) {
        function reduce(droppable1, droppable2) {
            return droppable1.getHeight() > droppable2.getHeight() ? droppable1 : droppable2;
        }
        return this.getHeightForSpans(rowIndex, columnIndex, rows, columns, reduce);
    };
    Grid.prototype.getArea = function(child, direction, width, height) {
        var self = this;
        var column, columns;
        if (direction.isHorizontal()) {
            columns = Math.ceil(width / (this.columnWidth + this.gap));
            if (direction.isEast()) {
                column = child.getColumn();
            } else {
                column = child.getColumn() + child.getColumns() - columns;
            }
        } else {
            column = child.getColumn();
            columns = child.getColumns();
        }
        function pick(index) {
            var row = self.rows[index - 1];
            if (row) {
                return row.getDroppables().slice(column - 1, column + columns - 1).reduce(function(a, b) {
                    return a.getHeight() > b.getHeight() ? a : b;
                });
            } else {
                return null;
            }
        }
        function positionTop(droppable) {
            return droppable.get$().position().top;
        }
        var row, rows;
        if (direction.isVertical()) {
            var top, bottom;
            rows = 1;
            if (direction.isSouth()) {
                row = child.getRow();
                top = pick(row);
                while (bottom = pick(row + rows)) {
                    if (height > positionTop(bottom) - positionTop(top)) {
                        rows++;
                    } else {
                        break;
                    }
                }
            } else {
                row = child.getRow() + child.getRows() - 1;
                bottom = pick(row);
                while (top = pick(row - 1)) {
                    if (height > positionTop(bottom) - positionTop(top) + bottom.getHeight() - top.getHeight()) {
                        row--;
                        rows++;
                    } else {
                        break;
                    }
                }
            }
        } else {
            row = child.getRow();
            rows = child.getRows();
        }
        return Grid.area(row, column, rows, columns);
    };
    Grid.prototype.setAreaHovered = function(area) {
        if (area) {
            this.each(function(row, rowIndex) {
                if (rowIndex >= area.row - 1 && rowIndex <= area.row - 1 + area.rows - 1) {
                    row.setHovered(true, area.column, area.column + area.columns - 1);
                } else {
                    row.setHovered(false);
                }
            });
        } else {
            this.each(function(row) {
                row.setHovered(false);
            });
        }
        if (this.callbacks.onAreaHovered) {
            this.callbacks.onAreaHovered.call(this, area);
        }
    };
    Grid.prototype.startResizing = function(child) {
        if (this.callbacks.onResizingStarted) {
            this.callbacks.onResizingStarted.call(this, child);
        }
    };
    Grid.prototype.stopResizing = function(child) {
        if (this.callbacks.onResizingStopped) {
            this.callbacks.onResizingStopped.call(this, child);
        }
    };
    Grid.prototype.adjustRows = function(children) {
        Adjustments.make(this, children.get());
    };
    Grid.prototype.getDroppables = function() {
        var droppables = [];
        var gap = this.gap;
        this.each(function(row, rowIndex) {
            var gutterSize = (row.isGuttered() ? gap : 0) + UNCOLLAPSIBLE_GUTTER_SIZE;
            row.each(function(droppable, columnIndex) {
                droppables.push({
                    droppable: droppable,
                    row: rowIndex + 1,
                    column: columnIndex + 1,
                    marginBottom: gutterSize
                });
            });
        });
        return droppables;
    };
    Grid.prototype.adjustSidebars = function() {
        var positions = [];
        $.each(this.rows, function(index, row) {
            var $row = row.get$();
            var rowTopMargin = parseInt($row.css("marginTop"));
            var rowTop = $row.position().top;
            var rowSize = $row.outerHeight(true);
            positions[index] = {
                top: rowTop + rowTopMargin / 2,
                middle: rowTop + rowTopMargin + (rowSize - rowTopMargin) / 2
            };
        });
        $.each(this.rows, function(index, row) {
            var position = positions[index];
            var nextPosition = positions[index + 1];
            row.setRemoveButtonShown(true);
            row.setInsertButtonShown(true);
            row.setGutterButtonShown(!IS_BASIC_LB && !!nextPosition);
            if (!IS_BASIC_LB && nextPosition) {
                row.adjustGutterButton(nextPosition.top - SIDEBAR_BUTTON_HEIGHT / 2);
            }
            if (index === 0) {
                row.adjustInsertButton(0);
                row.adjustRemoveButton(nextPosition ? (nextPosition.top - SIDEBAR_BUTTON_HEIGHT / 2) / 2 : position.middle);
            } else {
                row.adjustInsertButton(position.top - SIDEBAR_BUTTON_HEIGHT / 2);
                row.adjustRemoveButton(position.middle - SIDEBAR_BUTTON_HEIGHT / 2);
            }
        });
    };
    Grid.prototype.addRowBefore = function(row) {
        var index = this.rows.indexOf(row);
        if (index >= 0) {
            var isGuttered = true;
            if (index > 0) {
                isGuttered = this.rows[index - 1].isGuttered();
            }
            var newRow = this.createRow(isGuttered);
            this.rows[index].get$().before(newRow.get$());
            this.rows.splice(index, 0, newRow);
        }
        return index + 1;
    };
    Grid.prototype.addRow = function() {
        if (this.rows.length > 0) {
            this.rows[this.rows.length - 1].setGuttered(true);
        }
        var row = this.createRow(true);
        this.$template.append(row.get$());
        this.rows.push(row);
        return this.rows.length;
    };
    Grid.prototype.removeRow = function(row) {
        var index = this.rows.indexOf(row);
        if (index >= 0) {
            this.rows[index].remove();
            this.rows.splice(index, 1);
        }
        return index + 1;
    };
    Grid.prototype.setOnDrop = function(callback) {
        this.callbacks.onDrop = callback;
    };
    Grid.prototype.setOnAreaHovered = function(callback) {
        this.callbacks.onAreaHovered = callback;
    };
    Grid.prototype.setOnResizingStarted = function(callback) {
        this.callbacks.onResizingStarted = callback;
    };
    Grid.prototype.setOnResizingStopped = function(callback) {
        this.callbacks.onResizingStopped = callback;
    };
    function Row(columns, isGuttered) {
        this.$row = Template.dom("droppables-row");
        this.$gutterButton = Template.dom("toggle-gutter-button");
        this.$removeButton = Template.dom("remove-row-button");
        this.$insertButton = Template.dom("insert-row-button");
        this.$row.data("agn:row", this);
        this.$gutterButton.data("agn:row", this);
        this.$removeButton.data("agn:row", this);
        this.$insertButton.data("agn:row", this);
        this.droppables = [];
        this.callbacks = {};
        for (var column = 1; column <= columns; column++) {
            var droppable = this.createDroppable();
            this.droppables.push(droppable);
            this.$row.append(droppable.get$());
        }
        this.setGuttered(isGuttered);
        this.$gutterButton.appendTo("#sidebar-gutters");
        this.$removeButton.appendTo("#sidebar-actions");
        this.$insertButton.appendTo("#sidebar-actions");
        Ui.setTooltip(this.$removeButton, t("grid.row.delete"));
        Ui.setTooltip(this.$insertButton, t("grid.row.add"));
    }
    Row.get = function($row) {
        return $row.data("agn:row");
    };
    Row.prototype._isPointerAtAddOnTheFlyPosition = function(x, y) {
        const $row = this.$row;
        const tolerance = 10;
        const rowTop = $row.offset().top;
        const rowLeft = $row.offset().left;
        const rowHeight = $row.outerHeight();
        const rowWidth = $row.outerWidth();
        const rowEnd = rowTop + rowHeight;
        const gutter = this.isGuttered() ? editor.grid.gap : 1;
        return x > rowLeft && x < rowLeft + rowWidth && (y > rowEnd - tolerance && y < rowEnd + gutter + tolerance);
    };
    Row.prototype.isAllowedToAppendNewRowOnTheFly = function(x, y) {
        return this._isPointerAtAddOnTheFlyPosition(x, y) && (!this.preventAddOnTheFly && !this.isEmptyRowAddedOnTheFly);
    };
    Row.prototype.animateAppearance = function() {
        const $el = this.$row;
        const $clone = $el.clone(true);
        $el.hide().after($clone);
        $clone.show().addClass("container-row-animated");
        $clone.one("animationend", function() {
            $el.show();
            $clone.remove();
        });
    };
    Row.prototype.createDroppable = function() {
        var droppable = new Droppable(this);
        var self = this;
        droppable.setOnHoverChange(function(child, isHovered) {
            if (self.callbacks.onHoverChange) {
                var droppable = this;
                var columnIndex = self.droppables.indexOf(droppable) + 1;
                if (columnIndex > 0) {
                    self.callbacks.onHoverChange.call(self, droppable, child, columnIndex, isHovered);
                }
            }
        });
        droppable.setOnDrop(function(child) {
            if (self.callbacks.onDrop) {
                var droppable = this;
                var columnIndex = self.droppables.indexOf(droppable) + 1;
                if (columnIndex > 0) {
                    self.callbacks.onDrop.call(self, child, droppable, columnIndex);
                }
            }
        });
        return droppable;
    };
    Row.isEmpty = function(rowIndex) {
        return !editor.children.active().children.some(child => child.getRow() >= rowIndex && child.getRow() + child.getRows() - 1 <= rowIndex);
    };
    Row.prototype.get$ = function() {
        return this.$row;
    };
    Row.prototype.each = function(callback) {
        this.droppables.forEach(callback);
    };
    Row.prototype.getDroppables = function() {
        return this.droppables.slice();
    };
    Row.prototype.getDroppable = function(columnIndex) {
        return this.droppables[columnIndex - 1] || null;
    };
    Row.prototype.setHeight = function(height) {
        if (height > 0) {
            height = Math.max(height, COLLAPSED_BLOCK_SIZE);
        } else {
            height = EMPTY_ROW_HEIGHT;
        }
        this.droppables.forEach(function(droppable) {
            droppable.setHeight(height);
        });
    };
    Row.prototype.isGuttered = function() {
        return this.$row.hasClass("guttered");
    };
    Row.prototype.setGuttered = function(isGuttered) {
        if (isGuttered) {
            this.$row.addClass("guttered");
            Ui.setTooltip(this.$gutterButton, t("grid.gutter.hide"));
            this.$gutterButton.find("#show-spacing-icon").hide();
            this.$gutterButton.find("#hide-spacing-icon").show();
        } else {
            this.$row.removeClass("guttered");
            Ui.setTooltip(this.$gutterButton, t("grid.gutter.show"));
            this.$gutterButton.find("#show-spacing-icon").show();
            this.$gutterButton.find("#hide-spacing-icon").hide();
        }
    };
    Row.prototype.setHovered = function(isHovered, columnBegin, columnEnd) {
        if (columnBegin === undefined) {
            this.droppables.forEach(function(droppable) {
                droppable.setHovered(isHovered);
            });
        } else {
            if (columnEnd === undefined) {
                columnEnd = columnBegin;
            }
            this.droppables.forEach(function(droppable, index) {
                var column = index + 1;
                if (columnBegin <= column && column <= columnEnd) {
                    droppable.setHovered(isHovered);
                } else {
                    droppable.setHovered(!isHovered);
                }
            });
        }
    };
    Row.prototype.remove = function() {
        this.droppables.forEach(function(droppable) {
            droppable.remove();
        });
        this.droppables = [];
        this.$row.remove();
        Ui.removeTooltip(this.$gutterButton);
        this.$gutterButton.remove();
        Ui.removeTooltip(this.$removeButton);
        this.$removeButton.remove();
        Ui.removeTooltip(this.$insertButton);
        this.$insertButton.remove();
        this.callbacks.onDrop = undefined;
    };
    Row.prototype.adjustGutterButton = function(top) {
        this.$gutterButton.css("top", top);
    };
    Row.prototype.setGutterButtonShown = function(isShown) {
        Ui.setShown(this.$gutterButton, isShown);
    };
    Row.prototype.adjustRemoveButton = function(top) {
        this.$removeButton.css("top", top);
    };
    Row.prototype.setRemoveButtonShown = function(isShown) {
        Ui.setShown(this.$removeButton, isShown);
    };
    Row.prototype.adjustInsertButton = function(top) {
        this.$insertButton.css("top", top);
    };
    Row.prototype.setInsertButtonShown = function(isShown) {
        Ui.setShown(this.$insertButton, isShown);
    };
    Row.prototype.setOnHoverChange = function(callback) {
        this.callbacks.onHoverChange = callback;
    };
    Row.prototype.setOnDrop = function(callback) {
        this.callbacks.onDrop = callback;
    };
    function Droppable(row) {
        this.$droppable = Template.dom("droppable");
        this.$droppable.data("agn:droppable", this);
        this.$droppable.droppable(Droppable.options(this));
        this.row = row;
        this.callbacks = {};
    }
    Droppable.get = function($droppable) {
        return $droppable.data("agn:droppable");
    };
    Droppable.options = function(droppable) {
        return {
            accept: "[data-building-block]",
            tolerance: "pointer",
            deactivate: function() {
                droppable.setHovered(false);
                if (droppable.callbacks.onHoverChange) {
                    droppable.callbacks.onHoverChange(false);
                }
            },
            drop: function(event, ui) {
                droppable.setHovered(false);
                if (droppable.callbacks.onDrop) {
                    droppable.callbacks.onDrop(Child.get(ui.draggable));
                }
                droppable.row.isEmptyRowAddedOnTheFly = false;
            },
            over: function(event, ui) {
                if (droppable.callbacks.onHoverChange) {
                    droppable.callbacks.onHoverChange(Child.get(ui.draggable), true);
                } else {
                    droppable.setHovered(true);
                }
            },
            out: function(event, ui) {
                if (droppable.callbacks.onHoverChange) {
                    droppable.callbacks.onHoverChange(Child.get(ui.draggable), false);
                } else {
                    droppable.setHovered(false);
                }
            }
        };
    };
    Droppable.prototype.get$ = function() {
        return this.$droppable;
    };
    Droppable.prototype.getCoordinates = function() {
        return this.$droppable.offset();
    };
    Droppable.prototype.getRow = function() {
        return this.row;
    };
    Droppable.prototype.getHeight = function() {
        return Ui.getHeightAccurate(this.$droppable);
    };
    Droppable.prototype.setHeight = function(height) {
        this.$droppable.outerHeight(height);
    };
    Droppable.prototype.setHovered = function(isHovered) {
        if (isHovered) {
            this.$droppable.addClass("container-hover-accept");
        } else {
            this.$droppable.removeClass("container-hover-accept");
        }
    };
    Droppable.prototype.setLayeringIndex = function(index) {
        if (index > 0) {
            if (this.$rotationButton) {
                this.$rotationButton.css("visibility", "");
                this.$rotationButton.find(".layer-number").text(index);
            } else {
                var droppable = this;
                this.$rotationButton = Template.dom("child-z-index-button", {
                    index: index
                });
                if (editor.isEditable()) {
                    this.$rotationButton.on("click", function() {
                        if (droppable.callbacks.onLayeringRotate) {
                            droppable.callbacks.onLayeringRotate();
                        }
                    });
                }
                this.$droppable.append(this.$rotationButton);
            }
        } else {
            if (this.$rotationButton) {
                this.$rotationButton.css("visibility", "hidden");
            }
        }
    };
    Droppable.prototype.remove = function() {
        this.$droppable.droppable("destroy");
        if (this.$rotationButton) {
            this.$rotationButton.remove();
            this.$rotationButton = undefined;
        }
        this.$droppable.remove();
        this.callbacks.onDrop = undefined;
        this.callbacks.onHoverChange = undefined;
        this.callbacks.onLayeringRotate = undefined;
    };
    Droppable.prototype.setOnDrop = function(callback) {
        var droppable = this;
        this.callbacks.onDrop = function(child) {
            callback.call(droppable, child);
        };
    };
    Droppable.prototype.setOnHoverChange = function(callback) {
        var droppable = this;
        this.callbacks.onHoverChange = function(child, isHovered) {
            callback.call(droppable, child, isHovered);
        };
    };
    Droppable.prototype.setOnLayeringRotate = function(callback) {
        if (callback) {
            var droppable = this;
            this.callbacks.onLayeringRotate = function() {
                callback.call(droppable);
            };
        } else {
            this.callbacks.onLayeringRotate = undefined;
        }
    };
    function ChildDialog($modal, child, options) {
        const self = this;
        this.$modal = $modal;
        this.child = child;
        this.options = options;
        const placeholders = child.getPlaceholders(PLACEHOLDER_TYPE_IMAGE);
        const elementIds = [];
        placeholders.forEach(function(placeholder) {
            const id = parseInt(placeholder.value);
            if (id > 0) {
                elementIds.push(id);
            }
        });
        if (elementIds.length > 0) {
            $.ajax(this.options.urls.MEDIAPOOL_LOAD_ELEMENTS, {
                type: "POST",
                dataType: "json",
                traditional: true,
                contentType: "application/json",
                data: JSON.stringify(elementIds)
            }).done(function(entries) {
                placeholders.forEach(function(placeholder) {
                    const id = parseInt(placeholder.value);
                    if (id > 0) {
                        const entry = entries[id];
                        $("#image-category-id-" + placeholder.id).select2("val", entry.categoryId);
                        self.updateImagePreview(placeholder.id, entry.src, entry.name, entry.title);
                        if (entry.mobileSrc) {
                            const mobilePlaceholderId = self.buildMobilePlaceholder(placeholder.id);
                            self.updateImagePreview(mobilePlaceholderId, entry.mobileSrc, entry.mobileName, entry.mobileTitle);
                            self.changeImageControlsState(mobilePlaceholderId, true);
                            self.changeMobileImageBlockVisibility(mobilePlaceholderId, true);
                        }
                    }
                });
            });
        }
        controlCheckPhChildrenVisibility(child, $modal);
        this.updateImageSrcPreview = _.throttle(this.updateImageSrcPreview, 300);
    }
    function controlCheckPhChildrenVisibility(child, $modal) {
        child.getPlaceholders(PLACEHOLDER_TYPE_CHECK).filter(function(item) {
            return item;
        }).forEach(function(checkPlaceholder) {
            const $childrenContainer = $('<div id="' + checkPlaceholder.id + '-children" class="col-sm-offset-1 col-sm-11" data-show-by-checkbox="#content-' + checkPlaceholder.id + '"></div>');
            $childrenContainer.insertAfter($("#content-" + checkPlaceholder.id).closest(".form-group"));
            checkPlaceholder.options.split(",").forEach(function(phChildId) {
                $childrenContainer.append($(".ph-" + phChildId));
            });
        });
        AGN.Lib.CoreInitializer.run("checkbox-hider", $modal);
    }
    ChildDialog.get = function($e) {
        var dialog = $e.data("agn:child-dialog");
        if (dialog) {
            return dialog;
        }
        return $e.closest(".modal").data("agn:child-dialog");
    };
    ChildDialog.create = function(child, options) {
        var $modal = Modal.createFromTemplate(options, "div-editing-dialog");
        $modal.data("agn:child-dialog", new ChildDialog($modal, child, options));
    };
    ChildDialog.prototype.updateImageSrc = function($src) {
        var placeholderId = $src.data("placeholder-id");
        var src = $.trim($src.val());
        this.updateImageSrcPreview(placeholderId, src);
    };
    ChildDialog.prototype.updateImageSrcPreview = function(placeholderId, src) {
        var $img = $("#preview-" + placeholderId);
        if ($img.attr("src") !== src) {
            $img.attr("src", this.options.resolveAgnImageTags(src) || this.options.noPreviewImageLink);
        }
    };
    ChildDialog.prototype.updateImage = function($file, isMobile) {
        const placeholderId = $file.data("placeholder-id");
        const files = $file.prop("files");
        const $content = $("#content-" + placeholderId);
        if (files && files.length) {
            const file = files[0];
            if (file.type === "image" || file.type.match("image/.*")) {
                const reader = new FileReader();
                const self = this;
                if (isMobile) {
                    const originalPlaceholderId = placeholderId.replace(this.options.mobileSuffix, "");
                    const originalImageName = $("#image-name-" + originalPlaceholderId).text();
                    Helpers.renameFile(file, this.options.mobileImagePrefix + originalImageName);
                } else {
                    const mobilePlaceholderId = this.buildMobilePlaceholder(placeholderId);
                    this.changeMobileImageBlockVisibility(mobilePlaceholderId, true);
                    this.updateImagePreview(mobilePlaceholderId);
                }
                reader.onload = function(e) {
                    self.updateImagePreview(placeholderId, e.target.result, file.name, file.name);
                };
                reader.readAsDataURL(file);
            } else {
                Helpers.clearFormField($file);
                this.updateImagePreview(placeholderId);
            }
        } else {
            this.updateImagePreview(placeholderId);
        }
        $content.val("");
    };
    ChildDialog.prototype.syncImageCategories = function(placeholderId, categoryId) {
        const imageId = $("#content-" + placeholderId).val();
        const placeholdersWithSameImage = this._findPlaceholdersWithImage(imageId);
        placeholdersWithSameImage.forEach(function(ph) {
            const $categorySelect = $("#image-category-id-" + ph.id);
            Select.get($categorySelect).selectValue(categoryId);
        });
    };
    ChildDialog.prototype._findPlaceholdersWithImage = function(imageId) {
        return this.child.getPlaceholders(PLACEHOLDER_TYPE_IMAGE).filter(function(ph) {
            return imageId == $("#content-" + ph.id).val();
        });
    };
    ChildDialog.prototype.updateImagePreview = function(placeholderId, src, name, title) {
        var $img = $("#preview-" + placeholderId);
        var $name = $("#image-name-" + placeholderId);
        if ($img.attr("src") !== src) {
            $img.attr("src", src || this.options.noPreviewImageLink);
        }
        $img.attr("title", title || "");
        $name.text(name || "");
    };
    ChildDialog.prototype.changeMobileImageBlockVisibility = function(placeholderId, show) {
        const $imageContainer = $("#image-block-" + placeholderId);
        if (show) {
            $imageContainer.removeClass("hidden");
        } else {
            $imageContainer.addClass("hidden");
        }
    };
    ChildDialog.prototype.chooseImage = function(placeholderId) {
        var $file = $("#file-" + placeholderId);
        if ($file.val()) {
            $file.trigger("click");
        } else {
            this.showMediapoolDialog(placeholderId);
        }
    };
    ChildDialog.prototype.deleteImage = function(placeholderId, isMobile) {
        this.clearImageData(placeholderId);
        if (!isMobile) {
            const mobilePlaceholderId = this.buildMobilePlaceholder(placeholderId);
            this.clearImageData(mobilePlaceholderId);
            this.changeImageControlsState(mobilePlaceholderId, false);
            this.changeMobileImageBlockVisibility(mobilePlaceholderId, false);
        }
    };
    ChildDialog.prototype.clearImageData = function(placeholderId) {
        var $file = $("#file-" + placeholderId);
        var $name = $("#image-name-" + placeholderId);
        var $content = $("#content-" + placeholderId);
        var $img = $("#preview-" + placeholderId);
        Helpers.clearFormField($file);
        $name.text("");
        $content.val("");
        $img.attr("src", this.options.noPreviewImageLink);
    };
    ChildDialog.prototype.showMediapoolDialog = function(placeholderId) {
        const self = this;
        Confirm.request(this.options.urls.MEDIAPOOL_IMAGE_PICK).done(function(image) {
            const mobilePlaceholderId = self.buildMobilePlaceholder(placeholderId);
            self.loadMobileAlternative(image.id).then(function(imageData) {
                $("#content-" + mobilePlaceholderId).val(imageData.id);
                self.updateImagePreview(mobilePlaceholderId, imageData.src, imageData.name, imageData.title);
                self.changeImageControlsState(mobilePlaceholderId, true);
            }).catch(function() {
                self.updateImagePreview(mobilePlaceholderId);
                self.changeImageControlsState(mobilePlaceholderId, false);
            }).finally(function() {
                Helpers.clearFormField($("#file-" + mobilePlaceholderId));
                self.changeMobileImageBlockVisibility(mobilePlaceholderId, true);
            });
            var categoryId = image.categoryId;
            const placeholdersWithSameImage = self._findPlaceholdersWithImage(image.id);
            if (placeholdersWithSameImage.length > 0) {
                categoryId = $("#image-category-id-" + placeholdersWithSameImage[0].id).val();
            }
            $("#content-" + placeholderId).val(image.id);
            Select.get($("#image-category-id-" + placeholderId)).selectValue(categoryId);
            Helpers.clearFormField($("#file-" + placeholderId));
            self.updateImagePreview(placeholderId, image.src, image.name, image.title);
        });
    };
    ChildDialog.prototype.changeImageControlsState = function(placeholderId, disabled) {
        const $previewImage = $("#preview-" + placeholderId);
        $("#image-delete-button-" + placeholderId).find(".btn").prop("disabled", disabled);
        $("#choose-image-btn-" + placeholderId).prop("disabled", disabled);
        $previewImage.toggleClass("clickable", !disabled);
        $previewImage.attr("data-action", disabled ? "" : "chooseImage");
    };
    ChildDialog.prototype.loadMobileAlternative = function(imageId) {
        return new Promise(function(resolve, reject) {
            $.ajax({
                url: AGN.url("/mediapool/content/images/mobile-alternative/" + imageId + "/load.action"),
                type: "GET",
                success: function(mobileImage) {
                    resolve(mobileImage);
                },
                error: function() {
                    reject();
                },
                statusCode: {
                    404: function() {
                        reject();
                    }
                }
            });
        });
    };
    ChildDialog.prototype.validate = function(form) {
        var areImageCategoriesValid = this.validateImageCategories(form);
        var areImageFormatsValid = this.validateImageFormats(form);
        return areImageCategoriesValid && areImageFormatsValid && this.validateHtml();
    };
    ChildDialog.prototype.validateHtml = function() {
        var htmlPlaceholders = {};
        this.child.getPlaceholders().forEach(function(placeholder) {
            if (placeholder.type !== PLACEHOLDER_TYPE_IMAGE) {
                var content = $("#content-" + placeholder.id).val();
                if ($.trim(content)) {
                    htmlPlaceholders[placeholder.name] = content;
                }
            }
        });
        if (Object.keys(htmlPlaceholders).length <= 0) {
            return true;
        }
        var isValid = false;
        $.ajax({
            type: "POST",
            url: AGN.url("/layoutbuilder/template/" + editor.getTemplateId() + "/validateHtml.action"),
            contentType: "application/json",
            async: false,
            data: JSON.stringify({
                htmlPlaceholders: htmlPlaceholders
            })
        }).done(function(resp) {
            AGN.Lib.JsonMessages(resp.popups, true);
            isValid = !!resp.success;
        });
        return isValid;
    };
    ChildDialog.prototype.validateImageCategories = function(form) {
        var isValid = true;
        this.child.getPlaceholders(PLACEHOLDER_TYPE_IMAGE).forEach(function(placeholder) {
            var id = placeholder.id;
            var categoryId = $("#image-category-id-" + id).val();
            if (categoryId <= 0) {
                var isFile = !!$("#file-" + id).val();
                var content = $("#content-" + id).val();
                if (isFile || parseInt(content) > 0) {
                    isValid = false;
                    form.showFieldError("image-category-id-" + id, t("error.grid.noCategorySelected"));
                }
            }
        });
        return isValid;
    };
    ChildDialog.prototype.validateImageFormats = function(form) {
        var isValid = true;
        function validateImageFileExtension(name) {
            var groups = name.match(/[^.\\/]\.([^.\\/]+)$/);
            if (groups) {
                var extension = groups[1].toUpperCase();
                return extension in {
                    GIF: 1,
                    JPG: 1,
                    JPEG: 1,
                    PNG: 1,
                    SVG: 1,
                    ICO: 1
                };
            }
            return false;
        }
        this.child.getPlaceholders(PLACEHOLDER_TYPE_IMAGE).forEach(function(placeholder) {
            var id = placeholder.id;
            var name = $("#file-" + id).val();
            if (name && !validateImageFileExtension(name)) {
                isValid = false;
                form.showFieldError("content-" + id, t("grid.divchild.format.error"));
            }
        });
        return isValid;
    };
    ChildDialog.prototype.updateImagesCategories = function() {
        var self = this;
        var deferred = $.Deferred();
        var entries = [];
        this.child.getPlaceholders(PLACEHOLDER_TYPE_IMAGE).forEach(function(placeholder) {
            var placeholderId = placeholder.id;
            var imageId = parseInt($("#content-" + placeholderId).val());
            if (imageId > 0) {
                entries.push({
                    imageId: imageId,
                    categoryId: $("#image-category-id-" + placeholderId).val()
                });
            }
        });
        if (entries.length) {
            var categoriesMap = {};
            entries.forEach(function(e) {
                categoriesMap[e.imageId] = e.categoryId;
            });
            $.ajax(self.options.urls.MEDIAPOOL_SET_CATEGORIES, {
                type: "POST",
                dataType: "json",
                contentType: "application/json",
                data: JSON.stringify(categoriesMap)
            }).done(function() {
                deferred.resolve();
            }).fail(function() {
                deferred.reject();
            });
        } else {
            deferred.resolve();
        }
        return deferred.promise();
    };
    ChildDialog.prototype.uploadImages = function(form) {
        const self = this;
        const deferred = $.Deferred();
        const entries = [];
        this.child.getPlaceholders(PLACEHOLDER_TYPE_IMAGE).forEach(function(placeholder) {
            const placeholderId = placeholder.id;
            const mobilePlaceholderId = self.buildMobilePlaceholder(placeholderId);
            const files = $("#file-" + placeholderId).prop("files");
            const mobileFiles = $("#file-" + mobilePlaceholderId).prop("files");
            if (files && files.length) {
                entries.push({
                    placeholderId: placeholderId,
                    image: files[0],
                    categoryId: $("#image-category-id-" + placeholderId).val()
                });
            }
            if (mobileFiles && mobileFiles.length) {
                entries.push({
                    placeholderId: mobilePlaceholderId,
                    image: mobileFiles[0],
                    categoryId: $("#image-category-id-" + placeholderId).val()
                });
            }
        });
        if (entries.length) {
            const data = new FormData();
            entries.forEach(function(e, index) {
                data.append("images[" + index + "].file", e.image);
                data.append("images[" + index + "].fileName", e.image.name);
                data.append("images[" + index + "].title", e.image.name);
                data.append("images[" + index + "].categoryId", e.categoryId);
            });
            $.ajax(self.options.urls.MEDIAPOOL_IMAGE, {
                type: "POST",
                dataType: "json",
                enctype: "multipart/form-data",
                processData: false,
                contentType: false,
                data: data
            }).done(function(resp) {
                AGN.Lib.JsonMessages(resp.popups);
                if (resp.data) {
                    resp.data.forEach(function(imageId, index) {
                        if (imageId > 0) {
                            const placeholderId = entries[index].placeholderId;
                            $("#content-" + placeholderId).val(imageId);
                            Helpers.clearFormField($("#file-" + placeholderId));
                        }
                    });
                }
                if (resp.success === true) {
                    deferred.resolve();
                } else {
                    deferred.reject();
                }
            }).fail(function() {
                deferred.reject();
            });
        } else {
            deferred.resolve();
        }
        return deferred.promise();
    };
    ChildDialog.prototype.buildMobilePlaceholder = function(placeholderId) {
        return placeholderId + this.options.mobileSuffix;
    };
    ChildDialog.prototype.save = function(form) {
        var self = this;
        this.updateCkditorsValues();
        if (this.validate(form)) {
            var $modal = this.$modal;
            var child = this.child;
            var $body = this.$modal.find(".modal-body");
            var $button = $("#child-save-button");
            $body.addClass("ui-modal-loading");
            $body.scrollTop(0);
            $button.prop("disabled", true);
            this.updateImagesCategories(form).then(function() {
                return self.uploadImages(form);
            }).always(function() {
                $body.removeClass("ui-modal-loading");
                $button.prop("disabled", false);
            }).done(function() {
                var contentMap = {};
                var placeholders = child.getPlaceholders();
                $modal.find(".js-wysiwyg").each(function() {
                    var $e = $(this);
                    var id = $e.attr("id");
                    if (CKEDITOR.instances[id]) {
                        CKEDITOR.instances[id].updateElement();
                    }
                    AGN.Lib.Editor.get($e).val($e.val());
                    window.removeEditor(id);
                });
                placeholders.forEach(function(placeholder) {
                    const id = placeholder.id;
                    const $phInput = $("#content-" + id);
                    contentMap[id] = placeholder.type === PLACEHOLDER_TYPE_CHECK ? $phInput.prop("checked") ? "checked" : "" : contentMap[id] = $phInput.val();
                });
                var name = $("#child-title").val();
                var targetId = parseInt($("#target-group-id").val());
                var isTocItem = $("#is-toc-enabled").is(":checked");
                var interestGroup = $("#is-interest-sortable").is(":checked") ? $("#interest-group").val() : "";
                $modal.modal("hide");
                if (child.isToc()) {
                    var includedTocItemsMap = {};
                    $("input.js-is-toc-item").each(function() {
                        var $e = $(this);
                        includedTocItemsMap[$e.data("child-id")] = $e.is(":checked");
                    });
                    editor.saveChild(child, name, targetId, isTocItem, interestGroup, contentMap, includedTocItemsMap);
                } else {
                    editor.saveChild(child, name, targetId, isTocItem, interestGroup, contentMap);
                }
            });
        }
    };
    ChildDialog.prototype.updateCkditorsValues = function() {
        this.$modal.find(".js-wysiwyg").each(function() {
            var ckeditorInstance = CKEDITOR.instances[$(this).attr("id")];
            if (ckeditorInstance) {
                ckeditorInstance.updateElement();
            }
        });
    };
});

AGN.Lib.Controller.new("grid-overview", function() {
    var config;
    this.addDomInitializer("grid-overview", function($scope) {
        config = this.config;
        $scope.all(".card[data-grid-id]").each(function() {
            var $el = $(this);
            var data = config.grids[parseInt($el.data("grid-id"))];
            var d3data = [], imageRatio = 165 / 90, svgWidth = 1e3, svgHeight = svgWidth / imageRatio, columnWidth = data.columnWidth * svgWidth / data.templateWidth, gutterWidth = data.gutter * svgWidth / data.templateWidth, bar;
            if ($el.find("svg").exists()) {
                return;
            }
            $el.find(".js-grid").append('<svg class="grid-preview" viewBox="0 0 ' + svgWidth + " " + svgHeight + '"></svg>');
            _.times(data.columnNum, function(col) {
                d3data.push({
                    type: "gutter",
                    width: gutterWidth / 2
                });
                d3data.push({
                    type: "col",
                    width: columnWidth
                });
                d3data.push({
                    type: "gutter",
                    width: gutterWidth / 2
                });
            });
            _.reduce(d3data, function(sum, span) {
                span.xPos = sum;
                return sum + span.width;
            }, 0);
            bar = d3.select($el.find("svg")[0]).selectAll("g").data(d3data).enter().append("g").attr("transform", function(span) {
                return "translate(" + span.xPos + ",0)";
            });
            bar.append("rect").attr("class", function(d) {
                return "grid-preview-" + d.type;
            }).attr("width", function(d) {
                return d.width;
            }).attr("height", svgHeight);
        });
    });
    this.addAction({
        click: "back"
    }, function() {
        history.back();
    });
    this.addAction({
        click: "pick"
    }, function() {
        var grid = config.grids[this.el.data("grid-id")];
        if (grid) {
            $.ajax(grid.viewLink, {
                method: "POST",
                data: {
                    newTemplateName: config.newTemplateName
                }
            }).done(function(resp) {
                AGN.Lib.Page.render(resp);
            });
        }
    });
    this.addAction({
        submission: "createNewGrid"
    }, function() {
        var $form = this.el;
        var form = AGN.Lib.Form.get($form);
        var $newGridName = $form.find("#newGridName");
        $.ajax(config.urls.CHECK_NAME, {
            type: "GET",
            data: {
                name: $newGridName.val()
            }
        }).done(function(data) {
            if (data.used) {
                form.showFieldError("newGridName", t("fields.name.errors.name_in_use"));
            } else {
                form.submit("static");
            }
        });
    });
});

AGN.Lib.Controller.new("grid-template", function() {
    var templateValidator;
    var formWrapper;
    var previewUpdateService = new PreviewUpdateService();
    var Storage = AGN.Lib.Storage;
    var templateId;
    var previewWidths;
    var previewMediaQueries;
    this.addDomInitializer("grid-template", function() {
        var config = this.config;
        formWrapper = this.el;
        templateValidator = new GridTemplateValidator(formWrapper, config);
    });
    this.addDomInitializer("grid-template-css", function() {
        templateId = this.config.templateId;
        previewWidths = this.config.previewWidths;
        previewMediaQueries = this.config.previewMediaQueries;
        const $previewSizes = $('[name="previewSize"]');
        Storage.restoreChosenFields($previewSizes);
        if ($previewSizes.is(":checked") === false) {
            $previewSizes.filter("[value=1]").prop("checked", true);
        }
        refreshPreview();
    });
    function refreshPreview() {
        const $previewWrapper = $(".template-preview-wrapper");
        $previewWrapper.empty();
        var $previewForm = $("#layoutPreviewForm");
        var previewSize = parseInt($("input[name=previewSize]:checked").val());
        var previewWidth = previewWidths[previewSize] + 2;
        $previewWrapper.append('<div>           <div id="layout-preview-container" class="center-block">               <iframe name="layoutPreviewFrame" id="layoutPreviewFrame"                     class="mailing-preview-frame js-simple-iframe" border="0"                     data-max-width="' + previewWidth + '" data-media-query="' + previewMediaQueries[previewSize] + '"                     style="width:' + previewWidth + 'px;">                   Your Browser does not support IFRAMEs, please update!               </iframe>           </div>       </div>');
        AGN.Lib.CoreInitializer.run("iframe");
        setPreviewSizeToForm($previewForm, previewSize);
        $previewForm.submit();
    }
    function setCssToForm() {
        $("#layoutPreviewForm").find('input[name="css"]').val($("#cssContents").val());
    }
    this.addAction({
        click: "update-css-preview"
    }, function() {
        Storage.saveChosenFields($("input[name=previewSize]:checked"));
        setCssToForm();
        refreshPreview();
    });
    function setPreviewSizeToForm($form, previewSize) {
        const $formPreviewSize = $form.find('input[name="previewSize"]');
        if ($formPreviewSize.length > 0) {
            $formPreviewSize.remove();
        }
        $form.append('<input type="hidden" name="previewSize" value="' + previewSize + '" />');
    }
    this.addAction({
        submission: "grid-template-validation"
    }, function() {
        templateValidator.validateTemplateName(formWrapper.find("#newTemplateName"));
    });
    this.addAction({
        click: "back"
    }, function() {
        history.back();
    });
    this.addAction({
        click: "delete"
    }, function() {
        var self = this;
        var el = self.el;
        var address = "";
        if (el.prop("tagName") == "A") {
            address = el.prop("href");
        } else {
            address = el.data("url");
        }
        var jqxhr = $.get(address);
        jqxhr.done(function(resp) {
            var $resp = $(resp), $modal;
            $modal = $resp.filter(".modal").add($resp.find(".modal"));
            if ($modal.length != 1) {
                AGN.Lib.Page.render(resp, address);
                return;
            }
            AGN.Lib.Confirm.create(resp).done(function(resp) {
                AGN.Lib.Page.render(resp, address);
            });
        });
        self.event.preventDefault();
        return false;
    });
    function GridTemplateValidator(formWrapper, config) {
        this.templateNameValidationUrl = config.templateNameValidationUrl;
        this.form = AGN.Lib.Form.get(formWrapper);
    }
    GridTemplateValidator.prototype.validateTemplateName = function(templateNameInput) {
        var value = templateNameInput.val();
        var form = this.form;
        var url = this.templateNameValidationUrl;
        if (value == "") {
            form.showFieldError("newTemplateName", t("fields.required.errors.missing"));
        } else {
            $.ajax({
                type: "GET",
                url: url,
                data: {
                    newTemplateName: value
                }
            }).done(function(data) {
                if (data.newTemplateName == false) {
                    form.showFieldError("templateName", t("fields.name.errors.name_in_use"));
                } else {
                    form.submit("static");
                }
            });
        }
    };
    this.addAction({
        click: "update-preview"
    }, function() {
        var element = this.el;
        previewUpdateService.updateInputValue(element.data("target-form"), element.data("content-type"));
    });
    function PreviewUpdateService() {
        this.contentTypes = {
            css: {
                inputSelector: 'input[name="css"]',
                contentId: "#cssContents"
            },
            outerHtml: {
                inputSelector: 'input[name="outerHtml"]',
                contentId: "#templateOuterHTML"
            },
            styles: {
                inputSelector: 'input[name^="styles["]',
                getContentSelector: function(name) {
                    return 'input[name="' + name + '"]';
                }
            }
        };
    }
    PreviewUpdateService.updateFields = function(inputSelector, fn, form) {
        var contentForm = $("form").not("#" + form.attr("id"));
        _.each(contentForm.find(inputSelector), function(input) {
            var $input = $(input);
            var content = $input.val();
            form.find(fn($input.attr("name"))).val(content);
        });
    };
    PreviewUpdateService.updateField = function(inputSelector, content, form) {
        form.find(inputSelector).val(content);
    };
    PreviewUpdateService.prototype.updateInputValue = function(targetFormId, contentType) {
        var typeConfig = this.contentTypes[contentType];
        var previewForm = $(targetFormId);
        if (contentType == "styles" && typeConfig && previewForm) {
            PreviewUpdateService.updateFields(typeConfig.inputSelector, typeConfig.getContentSelector, previewForm);
        } else if (typeConfig && previewForm) {
            var content = $(typeConfig.contentId).val();
            PreviewUpdateService.updateField(typeConfig.inputSelector, content, previewForm);
        }
        previewForm.submit();
    };
});

AGN.Lib.Controller.new("image-editor", function() {
    var Confirm = AGN.Lib.Confirm, Template = AGN.Lib.Template;
    var x, y;
    var selectedWidth = 0, selectedHeight = 0;
    var isBlocked = false;
    var isEnableCrop = false;
    function calculateCropData(jCropData) {
        x = jCropData.x;
        y = jCropData.y;
        selectedWidth = jCropData.w;
        selectedHeight = jCropData.h;
    }
    this.addDomInitializer("img-editor-init", function() {
        isBlocked = false;
        isEnableCrop = false;
        $("#editor-result").prop("disabled", true);
    });
    this.addAction({
        click: "editCategory"
    }, function() {
        Confirm.create(Template.text("modal-element-category-select", {
            categoryId: $("#category-id").val()
        })).done(function(resp) {
            if (resp && resp.categoryId) {
                $("#category-id").val(resp.categoryId);
            }
        });
    });
    this.addAction({
        click: "cropImage"
    }, function() {
        getLastImageState();
        if (isEnableCrop) {
            destroyJcrop();
            updateOriginalImage();
            isEnableCrop = false;
        } else {
            $("#editor-canvas").Jcrop({
                onChange: calculateCropData,
                onSelect: calculateCropData,
                bgOpacity: 1
            });
            $("#editor-crop-btn").addClass("btn-primary");
            isEnableCrop = true;
        }
    });
    this.addAction({
        click: "saveCrop"
    }, function() {
        getLastImageState();
        var canvas = document.getElementById("editor-canvas");
        var context = canvas.getContext("2d");
        var imageObj = new Image();
        imageObj.src = $("#editor-img").attr("src");
        if (selectedWidth > 1 && selectedHeight > 1) {
            imageObj.onload = function() {
                canvas.width = selectedWidth;
                canvas.height = selectedHeight;
                context.save();
                context.drawImage(imageObj, x, y, selectedWidth, selectedHeight, 0, 0, selectedWidth, selectedHeight);
                context.restore();
                var contentType = $("#editor-img").data("content-type");
                var newSrc = canvas.toDataURL(contentType);
                $("#editor-img").attr("src", newSrc);
                $("#editor-canvas").css("width", selectedWidth);
                $("#editor-canvas").css("height", selectedHeight);
                $("#l-editor-img-width").attr("value", selectedWidth);
                $("#l-editor-img-height").attr("value", selectedHeight);
                updateOriginalImage();
                destroyJcrop();
            };
        }
    });
    this.addAction({
        click: "rotateImage"
    }, function() {
        destroyJcrop();
        getLastImageState();
        var canvas = document.getElementById("editor-canvas");
        var context = canvas.getContext("2d");
        var contentType = $("#editor-img").data("content-type");
        var newSrc = canvas.toDataURL(contentType);
        var imageObj = new Image();
        imageObj.src = newSrc;
        $("#editor-img").attr("src", newSrc);
        imageObj.onload = function() {
            var canvasWidth = canvas.width;
            var canvasHeight = canvas.height;
            canvas.width = canvasHeight;
            canvas.height = canvasWidth;
            canvasWidth = canvas.width;
            canvasHeight = canvas.height;
            context.save();
            context.translate(canvasWidth, canvasHeight / canvasWidth);
            context.rotate(Math.PI / 2);
            context.drawImage(imageObj, 0, 0);
            context.restore();
            updateOriginalImage();
        };
    });
    this.addAction({
        input: "changeSize"
    }, function() {
        destroyJcrop();
        var canvas = document.getElementById("editor-canvas");
        var context = canvas.getContext("2d");
        var imageObj = new Image();
        imageObj.src = $("#editor-img").attr("src");
        imageObj.onload = function() {
            var newImgWidth = $("#l-editor-img-width").val();
            var newImgHeight = $("#l-editor-img-height").val();
            var oldWidth = imageObj.width;
            var oldHeight = imageObj.height;
            if (isBlocked) {
                if ($("#l-editor-img-width").is(":focus")) {
                    var proportion = newImgWidth / oldWidth;
                    newImgHeight = Math.round(proportion * oldHeight);
                    $("#l-editor-img-height").attr("value", newImgHeight);
                } else if ($("#l-editor-img-height").is(":focus")) {
                    var proportion = newImgHeight / oldHeight;
                    newImgWidth = Math.round(proportion * oldWidth);
                    $("#l-editor-img-width").attr("value", newImgWidth);
                }
            }
            canvas.width = newImgWidth;
            canvas.height = newImgHeight;
            context.save();
            context.drawImage(imageObj, 0, 0, newImgWidth, newImgHeight);
            context.restore();
            updateOriginalImage();
        };
    });
    this.addAction({
        input: "pcChangeSize"
    }, function() {
        destroyJcrop();
        var canvas = document.getElementById("editor-canvas");
        var context = canvas.getContext("2d");
        var imageObj = new Image();
        imageObj.src = $("#editor-img").attr("src");
        imageObj.onload = function() {
            var proportion = $("#l-editor-img-percent").val();
            var oldWidth = imageObj.width;
            var oldHeight = imageObj.height;
            var newImgWidth = Math.round(oldWidth * (proportion / 100));
            var newImgHeight = Math.round(oldHeight * (proportion / 100));
            $("#l-editor-img-height").attr("value", newImgHeight);
            $("#l-editor-img-width").attr("value", newImgWidth);
            canvas.width = newImgWidth;
            canvas.height = newImgHeight;
            context.save();
            context.drawImage(imageObj, 0, 0, newImgWidth, newImgHeight);
            context.restore();
            updateOriginalImage();
        };
    });
    this.addAction({
        click: "blockSizes"
    }, function() {
        if (isBlocked) {
            isBlocked = false;
            $("#editor-lock-btn").removeClass("btn-primary");
        } else {
            isBlocked = true;
            $("#editor-lock-btn").addClass("btn-primary");
        }
    });
    function getLastImageState() {
        var canvas = document.getElementById("editor-canvas");
        var contentType = $("#editor-img").data("content-type");
        var newSrc = canvas.toDataURL(contentType);
        $("#editor-img").attr("src", newSrc);
    }
    function updateOriginalImage() {
        var canvas = document.getElementById("editor-canvas");
        var contentType = $("#editor-img").data("content-type");
        var newSrc = canvas.toDataURL(contentType);
        var $result = $("#editor-result");
        var separatorPosition = newSrc.indexOf(",");
        if (separatorPosition >= 0) {
            newSrc = newSrc.substring(separatorPosition + 1);
        }
        if ($result.val() != newSrc) {
            $result.val(newSrc);
            $result.prop("disabled", false);
        }
        var newWidthOfEditor = canvas.width + $("#l-img-editor-tools").width() + 10;
        $("#l-img-editor").css("min-width", newWidthOfEditor);
    }
    function destroyJcrop() {
        var JcropAPI = $("#editor-canvas").data("Jcrop");
        if (typeof JcropAPI != "undefined") {
            $("#editor-canvas").appendTo("#canvas-editor-area");
            $("#editor-canvas").removeAttr("style");
            JcropAPI.destroy();
        }
        $("#editor-crop-btn").removeClass("btn-primary");
        isEnableCrop = false;
        selectedWidth = 0;
        selectedHeight = 0;
    }
});

AGN.Lib.Controller.new("import-profile-mappings", function() {
    const DONT_IMPORT_COL_OPTION = "do-not-import-column";
    const Template = AGN.Lib.Template;
    const Form = AGN.Lib.Form;
    const CoreInitializer = AGN.Lib.CoreInitializer;
    var config;
    var $columnMappingsTable;
    var form;
    var columnMappingRowTemplate;
    var usedDbColumns = [];
    var usedNewMappingColName;
    var $uploadContainer;
    var $contentContainer;
    this.addDomInitializer("import-profile-mappings", function() {
        config = this.config;
        $uploadContainer = $("#upload-file-container");
        $contentContainer = $("#content-container");
        renderMappings(config.columnMappings);
        form = Form.get(this.el);
        form.initFields();
    });
    function renderMappings(mappings) {
        $columnMappingsTable = $("#columnMappings tbody");
        $columnMappingsTable.html("");
        columnMappingRowTemplate = Template.prepare("column-mapping-table-row");
        for (var colIndex = 0; colIndex < mappings.length; colIndex++) {
            const mapping = mappings[colIndex];
            appendRowToColumnMappingTable(colIndex, mapping.id, mapping.fileColumn, mapping.databaseColumn, mapping.mandatory, mapping.encrypted, mapping.defaultValue);
        }
        renderNewMappingRow();
        removeUsedOptionsFromDbColumnsSelects();
        usedDbColumns = findUsedDbColumns();
    }
    function appendRowToColumnMappingTable(index, id, fileColumn, databaseColumn, mandatory, encrypted, defaultValue) {
        const $rowTemplate = columnMappingRowTemplate({
            index: index,
            id: id,
            fileColumn: fileColumn,
            databaseColumn: databaseColumn,
            mandatory: mandatory,
            encrypted: encrypted,
            defaultValue: defaultValue
        });
        $columnMappingsTable.append($rowTemplate);
        const $dbColumn = $('[data-mapping-row="' + index + '"]').find("[data-mapping-db-column]");
        CoreInitializer.run("select", $dbColumn);
    }
    this.addAction({
        click: "upload"
    }, function() {
        const form = Form.get(this.el);
        const file = $("#uploadFile").prop("files")[0];
        $.ajax(config.urls.UPLOAD, {
            type: "POST",
            dataType: "json",
            enctype: "multipart/form-data",
            processData: false,
            contentType: false,
            data: form.data()
        }).done(function(resp) {
            if (resp.success === true) {
                renderMappings(getMappingsForRender(resp.data));
                const $uploadedBlock = Template.dom("uploaded-file-selected", {
                    fileName: file.name
                });
                $uploadContainer.hide();
                $uploadedBlock.insertAfter($uploadContainer);
                $contentContainer.removeClass("hidden");
            } else {
                AGN.Lib.JsonMessages(resp.popups);
            }
        });
    });
    function getMappingsForRender(uploadedMappings) {
        const tableMappings = collectMappingsDataFromTable(false);
        const nonDataFileColumns = tableMappings.filter(function(mapping) {
            return !mapping.fileColumn;
        });
        const fileColumnMappings = [];
        for (var i = 0; i < uploadedMappings.length; i++) {
            const newMapping = uploadedMappings[i];
            const existingMappingIndex = tableMappings.findIndex(function(el) {
                return el.fileColumn === newMapping.fileColumn;
            });
            if (existingMappingIndex === -1) {
                fileColumnMappings.push(newMapping);
            } else {
                fileColumnMappings.push(tableMappings[existingMappingIndex]);
            }
        }
        return [].concat(fileColumnMappings, nonDataFileColumns);
    }
    this.addAction({
        click: "delete-file"
    }, function() {
        const jqxhr = $.post(AGN.url("/recipient/import/file/delete.action"));
        jqxhr.done(function() {
            $("#uploaded-file-container").remove();
            $("#uploadFile").val("");
            $uploadContainer.show();
        });
    });
    this.addAction({
        submission: "save-mappings"
    }, function() {
        const form = Form.get(this.el);
        _.each(collectMappingsDataFromTable(true), function(mapping, index) {
            form.setValueOnce("columnsMappings[" + index + "].id", mapping.id);
            form.setValueOnce("columnsMappings[" + index + "].fileColumn", mapping.fileColumn);
            form.setValueOnce("columnsMappings[" + index + "].databaseColumn", mapping.databaseColumn);
            form.setValueOnce("columnsMappings[" + index + "].mandatory", mapping.mandatory);
            form.setValueOnce("columnsMappings[" + index + "].encrypted", mapping.encrypted);
            form.setValueOnce("columnsMappings[" + index + "].defaultValue", mapping.defaultValue);
        });
        form.submit();
    });
    function collectMappingsDataFromTable(includingNewMapping) {
        if (!$columnMappingsTable || !$columnMappingsTable.length) {
            return [];
        }
        const mappings = _.map($columnMappingsTable.find("[data-mapping-row]"), function(row) {
            const $row = $(row);
            return {
                id: getMappingValueInRowByCol($row, "id"),
                fileColumn: getMappingValueInRowByCol($row, "fileColumn"),
                databaseColumn: getMappingValueInRowByCol($row, "db-column"),
                mandatory: getMappingValueInRowByCol($row, "mandatory"),
                encrypted: getMappingValueInRowByCol($row, "encrypted"),
                defaultValue: getMappingValueInRowByCol($row, "defaultValue")
            };
        });
        if (includingNewMapping) {
            const newMapping = findNewMapping();
            if (newMapping.databaseColumn && newMapping.databaseColumn !== DONT_IMPORT_COL_OPTION) {
                mappings.push(newMapping);
            }
        }
        return mappings;
    }
    function getMappingValueInRowByCol($row, col) {
        const $input = $row.find("[data-mapping-" + col + "]");
        if ($input.is(":checkbox")) {
            return $input.is(":checked");
        }
        return $input.val();
    }
    this.addAction({
        change: "change-new-col-name"
    }, function() {
        if (usedNewMappingColName && usedNewMappingColName !== DONT_IMPORT_COL_OPTION) {
            addOptionToDbColumnsSelects(usedNewMappingColName);
        }
        const colName = this.el.find(":selected").val();
        usedNewMappingColName = colName;
        removeNewOptionFromDbColumnsSelects(colName);
        updateNewMappingDefValInput(colName);
    });
    this.addAction({
        change: "change-exist-col-name"
    }, function() {
        const previousSelectedColumn = findPreviousSelectedDbColumn();
        if (previousSelectedColumn) {
            addOptionToDbColumnsSelects(previousSelectedColumn);
            removeNewOptionFromDbColumnsSelects(this.el.val());
            usedDbColumns = findUsedDbColumns();
        }
    });
    this.addAction({
        click: "delete-mapping"
    }, function() {
        deleteMapping(this.el);
    });
    this.addAction({
        click: "bulk-delete"
    }, function() {
        _.each($(".column-checkbox:checkbox:checked"), function(el) {
            deleteMapping($(el));
        });
    });
    function deleteMapping($el) {
        const $mappingRow = $el.closest("tr");
        const newFreeOption = getMappingValueInRowByCol($mappingRow, "db-column");
        $mappingRow.remove();
        if (newFreeOption && newFreeOption !== DONT_IMPORT_COL_OPTION) {
            addOptionToDbColumnsSelects(newFreeOption);
        }
    }
    this.addAction({
        click: "add-mapping"
    }, function() {
        if (!form.valid({})) {
            form.handleErrors();
            return;
        }
        form.cleanErrors();
        const newMapping = findNewMapping();
        if (isDuplicatedMapping(newMapping)) {
            AGN.Lib.Messages(t("defaults.error"), t("export.columnMapping.error.duplicate"), "alert");
            return;
        }
        this.el.closest("tr").remove();
        const colIndex = findLastMappingIndex() + 1;
        appendRowToColumnMappingTable(colIndex, newMapping.id, newMapping.fileColumn, newMapping.databaseColumn, newMapping.mandatory, newMapping.encrypted, newMapping.defaultValue);
        renderNewMappingRow();
        removeUsedOptionsFromDbColumnsSelects();
    });
    function isDuplicatedMapping(mappingToCheck) {
        if (mappingToCheck.databaseColumn === DONT_IMPORT_COL_OPTION) {
            return false;
        }
        const existingMappings = collectMappingsDataFromTable(false);
        return existingMappings.some(function(mapping) {
            return mapping.fileColumn === mappingToCheck.databaseColumn || mapping.databaseColumn === mappingToCheck.databaseColumn;
        });
    }
    function findNewMapping() {
        const $encryptedInput = $("#encrypted-new");
        const isEncrypted = $encryptedInput ? $encryptedInput.is(":checked") : false;
        return {
            id: 0,
            fileColumn: "",
            databaseColumn: $("#database-column-new").val(),
            mandatory: $("#mandatory-new").is(":checked"),
            encrypted: isEncrypted,
            defaultValue: prepareDefaultValueForNewMapping()
        };
    }
    function prepareDefaultValueForNewMapping() {
        if ($("[data-action=change-date-input]").is(":checked")) {
            const daysCount = parseInt($("#daysCount").val() || 0);
            const additionalDays = daysCount === 0 ? "" : daysCount > 0 ? "+" + daysCount : daysCount;
            return "CURRENT_TIMESTAMP" + additionalDays;
        }
        return $("[name=default-value-new]").val();
    }
    function findLastMappingIndex() {
        return $("[data-mapping-row]").last().data("mapping-row");
    }
    this.addAction({
        change: "change-date-input"
    }, function() {
        $("#dateInput").toggle(!this.el.is(":checked"));
        $("#daysInput").toggle(this.el.is(":checked"));
        handleIntegerInput($("#daysCount"));
    });
    function handleIntegerInput($input) {
        $input.on("change.offset keyup.offset", function(e) {
            const value = $input.val();
            if (value) {
                const offset = parseInt(value);
                if (!isNaN(offset)) {
                    const newValue = (offset < 0 ? "" : "+") + offset;
                    if (newValue != value) {
                        $input.val(newValue);
                    }
                } else {
                    $input.val(value.replace(/[^\d+-]/g, ""));
                }
            } else if (e.type === "change") {
                $input.val("+0");
            }
        });
    }
    function removeUsedOptionsFromDbColumnsSelects() {
        _.each($columnMappingsTable.find("[data-mapping-db-column]"), function(colNameSelect) {
            removeNewOptionFromDbColumnsSelects($(colNameSelect).val());
        });
    }
    function removeNewOptionFromDbColumnsSelects(option) {
        _.each($columnMappingsTable.find("[data-mapping-db-column]"), function(colNameSelect) {
            removeOptionFromDbColumnSelect($(colNameSelect), option);
        });
        removeOptionFromDbColumnSelect($("#database-column-new"), option);
    }
    function addOptionToDbColumnsSelects(option) {
        _.each($columnMappingsTable.find("[data-mapping-db-column]"), function(select) {
            addNewSelectOption($(select), option);
        });
        addNewSelectOption($("#database-column-new"), option);
    }
    function removeOptionFromDbColumnSelect($select, option) {
        if ($select.val() !== option && option !== DONT_IMPORT_COL_OPTION) {
            $select.find('[value="' + option + '"]').remove();
        }
    }
    function addNewSelectOption($select, option) {
        if ($select.val() !== option) {
            $select.append($("<option>", {
                value: option,
                text: option
            }));
        }
    }
    function performElemPostDraw($inputCell, type) {
        if (type === "date") {
            AGN.runAll($inputCell);
        } else if (type === "datetime") {
            form.initFields();
        }
    }
    function getColumnDefValInputType(colName) {
        const type = config.columns[colName].dataType.toLowerCase();
        switch (type) {
          case "date":
          case "datetime":
            return type;

          default:
            return "text";
        }
    }
    function updateNewMappingDefValInput(colName) {
        const type = getColumnDefValInputType(colName);
        const $currentDefValInput = $("[name=default-value-new]");
        const val = $currentDefValInput.val();
        const $inputCell = $currentDefValInput.closest("td");
        if ($inputCell.children().first().data("type") !== type) {
            $inputCell.empty();
            $inputCell.append(getDefValInputByType(type, val));
            performElemPostDraw($inputCell, type);
        }
    }
    function getDefValInputByType(type, val) {
        switch (type) {
          case "date":
          case "datetime":
            return Template.text("date-def-val-input", {
                withTime: type === "datetime",
                val: val
            });

          default:
            return Template.text("text-def-val-input");
        }
    }
    function renderNewMappingRow() {
        $columnMappingsTable.append(Template.text("new-mapping-row"));
        CoreInitializer.run("select", $("#database-column-new"));
    }
    function findPreviousSelectedDbColumn() {
        const currentUsedDbColumns = findUsedDbColumns();
        return usedDbColumns.filter(function(colName) {
            return currentUsedDbColumns.indexOf(colName) < 0;
        })[0];
    }
    function findUsedDbColumns() {
        const colNames = [];
        _.each($columnMappingsTable.find("[data-mapping-db-column]"), function(colNameSelect) {
            colNames.push($(colNameSelect).val());
        });
        return colNames;
    }
});

AGN.Lib.Controller.new("import-profile", function() {
    var genderMappingRowTemplate;
    var $genderMappingTable;
    var isGenderSectionFocused = false;
    var isAllowedToShowMailinglists;
    this.addAction({
        click: "save"
    }, function() {
        if (isTextGendersUnique(getGenderTextValues(getGenderTableLastRow()))) {
            const form = AGN.Lib.Form.get($("#importProfileForm"));
            setGenderMappingsToForm(form);
            form.setValue("isGenderSectionFocused", isGenderSectionFocused);
            form.submit();
        }
    });
    this.addDomInitializer("import-profile-view", function() {
        isAllowedToShowMailinglists = this.config.isAllowedToShowMailinglists;
        $("#importProfileForm").on("click change", function(event) {
            const $el = $(event.target);
            isGenderSectionFocused = ($el.is("input") || $el.is("select") || $el.is("button") || $el.parent().is("button")) && $el.parents("#recipient-import-gender-settings").length > 0;
        });
        initGenderMappingTable(sortMappingsByValue(this.config.genderMappings));
        processMailingListsTileDisplaying();
    });
    this.addAction({
        change: "new-recipients-action-select"
    }, function() {
        processMailingListsTileDisplaying();
    });
    this.addAction({
        click: "add-gender-mapping",
        enterdown: "gender-enterdown"
    }, function() {
        this.event.preventDefault();
        if (isLastRowCanBeAddedToTable()) {
            replaceNewButtonWithDeleteButton();
            appendRowToGenderMappingTable("", "");
            getGenderTableLastRow().find("[data-gender-text-value]").focus();
        }
    });
    this.addAction({
        click: "delete-gender-mapping"
    }, function() {
        this.el.closest("tr").remove();
    });
    const setMailingListSelectionEnabled = function(isEnabled) {
        $("#mailinglists").toggleClass("hidden", !isEnabled);
        $("#mailinglists-to-show").toggleClass("hidden", isEnabled);
    };
    this.addDomInitializer("allMailinglists-checkbox", function() {
        processMailingListsTileDisplaying();
    });
    this.addAction({
        change: "mode-select-change"
    }, function() {
        const visible = $("#all-mailinglists-wrapper").is(":visible");
        if (!visible && $("#allMalinglistsCheckbox").is(":checked")) {
            $("#allMalinglistsCheckbox").click();
        }
    });
    this.addAction({
        change: "allMailinglists-checkbox"
    }, function() {
        setSeparateMailinglistChecboxes($(this.el).is(":checked"));
    });
    const setSeparateMailinglistChecboxes = function(disabled) {
        $('#mailinglists [type="checkbox"]').prop("disabled", disabled);
    };
    function processAllMailinglistsToggle(newRecipientsActionSelected) {
        const $allMalinglistsCheckbox = $("#allMalinglistsCheckbox");
        if (newRecipientsActionSelected) {
            $allMalinglistsCheckbox.attr("checked", false);
            $("#all-mailinglists-wrapper").hide();
        } else {
            $("#all-mailinglists-wrapper").show();
        }
        $allMalinglistsCheckbox.attr("disabled", newRecipientsActionSelected || !isAllowedToShowMailinglists);
    }
    function processMailinglistsCheckboxes(newRecipientsActionSelected) {
        setMailingListSelectionEnabled(!newRecipientsActionSelected);
        setSeparateMailinglistChecboxes($("#allMalinglistsCheckbox").is(":checked") || !isAllowedToShowMailinglists || newRecipientsActionSelected);
    }
    function initGenderMappingTable(mappings) {
        $genderMappingTable = $("#recipient-import-gender-settings tbody");
        genderMappingRowTemplate = AGN.Lib.Template.prepare("gender-settings-table-row");
        _.each(mappings, function(mapping) {
            appendRowToGenderMappingTable(mapping[0], mapping[1]);
        });
        appendRowToGenderMappingTable("", "");
    }
    function getGenderTextValuesStr($row) {
        const $el = $row.find("[data-gender-text-value]");
        if ($el.is("input")) {
            return $el.val().trim();
        } else {
            return $el.text().trim();
        }
    }
    function getGenderTextValues($row) {
        const textValuesStr = getGenderTextValuesStr($row);
        const result = textValuesStr.length ? textValuesStr.split(",") : [];
        return new Set(_.without(_.map(result, _.trim), ""));
    }
    function getGenderIntValue($row) {
        const $el = $row.find("[data-gender-int-value]");
        return $el.is("select") ? $el.val() : $el.text()[0];
    }
    function appendRowToGenderMappingTable(textValues, intValue) {
        if (intValue === 0 || intValue) {
            intValue += " (" + t("import.gender.short." + intValue) + ")";
        } else {
            intValue = "";
        }
        $genderMappingTable.append(genderMappingRowTemplate({
            intValue: intValue,
            textValues: textValues
        }));
        AGN.Lib.CoreInitializer.run("select", $genderMappingTable.find("[data-gender-int-value]:last-child"));
    }
    function replaceNewButtonWithDeleteButton() {
        const newBtn = $genderMappingTable.find('[data-action="add-gender-mapping"]');
        newBtn.after("<a href='#' class='btn btn-regular btn-alert' data-action='delete-gender-mapping'>" + "<i class='icon icon-trash-o'></i></a>");
        newBtn.remove();
    }
    function isLastRowCanBeAddedToTable() {
        const textValues = getGenderTextValues(getGenderTableLastRow());
        if (textValues.size < 1) {
            AGN.Lib.Messages(t("defaults.error"), t("import.gender.error.empty"), "alert");
            return false;
        }
        return isTextGendersUnique(textValues);
    }
    function isTextGendersUnique(genders) {
        const rows = $genderMappingTable.find("[data-gender-settings-row]").toArray();
        for (var i = 0; i < rows.length - 1; i++) {
            if (_.intersection(Array.from(genders), Array.from(getGenderTextValues($(rows[i])))).length) {
                AGN.Lib.Messages(t("defaults.error"), t("import.gender.error.duplicate"), "alert");
                return false;
            }
        }
        return true;
    }
    function getGenderTableLastRow() {
        return $genderMappingTable.find("[data-gender-settings-row]:last-child");
    }
    function collectGenderMappings() {
        const mappings = {};
        _.each($genderMappingTable.find("[data-gender-settings-row]"), function(row) {
            const $row = $(row);
            const textValuesStr = getGenderTextValuesStr($row);
            const intValue = getGenderIntValue($row);
            if (textValuesStr.length) {
                mappings[intValue] = !mappings.hasOwnProperty(intValue) ? textValuesStr : mappings[intValue] + ", " + textValuesStr;
            }
        });
        return mappings;
    }
    function setGenderMappingsToForm(form) {
        _.each(collectGenderMappings(), function(textValuesStr, intValue) {
            form.setValue("genderMapping[" + intValue + "]", textValuesStr);
        });
    }
    function sortMappingsByValue(mappings) {
        if (!mappings) {
            mappings = "";
        }
        const result = [];
        Object.keys(mappings).forEach(function(key) {
            result.push([ key, mappings[key] ]);
        });
        result.sort(function(a, b) {
            return a[1] - b[1];
        });
        return result;
    }
    function processMailingListsTileDisplaying() {
        const $newRecipientsActionSelect = $("#import_actionnewrecipients");
        const newRecipientsActionSelected = $newRecipientsActionSelect.length && $newRecipientsActionSelect.val() > 0;
        processAllMailinglistsToggle(newRecipientsActionSelected);
        processMailinglistsCheckboxes(newRecipientsActionSelected);
    }
});

AGN.Lib.Controller.new("logon-password-change", function() {
    this.addAction({
        click: "showPasswordChangeForm"
    }, function() {
        $("#suggestion-view").addClass("hidden");
        $("#submission-view").removeClass("hidden");
    });
});

AGN.Lib.Controller.new("mailing-upload-attachment", function() {
    this.addDomInitializer("mailing-upload-attachment", function() {
        resetFields();
    });
    this.addAction({
        change: "use-pdf"
    }, function() {
        updateFields($(this.elem).prop("checked"));
    });
    this.addAction({
        change: "change-attachment-file"
    }, function() {
        updateFilename(false);
    });
    this.addAction({
        change: "change-upload-file"
    }, function() {
        updateFilename(true);
    });
    function resetFields() {
        $("#attachment").val("");
        $("#attachmentName").val("");
        $("#backgroundAttachment").val("");
        $("#targetId").select2("val", 0);
        AGN.Lib.Select.get($("#type")).selectFirstValue();
    }
    function updateFilename(useUploadActivated) {
        var attachmentName = "";
        if (useUploadActivated) {
            attachmentName = $("#pdfUploadId").select2("val");
        } else {
            var files = $("#attachment").prop("files");
            if (files && files.length) {
                attachmentName = files[0].name;
            }
        }
        $("#attachmentName").val(attachmentName);
    }
    function updateFields(useUploadActivated) {
        resetFields();
        updateFilename(useUploadActivated);
    }
});

AGN.Lib.Controller.new("mailing-content-controller", function() {
    const Confirm = AGN.Lib.Confirm;
    const Template = AGN.Lib.Template;
    const Storage = AGN.Lib.Storage;
    var mailingContent;
    var preparedTableEntryTemplate;
    var isMailingExclusiveLockingAcquired;
    var isEditableMailing;
    var isContentGenerationAllowed;
    var templateId;
    var $tableBody;
    this.addDomInitializer("mailing-content-initializer", function() {
        $tableBody = $("#table_body");
        preparedTableEntryTemplate = Template.prepare("mailing-content-table-entry-template");
        isMailingExclusiveLockingAcquired = this.config.isMailingExclusiveLockingAcquired;
        isEditableMailing = this.config.isEditableMailing;
        isContentGenerationAllowed = this.config.isContentGenerationAllowed;
        const dynTagsMap = this.config.dynTagsMap;
        const targetGroups = this.config.targetGroupList;
        const interestGroups = this.config.interestGroupList;
        const dynTagNames = this.config.dynTagNames;
        mailingContent = new MailingContent(dynTagsMap, targetGroups, interestGroups, dynTagNames);
        initTableContent();
        selectLastImportedContentSource();
    });
    this.addDomInitializer("gridTemplate-textContent-initializer", function() {
        $tableBody = $("#textModulesTable");
        templateId = this.config.templateId;
        isEditableMailing = true;
        isContentGenerationAllowed = this.config.isContentGenerationAllowed;
        isMailingExclusiveLockingAcquired = true;
        preparedTableEntryTemplate = Template.prepare("gridTemplate-textContent-tableRow-template");
        mailingContent = new MailingContent(this.config.dynTags, this.config.targets, [], []);
        initTableContent();
    });
    this.addAction({
        click: "createContentEditorModal"
    }, function() {
        const dynNameId = parseInt(this.el.data("dyn-name-id"));
        if (dynNameId > 0) {
            $.ajax({
                url: AGN.url("/mailing/content/name/{id}/view.action".replace("{id}", dynNameId.toString())),
                method: "GET",
                dataType: "json",
                success: function(resp) {
                    const dynTag = new DynTag(resp);
                    const isHtmlContentBlock = mailingContent.isHtmlContentBlock(dynTag.name);
                    const promise = Confirm.createFromTemplate({
                        dynTag: dynTag,
                        targetGroups: _.cloneDeep(mailingContent.targetGroups),
                        interestGroups: _.cloneDeep(mailingContent.interestGroups),
                        saveUrl: AGN.url("/mailing/content/save.action"),
                        DynTagObject: DynTag,
                        isFullHtmlTags: dynTag.name == "HTML-Version",
                        showHTMLEditor: isHtmlContentBlock,
                        isEditableMailing: isEditableMailing,
                        isContentGenerationAllowed: isContentGenerationAllowed
                    }, "content-editor-template");
                    promise.done(function(dynBlock) {
                        mailingContent.setDynTag(dynBlock);
                        replaceTableContent(dynBlock);
                        updatePreview();
                    });
                },
                statusCode: {
                    404: function() {
                        AGN.Lib.Messages(t("defaults.error"), t("defaults.error"), "alert");
                    }
                }
            });
        }
    });
    this.addAction({
        click: "createGridTemplateTextContentEditorModal"
    }, function() {
        const dynNameId = parseInt(this.el.data("dyn-name-id"));
        if (dynNameId > 0) {
            $.ajax({
                url: AGN.url("/layoutbuilder/template/" + templateId + "/textModules/" + dynNameId + "/view.action"),
                method: "GET",
                dataType: "json",
                success: function(resp) {
                    const dynTag = new DynTag(resp);
                    const isHtmlContentBlock = mailingContent.isHtmlContentBlock(dynTag.name);
                    const promise = Confirm.createFromTemplate({
                        dynTag: dynTag,
                        targetGroups: _.cloneDeep(mailingContent.targetGroups),
                        interestGroups: _.cloneDeep(mailingContent.interestGroups),
                        saveUrl: AGN.url("/layoutbuilder/template/" + templateId + "/textModules/update.action"),
                        DynTagObject: DynTag,
                        isFullHtmlTags: dynTag.name == "HTML-Version",
                        showHTMLEditor: isHtmlContentBlock,
                        isEditableMailing: isEditableMailing,
                        isContentGenerationAllowed: isContentGenerationAllowed
                    }, "content-editor-template");
                    promise.done(function(dynBlock) {
                        mailingContent.setDynTag(dynBlock);
                        replaceTableContent(dynBlock);
                    });
                },
                statusCode: {
                    404: function() {
                        AGN.Lib.Messages(t("defaults.error"), t("defaults.error"), "alert");
                    }
                }
            });
        }
    });
    const updatePreview = function() {
        const form = AGN.Lib.Form.get($("#preview"));
        form.setValue("reload", false);
        form.setResourceSelectorOnce("#preview");
        form.submit();
    };
    const initTableContent = function() {
        mailingContent.dynTags.forEach(function(dynTag) {
            $tableBody.append(getFilledTemplate(dynTag));
        });
    };
    const selectLastImportedContentSource = function() {
        const $select = $("#content-source-select");
        if (!$select) {
            return;
        }
        const storageKey = "web-storage#last-content-source";
        const lastContentSource = Storage.get(storageKey);
        if (lastContentSource) {
            if (isOptionExists(lastContentSource.id, $select)) {
                $select.val(lastContentSource.id);
                $select.change();
            } else {
                Storage.delete(storageKey);
            }
        }
    };
    const isOptionExists = function(value, $select) {
        var exists = false;
        $select.find("option").each(function() {
            if (this.value === value) {
                exists = true;
                return false;
            }
        });
        return exists;
    };
    const replaceTableContent = function(dynTag) {
        const html = getFilledTemplate(dynTag);
        $tableBody.find('[data-dyn-name-id="' + dynTag.id + '"]').replaceWith(html);
    };
    const getFilledTemplate = function(dynTag) {
        const targetGroups = dynTag.contentBlocks.map(function(contentBlock) {
            return getTargetGroupName(contentBlock);
        }, []);
        const contents = dynTag.contentBlocks.map(function(contentBlock) {
            return contentBlock.content.length > 35 ? contentBlock.content.substring(0, 35) + "..." : contentBlock.content;
        }, []);
        return preparedTableEntryTemplate({
            id: dynTag.id,
            name: dynTag.name,
            targetGroups: targetGroups,
            contents: contents,
            editable: !!isMailingExclusiveLockingAcquired
        });
    };
    const getTargetGroupName = function(dynContent) {
        var targetGroupName = t("mailing.default.target_group_name");
        if (dynContent.targetId > 0) {
            const targetGroup = mailingContent.getTargetGroupById(dynContent.targetId);
            const description = targetGroup.deleted ? t("mailing.default.target_group_deleted") : targetGroup.id;
            targetGroupName = targetGroup.targetName + " (" + description + ")";
        }
        return targetGroupName;
    };
    const MailingContent = function MailingContent(contentData, availableTargetGroups, interestGroups, dynTagNames) {
        this.dynTags = Object.entries(contentData).map(function(entry) {
            return new DynTag(entry[1]);
        }, []);
        this.interestGroups = _.cloneDeep(interestGroups);
        this.interestGroups.unshift({
            column: "",
            shortname: t("mailing.default.interest_group_name")
        });
        this.targetGroups = _.cloneDeep(availableTargetGroups);
        this.targetGroups.unshift({
            id: 0,
            targetName: t("mailing.default.target_group_name")
        });
        this.targetGroupsMap = availableTargetGroups.reduce(function(map, targetGroup) {
            map[targetGroup.id] = targetGroup;
            return map;
        }, {});
        this.dynTagNames = dynTagNames;
        this.isHtmlContentBlock = function(dynTagName) {
            if (typeof dynTagNames != "undefined" && dynTagNames != null && dynTagNames.length != null && dynTagNames.length > 0) {
                return dynTagNames.includes(dynTagName);
            }
            return false;
        };
        this.getDynTagById = function(id) {
            const filteredBlocks = this.dynTags.filter(function(block) {
                return block.id === id;
            });
            return filteredBlocks[0];
        };
        this.setDynTag = function(dynTag) {
            const currentDynTag = this.getDynTagById(dynTag.id);
            const index = this.dynTags.indexOf(currentDynTag);
            if (index > -1) {
                this.dynTags[index] = dynTag.clone();
            }
        };
        this.getTargetGroupById = function(targetGroupId) {
            return this.targetGroupsMap[targetGroupId] || {
                id: 0,
                targetName: t("mailing.default.target_group_name")
            };
        };
    };
    const DynTag = function(dynTagData) {
        this.id = dynTagData.id || 0;
        this.name = dynTagData.dynName === undefined ? dynTagData.name : dynTagData.dynName;
        this.mailingId = dynTagData.mailingID === undefined ? dynTagData.mailingId : dynTagData.mailingID;
        this.interestGroup = this.interestGroup || "";
        this.interestGroup = dynTagData.interestValue === undefined ? dynTagData.interestGroup : dynTagData.dynInterestGroup;
        if (dynTagData.contentBlocks) {
            this.contentBlocks = dynTagData.contentBlocks.map(function(block) {
                return new DynContent(block);
            });
        } else {
            this.contentBlocks = Object.entries(dynTagData.dynContent).map(function(entry) {
                return new DynContent(entry[1]);
            });
        }
        this.contentBlocks.__proto__.swap = function(indexFrom, indexTo) {
            const temp = this[indexFrom];
            this[indexFrom] = this[indexTo];
            this[indexTo] = temp;
            return this;
        };
        const defaultContentBlock = {
            id: 0,
            index: 0,
            targetId: 0,
            content: ""
        };
        this.getContentBlockByTargetId = function(targetId) {
            const filteredBlocks = this.contentBlocks.filter(function(block) {
                return block.targetId === targetId;
            });
            return filteredBlocks[0];
        };
        this.getContentBlockById = function(id) {
            const filteredBlocks = this.contentBlocks.filter(function(block) {
                return block.uniqueId === id;
            });
            return filteredBlocks[0];
        };
        this.createNewContentBlock = function() {
            const newContentBlock = new DynContent(defaultContentBlock);
            newContentBlock.index = this.contentBlocks.length;
            this.contentBlocks.push(newContentBlock);
            recalculateIndexes(this.contentBlocks);
            return newContentBlock;
        };
        this.moveUpContentBlock = function(contentBlockId) {
            const contentBlock = this.getContentBlockById(contentBlockId);
            if (contentBlock.index > 1) {
                this.contentBlocks.swap(contentBlock.index - 1, contentBlock.index - 2);
                recalculateIndexes(this.contentBlocks);
            }
        };
        this.moveDownContentBlock = function(contentBlockId) {
            const contentBlock = this.getContentBlockById(contentBlockId);
            if (contentBlock.index < this.contentBlocks.length) {
                this.contentBlocks.swap(contentBlock.index - 1, contentBlock.index);
                recalculateIndexes(this.contentBlocks);
            }
        };
        this.setFirstContentBlock = function(contentBlockId) {
            const contentBlock = this.getContentBlockById(contentBlockId);
            if (contentBlock.index > 1) {
                const removedContentBlock = this.contentBlocks.splice(contentBlock.index - 1, 1);
                this.contentBlocks = removedContentBlock.concat(this.contentBlocks);
                recalculateIndexes(this.contentBlocks);
            }
        };
        this.setLastContentBlock = function(contentBlockId) {
            const contentBlock = this.getContentBlockById(contentBlockId);
            if (contentBlock.index < this.contentBlocks.length) {
                const removedContentBlock = this.contentBlocks.splice(contentBlock.index - 1, 1);
                this.contentBlocks = this.contentBlocks.concat(removedContentBlock);
                recalculateIndexes(this.contentBlocks);
            }
        };
        this.changeTargetGroup = function(contentBlockId, newTargetGroupId) {
            const contentBlock = this.getContentBlockById(contentBlockId);
            contentBlock.targetId = newTargetGroupId;
            return contentBlock;
        };
        this.changeInterestGroup = function(interestGroupKey) {
            this.interestGroup = interestGroupKey;
        };
        this.changeContent = function(contentBlockId, newContent) {
            const contentBlock = this.getContentBlockById(contentBlockId);
            contentBlock.content = newContent || "";
            return contentBlock;
        };
        this.changeOrder = function(newOrder) {
            const func = function(self) {
                return function(id) {
                    return self.getContentBlockById(parseInt(id));
                };
            };
            this.contentBlocks = newOrder.map(func(this));
            recalculateIndexes(this.contentBlocks);
        };
        this.remove = function(id) {
            const currentContentBlock = this.getContentBlockById(id);
            const index = this.contentBlocks.indexOf(currentContentBlock);
            if (index > -1) {
                this.contentBlocks.splice(index, 1);
                recalculateIndexes(this.contentBlocks);
            }
        };
        this.removeAll = function() {
            this.contentBlocks = [];
        };
        this.clone = function() {
            return new DynTag(this);
        };
        const recalculateIndexes = function(contentBlocks) {
            contentBlocks.forEach(function(contentBlock, index) {
                contentBlock.index = index + 1;
            });
        };
    };
    const DynContent = function(dynContentData) {
        if (typeof DynContent.uniqueIdCounter === "undefined") {
            DynContent.uniqueIdCounter = 0;
        }
        this.uniqueId = ++DynContent.uniqueIdCounter;
        this.id = dynContentData.id;
        this.index = dynContentData.dynOrder === undefined ? dynContentData.index : dynContentData.dynOrder;
        this.content = dynContentData.dynContent === undefined ? dynContentData.content : dynContentData.dynContent;
        this.targetId = dynContentData.targetID === undefined ? dynContentData.targetId : dynContentData.targetID;
    };
});

AGN.Lib.Controller.new("mailing-content-editor-controller", function() {
    const Modal = AGN.Lib.Modal;
    const Confirm = AGN.Lib.Confirm;
    const Template = AGN.Lib.Template;
    const AutoSave = AGN.Lib.AutoSave;
    var currentDynTag;
    var targetGroups;
    var saveUrl;
    var DynTagObject;
    var showHTMLEditor;
    var isEditableMailing;
    var isContentGenerationAllowed;
    var $selectableContainer;
    var $orderedArea;
    var $targetGroups;
    var $interestGroups;
    var $editableArea;
    var preparedEntryTemplate;
    var EVENT_NAMESPACE = ".mailingContentNamespace";
    var CONTENT_BLOCK_SELECTOR = ".l-mailing-content-entry";
    var ID_PREFIX = "content_entry_";
    this.addDomInitializer("mailing-content-editor-initializer", function($modal) {
        var config = Modal.get($modal);
        currentDynTag = config.dynTag;
        targetGroups = config.targetGroups;
        saveUrl = config.saveUrl;
        DynTagObject = config.DynTagObject;
        showHTMLEditor = config.showHTMLEditor;
        isEditableMailing = config.isEditableMailing;
        isContentGenerationAllowed = config.isContentGenerationAllowed;
        $selectableContainer = $("#content_area");
        $orderedArea = $("#ordered_area");
        $targetGroups = $("#target_groups");
        $interestGroups = $("#interest_groups");
        $editableArea = $("#editable_area");
        preparedEntryTemplate = Template.prepare("mailing-content-entry-template");
        initSortable();
        initModalListeners();
        initButtonClickListeners();
        initDynContent(currentDynTag);
        initInterestGroup(currentDynTag.interestGroup);
        if (currentDynTag.contentBlocks.length > 0) {
            var firstContentBlock = currentDynTag.contentBlocks[0];
            selectContentBlock(firstContentBlock, false);
        } else {
            createNewTag();
        }
        initTargetGroupListeners();
        initInterestListeners();
        var saveToStorage = function() {
            var contentStorage = Array();
            getEditorsContent();
            var contentBlocks = currentDynTag.contentBlocks;
            Array.prototype.forEach.call(contentBlocks, function(block) {
                contentStorage.push({
                    targetGroupId: block.targetId,
                    content: block.content,
                    uniqueId: block.uniqueId
                });
            });
            return contentStorage;
        };
        var readFromStorage = function(contentStorage) {
            var lastContentBlock;
            currentDynTag.removeAll();
            removeAllContentsBlock();
            Array.prototype.forEach.call(contentStorage, function(contentBlockStorage) {
                var $orderedStub = $orderedArea.find(".l-stub");
                var contentBlock = currentDynTag.createNewContentBlock();
                contentBlock.uniqueId = contentBlockStorage.uniqueId;
                contentBlock.content = contentBlockStorage.content;
                contentBlock.targetId = contentBlockStorage.targetGroupId;
                var targetGroup = getTargetGroupById(contentBlock.targetId);
                var html = preparedEntryTemplate({
                    name: targetGroup.targetName,
                    id: ID_PREFIX + contentBlock.uniqueId
                });
                $orderedStub.before(html);
                unlockEditableArea();
                lastContentBlock = contentBlock;
            });
            if (lastContentBlock) {
                selectContentBlock(lastContentBlock);
                synchronizeEditorTab(getActiveEditor());
            }
        };
        var checkIsStorageAdded = function(bundleValues) {
            return bundleValues.length !== currentDynTag.contentBlocks.length || !currentDynTag.contentBlocks.every(function(block) {
                return bundleValues.some(function(bundle) {
                    return bundle.targetGroupId === block.targetId && bundle.content === block.content;
                });
            });
        };
        AutoSave.initialize("mailing-components/" + currentDynTag.mailingId + "/" + currentDynTag.id, saveToStorage, checkIsStorageAdded, readFromStorage, 0);
        displayCharCounter();
    });
    function displayCharCounter() {
        if (getActiveEditor() === "html") {
            showCharCounter();
        } else {
            hideCharCounter();
        }
    }
    this.addAction({
        click: "selectContentEntry"
    }, function() {
        var $current = $(this.el);
        var contentBlockId = getElementId($current);
        var contentBlock = currentDynTag.getContentBlockById(contentBlockId);
        selectContentBlock(contentBlock);
    });
    this.addAction({
        click: "deleteContentEntry"
    }, function() {
        this.event.stopPropagation();
        var $current = $(this.el).parent();
        var id = getElementId($current);
        var $nextSelected = $current.next(CONTENT_BLOCK_SELECTOR);
        $nextSelected = $nextSelected.length > 0 ? $nextSelected : $current.prev(CONTENT_BLOCK_SELECTOR);
        currentDynTag.remove(id);
        $current.remove();
        if (currentDynTag.contentBlocks.length > 0) {
            var nextSelectedId = getElementId($nextSelected);
            var nextSelected = currentDynTag.getContentBlockById(nextSelectedId);
            selectContentBlock(nextSelected);
        } else {
            selectContentBlock();
            lockEditableArea();
        }
    });
    this.addAction({
        click: "createEnlargedContentEditorModal"
    }, function() {
        getEditorsContent();
        var selectedContentBlockId = getSelectedContentBlockId();
        if (selectedContentBlockId) {
            var contentBlock = currentDynTag.getContentBlockById(selectedContentBlockId);
            var promise = Confirm.createFromTemplate({
                content: contentBlock.content,
                selectedContentBlock: selectedContentBlockId,
                editorType: getActiveEditor(),
                isFullHtmlTags: currentDynTag.name == "HTML-Version",
                showHTMLEditor: showHTMLEditor,
                isEditableMailing: isEditableMailing,
                isContentGenerationAllowed: isContentGenerationAllowed
            }, "enlarged-content-editor-template");
            const $modal = $("#content_modal");
            const $enlargedModal = $("#enlarged_content_modal");
            $modal.trigger("modal:enlarged", [ $enlargedModal ]);
            promise.done(function(response) {
                $modal.trigger("modal:enlarged:apply", [ $enlargedModal ]);
                var updatedContentBlock = currentDynTag.changeContent(selectedContentBlockId, response.content);
                setEditorsContent(updatedContentBlock.content);
                synchronizeEditorTab(response.editorType);
            });
        }
    });
    this.addAction({
        click: "addDynContent"
    }, function() {
        createNewTag();
    });
    this.addAction({
        click: "saveDynTag"
    }, function() {
        const event = $.Event("saveDynTag");
        this.el.closest(".modal").trigger(event, [ currentDynTag ]);
        if (!event.isDefaultPrevented()) {
            saveDynTag();
        }
    });
    function saveDynTag() {
        getEditorsContent();
        if (validateDynTag()) {
            const $saveBtn = $('[data-action="saveDynTag"]');
            $.ajax({
                type: "POST",
                url: saveUrl,
                dataType: "json",
                contentType: "application/json",
                data: JSON.stringify(currentDynTag),
                success: function(response) {
                    var deferred = Confirm.get($saveBtn);
                    AGN.Lib.JsonMessages(response.popups, true);
                    if (response.success) {
                        deferred.positive(new DynTagObject(response.data));
                        closeModal();
                    }
                }
            });
        }
    }
    var validateDynTag = function() {
        var duplicatedContentBlocks = currentDynTag.contentBlocks.map(function(content) {
            return content.targetId;
        }).filter(function(targetId, index, targetIds) {
            return targetIds.indexOf(targetId, index + 1) > -1;
        }, []);
        if (duplicatedContentBlocks.length) {
            AGN.Lib.Messages(t("Error"), t("mailing.validation.target_group_duplicated"), "alert");
            return false;
        }
        if (showHTMLEditor) {
            var illegalScriptElement = currentDynTag.contentBlocks.find(function(content) {
                return new DOMParser().parseFromString(content, "text/html").querySelector("script");
            });
            if (illegalScriptElement) {
                AGN.Lib.Messages(t("Error"), t("fields.error.illegal_script_element"), "alert");
                return false;
            }
        }
        var allRecipientsContentBlock = currentDynTag.contentBlocks.filter(function(block) {
            return block.targetId === 0;
        }, []);
        if (allRecipientsContentBlock.length !== currentDynTag.contentBlocks.length) {
            if (allRecipientsContentBlock.length && allRecipientsContentBlock[0].index < currentDynTag.contentBlocks.length) {
                AGN.Lib.Messages(t("Error"), t("mailing.validation.all_recipients_not_last"), "alert");
                return false;
            }
        }
        return true;
    };
    var moveUp = function() {
        var $current = getSelectedContentBlock();
        var $previous = $current.prev(CONTENT_BLOCK_SELECTOR);
        if ($previous.length !== 0) {
            $current.insertBefore($previous);
            currentDynTag.moveUpContentBlock(getElementId($current));
        }
    };
    var moveDown = function() {
        var $current = getSelectedContentBlock();
        var $next = $current.next(CONTENT_BLOCK_SELECTOR);
        if ($next.length !== 0) {
            $current.insertAfter($next);
            currentDynTag.moveDownContentBlock(getElementId($current));
        }
    };
    var initModalListeners = function() {
        const $modal = $("#content_modal");
        $modal.on("saveDynTagContent", function(e, content) {
            setContentToDynTag(content);
            saveDynTag();
        });
    };
    var initButtonClickListeners = function() {
        var ESC = 27;
        var UP = 38;
        var DOWN = 40;
        $(document).off("keydown" + EVENT_NAMESPACE);
        $(document).on("keydown" + EVENT_NAMESPACE, function(event) {
            event.stopPropagation();
            switch (event.which) {
              case ESC:
                closeModal();
                break;

              case UP:
                moveUp();
                break;

              case DOWN:
                moveDown();
                break;

              default:
                return;
            }
        });
    };
    var initSortable = function() {
        $selectableContainer.sortable({
            opacity: .4,
            delay: 100,
            scroll: true,
            scrollSensitivity: 40,
            scrollSpeed: 15,
            cursor: "move",
            items: CONTENT_BLOCK_SELECTOR,
            helper: "clone",
            containment: $orderedArea,
            appendTo: $orderedArea,
            start: function(event, ui) {
                ui.item.css("cursor", "move");
            },
            stop: function(event, ui) {
                ui.item.removeAttr("style");
                var sortableBlock = $(event.target);
                var newOrder = sortableBlock.sortable("toArray");
                var newOrderIds = newOrder.map(function(id) {
                    return id.replace(ID_PREFIX, "");
                });
                currentDynTag.changeOrder(newOrderIds);
            }
        });
    };
    var getActiveEditor = function() {
        var $wysiwygEditorBlock = $("#tab-content-wysiwyg");
        if ($wysiwygEditorBlock.is(":visible")) {
            return "wysiwyg";
        }
        var $htmlEditorBlock = $("#contentEditor");
        if ($htmlEditorBlock.is(":visible")) {
            return "html";
        }
        const $aiTextGenerationBlock = $("#tab-content-ai-text-generation");
        if ($aiTextGenerationBlock.is(":visible")) {
            return "ai-text-generation";
        }
        return "";
    };
    var synchronizeEditorTab = function(editorType) {
        if (!editorType || editorType === "") {
            return;
        }
        var tabLink = $('[data-toggle-tab$="' + editorType + '"]');
        if (tabLink) {
            tabLink.trigger("click");
        }
    };
    var setEditorsContent = function(content, selectAll) {
        const $wysiwygEditorBlock = $("#tab-content-wysiwyg");
        const $htmlEditorBlock = $("#contentEditor");
        const $aiTextGenerationBlock = $("#tab-content-ai-text-generation");
        if ($wysiwygEditorBlock.is(":visible")) {
            var editor = CKEDITOR.instances["content"];
            if (editor.status === "ready") {
                editor.setData(content);
            } else {
                editor.on("instanceReady", function(event) {
                    event.editor.setData(content);
                });
            }
        }
        if ($htmlEditorBlock.is(":visible")) {
            var cursorPos;
            if (selectAll === false) {
                cursorPos = 1;
            } else {
                cursorPos = null;
            }
            var aceEditor = ace.edit("contentEditor");
            if ($("body").hasClass("dark-theme")) {
                aceEditor.setTheme("ace/theme/idle_fingers");
            }
            aceEditor.setValue(content, cursorPos);
        }
        if ($aiTextGenerationBlock.is(":visible")) {
            $aiTextGenerationBlock.closest("form").find(".js-wysiwyg").val(content);
        }
    };
    var getEditorsContent = function() {
        var selectedContentBlockId = getSelectedContentBlockId();
        if (selectedContentBlockId > 0) {
            var $wysiwygEditorBlock = $("#tab-content-wysiwyg");
            var $htmlEditorBlock = $("#contentEditor");
            var content;
            if ($wysiwygEditorBlock.is(":visible")) {
                var wysiwygEditor = CKEDITOR.instances["content"];
                content = wysiwygEditor.getData();
            }
            if ($htmlEditorBlock.is(":visible")) {
                var htmlEditor = ace.edit("contentEditor");
                if ($("body").hasClass("dark-theme")) {
                    htmlEditor.setTheme("ace/theme/idle_fingers");
                }
                content = htmlEditor.getValue();
            }
            if (content !== undefined) {
                currentDynTag.changeContent(selectedContentBlockId, content);
            }
        }
    };
    var setContentToDynTag = function(content) {
        const selectedContentBlockId = getSelectedContentBlockId();
        if (selectedContentBlockId > 0) {
            currentDynTag.changeContent(selectedContentBlockId, content);
        }
    };
    var initDynContent = function(dynTag) {
        dynTag.contentBlocks.forEach(function(contentBlock) {
            var $orderedStub = $orderedArea.find(".l-stub");
            var targetGroup = getTargetGroupById(contentBlock.targetId);
            var html = preparedEntryTemplate({
                name: targetGroup.targetName,
                id: ID_PREFIX + contentBlock.uniqueId
            });
            $orderedStub.before(html);
        });
    };
    var initTargetGroup = function(id) {
        $targetGroups.val(id).trigger("change");
    };
    var initTargetGroupListeners = function() {
        $targetGroups.off("change" + EVENT_NAMESPACE);
        $targetGroups.on("change" + EVENT_NAMESPACE, function(event) {
            var newTargetGroupId = parseInt($(event.target).val());
            var selectedContentBlockId = getSelectedContentBlockId();
            if (selectedContentBlockId > 0) {
                var updatedContentBlock = currentDynTag.changeTargetGroup(selectedContentBlockId, newTargetGroupId);
                updateSelectedContentBlock(updatedContentBlock);
            }
        });
    };
    var initInterestGroup = function(key) {
        $interestGroups.val(key).trigger("change");
    };
    var initInterestListeners = function() {
        $interestGroups.off("change" + EVENT_NAMESPACE);
        $interestGroups.on("change" + EVENT_NAMESPACE, function(event) {
            var newInterestGroupKey = $(event.target).val();
            currentDynTag.changeInterestGroup(newInterestGroupKey);
        });
    };
    var updateSelectedContentBlock = function(contentBlock) {
        var $dynTag = findElementById(contentBlock.uniqueId);
        if ($dynTag.length > 0) {
            var targetGroup = getTargetGroupById(contentBlock.targetId);
            $dynTag.find(".l-name").children().text(targetGroup.targetName);
        }
    };
    var getSelectedContentBlock = function() {
        return $orderedArea.find(CONTENT_BLOCK_SELECTOR + ".selected");
    };
    var removeAllContentsBlock = function() {
        $orderedArea.find(CONTENT_BLOCK_SELECTOR).remove();
    };
    var getSelectedContentBlockId = function() {
        var $selectedDynTag = getSelectedContentBlock();
        if ($selectedDynTag.length > 0) {
            return getElementId($selectedDynTag);
        }
    };
    var markSelected = function(contentBlockId) {
        $orderedArea.children().removeClass("selected");
        var $clickedBlock = findElementById(contentBlockId, $orderedArea);
        $clickedBlock.addClass("selected");
    };
    var getTargetGroupById = function(id) {
        var filteredTargetGroups = targetGroups.filter(function(targetGroup) {
            return targetGroup.id === id;
        });
        return filteredTargetGroups[0];
    };
    var findElementById = function(id, $parent) {
        $parent = $parent ? $parent : $(document);
        return $parent.find("#" + ID_PREFIX + id);
    };
    var getElementId = function($element) {
        return parseInt($element.attr("id").replace(ID_PREFIX, ""));
    };
    var closeModal = function() {
        $(".modal").modal("toggle");
    };
    var selectContentBlock = function(contentBlock, selectAll) {
        getEditorsContent();
        if (contentBlock !== undefined) {
            markSelected(contentBlock.uniqueId);
            setEditorsContent(contentBlock.content, selectAll);
            initTargetGroup(contentBlock.targetId);
        } else {
            setEditorsContent("");
            initTargetGroup(0);
        }
    };
    var createNewTag = function() {
        var $orderedStub = $orderedArea.find(".l-stub");
        var contentBlock = currentDynTag.createNewContentBlock();
        var targetGroup = getTargetGroupById(contentBlock.targetId);
        var html = preparedEntryTemplate({
            name: targetGroup.targetName,
            id: ID_PREFIX + contentBlock.uniqueId
        });
        $orderedStub.before(html);
        unlockEditableArea();
        selectContentBlock(contentBlock);
    };
    var lockEditableArea = function() {
        if ($editableArea.is(":visible")) {
            $editableArea.hide();
        }
    };
    var unlockEditableArea = function() {
        if ($editableArea.is(":hidden")) {
            $editableArea.show();
        }
    };
    const updateCharCounter = function($el) {
        const count = $el.val().length;
        $('[data-char-counter-for="' + $el.attr("id") + '"]').find("span:first").text(t("fields.content.charactersEntered", count));
    };
    this.addAction({
        "editor:create": "count-textarea-chars",
        "editor:change": "count-textarea-chars",
        input: "count-textarea-chars"
    }, function() {
        updateCharCounter(this.el);
    });
    this.addAction({
        click: "hide-char-counter"
    }, function() {
        hideCharCounter();
    });
    this.addAction({
        click: "show-char-counter"
    }, function() {
        showCharCounter();
    });
    function showCharCounter() {
        $("[data-char-counter-for]").first().show();
    }
    function hideCharCounter() {
        $("[data-char-counter-for]").first().hide();
    }
    $(document).on("ckeditor-save", function() {
        saveDynTag();
    });
});

AGN.Lib.Controller.new("mailing-overview", function() {
    const Form = AGN.Lib.Form;
    var adminDateFormat = "dd.MM.yyyy";
    this.addDomInitializer("mailing-overview", function() {
        adminDateFormat = this.config.adminDateFormat;
    });
    this.addAction({
        click: "restore"
    }, function() {
        const form = Form.get(this.el);
        $.post(this.el.attr("href")).done(function(resp) {
            form.updateHtml(resp);
        });
    });
    this.addAction({
        click: "bulk-restore"
    }, function() {
        const form = Form.get(this.el);
        $.ajax(AGN.url("/mailing/bulkRestore.action"), {
            method: "POST",
            data: form.data()
        }).done(function(resp) {
            form.updateHtml(resp);
        });
    });
    this.addAction({
        click: "send-date-filter-period"
    }, function() {
        controlSendDatePeriodSelect(this.el);
        $("#filterSendDateBegin").val(getSendDateBeginVal());
        $("#filterSendDateEnd").val(getSendDateEndVal());
        toggleSendDateInputsReadonly($("input[name='sendDatePeriod']:checked").length > 0);
    });
    this.addAction({
        click: "reset-send-date-filter"
    }, function() {
        $("#filterSendDateBegin").val("");
        $("#filterSendDateEnd").val("");
        $('input[name="sendDatePeriod"]:checked').removeAttr("checked");
        toggleSendDateInputsReadonly(false);
    });
    function toggleSendDateInputsReadonly(readonly) {
        const $sendDateBegin = $("#filterSendDateBegin");
        const $sendDateEnd = $("#filterSendDateEnd");
        $sendDateBegin.get(0).toggleAttribute("readonly", readonly);
        $sendDateEnd.get(0).toggleAttribute("readonly", readonly);
        $sendDateBegin.toggleClass("js-datepicker", !readonly);
        $sendDateEnd.toggleClass("js-datepicker", !readonly);
    }
    function getSendDateBeginVal() {
        const period = $("input[name='sendDatePeriod']:checked").val();
        if (!period) {
            return "";
        }
        const date = new Date();
        date.setDate(date.getDate() - period);
        return AGN.Lib.DateFormat.format(date, adminDateFormat);
    }
    function getSendDateEndVal() {
        return $("input[name='sendDatePeriod']:checked").length ? AGN.Lib.DateFormat.format(new Date(), adminDateFormat) : "";
    }
    function controlSendDatePeriodSelect($periodCheckbox) {
        if ($periodCheckbox.is(":checked")) {
            const group = "input:checkbox[name='" + $periodCheckbox.attr("name") + "']";
            $(group).prop("checked", false);
            $periodCheckbox.prop("checked", true);
        } else {
            $periodCheckbox.prop("checked", false);
        }
    }
});

AGN.Lib.Controller.new("mailing-parameter-list-search", function() {
    this.addDomInitializer("mailing-parameter-list-search", function() {
        var config = this.config;
        var mailingQuery = config.mailingQuery;
        var paramQuery = config.paramQuery;
        var $paramSearchField = $("#param-search-field");
        var $mailingSearchField = $("#mailing-search-field");
        new initSelect2Field($paramSearchField, "paramQuery", paramQuery, false);
        new initSelect2Field($mailingSearchField, "mailingQuery", mailingQuery, true);
    });
    function initSelect2Field($field, searchFieldName, oldValue, isSelectable) {
        var lastSearchQuery = oldValue;
        var lastResults = {
            results: []
        };
        var $fieldCopy = $field;
        $fieldCopy.select2({
            openOnEnter: true,
            minimumInputLength: 1,
            initSelection: function(element, callback) {},
            id: function(dataEntry) {
                if (isSelectable) {
                    return dataEntry.mailingID;
                }
                return lastSearchQuery;
            },
            formatResult: function(resultEntry) {
                return '<div style="box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);">' + '<div class="row">' + '<div class="col-sm-6">' + t("fields.mailing.parameter") + "</div>" + '<div class="col-sm-6">' + resultEntry.name + "</div>" + "</div>" + '<div class="row">' + '<div class="col-sm-6">' + t("fields.mailing.description") + "</div>" + '<div class="col-sm-6">' + resultEntry.description + "</div>" + "</div>" + '<div class="row">' + '<div class="col-sm-6">' + t("fields.mailing.for_mailing") + "</div>" + '<div class="col-sm-6">' + resultEntry.mailingID + "</div>" + "</div>" + '<div class="row">' + '<div class="col-sm-6">' + t("fields.mailing.change_date") + "</div>" + '<div class="col-sm-6  ">' + new Date(resultEntry.changeDate).toLocaleDateString() + "</div>" + "</div>" + "</div>";
            },
            formatSelection: function(searchEntry) {
                if (isSelectable) {
                    return searchEntry.mailingID;
                }
                AGN.Lib.Page.reload(AGN.url("/mailing/parameters/" + searchEntry.mailingInfoID + "/view.action"), true);
            },
            ajax: {
                url: AGN.url("/mailing/parameters/search.action"),
                data: function(searchQuery) {
                    var searchRequest = {};
                    lastSearchQuery = searchQuery;
                    setInputText(lastSearchQuery, $fieldCopy);
                    searchRequest[searchFieldName] = searchQuery;
                    return searchRequest;
                },
                results: function(searchResponse) {
                    var id = 0;
                    searchResponse.forEach(function(entry) {
                        entry.id = id++;
                    });
                    lastResults = {
                        results: searchResponse
                    };
                    return lastResults;
                },
                cache: true
            }
        });
        $fieldCopy.on("select2-open", function() {
            setSearchText(lastSearchQuery, $fieldCopy);
        });
        function setSearchText(searchText, $field) {
            var text = searchText || "";
            $field.select2("search", text);
        }
        function setInputText(searchText, $field) {
            var text = searchText || "";
            var $fakeSearchField = $field.select2("container").find(".select2-chosen");
            $field.select2("val", text);
            $fakeSearchField.text(text);
        }
        setInputText(oldValue, $fieldCopy);
    }
});

AGN.Lib.Controller.new("mailing-parameters", function() {
    var mailingParamsIndex = 0;
    this.addDomInitializer("mailing-parameters", function() {
        var config = this.config;
        mailingParamsIndex = config.maxIndex;
    });
    this.addAction({
        click: "add-mailing-parameter"
    }, function() {
        var trLast = $("#mailingParamsTable tr:last");
        var newRow = AGN.Lib.Template.text("mailing-param-row-new", {
            key: ++mailingParamsIndex
        });
        trLast.after(newRow);
        var newBtn = trLast.find("#newMailingParameterBtn");
        newBtn.after('<a href="#" class="btn btn-regular btn-alert" data-action="remove-mailing-parameter" id="removeMailingParameterBtn"> <i class="icon icon-trash-o"></i> </a>');
        newBtn.remove();
    });
    this.addAction({
        click: "remove-mailing-parameter"
    }, function() {
        var $currentTr = this.el.closest("tr");
        $currentTr.remove();
    });
});

AGN.Lib.Controller.new("mailing-params", function() {
    var rowTemplate = _.template(AGN.Opt.Templates["mailing-param-row"]);
    var $table;
    var isChangeable = false;
    var initParams;
    this.addDomInitializer("mailing-params", function() {
        $table = $("#mailingParamsTable tbody");
        isChangeable = this.config.isChangeable;
        initParams = this.config.params;
        loadTableRows(initParams);
        const $form = $("#mailingSettingsForm");
        $form.dirty("setAsClean");
        $form.dirty("refreshEvents");
    });
    function loadTableRows(rows) {
        _.each(rows, function(row, index) {
            insertRow(index, row.name, row.value, row.description);
        });
        if (isChangeable) {
            appendLastRow("", "", "");
        }
    }
    function addParam() {
        if (isUniqueRow("", "")) {
            replaceNewButtonWithDeleteButton();
            appendLastRow("", "", "");
        }
    }
    function getNextInputToFocus($current) {
        if (!$current.is("[data-param-description]")) {
            return $current.closest("td").next().find("input:text");
        }
        var $nameInput = $current.closest("tr").find("[data-param-name]");
        if (!$nameInput.val()) {
            return $nameInput;
        }
        if (!$current.is('[data-action="param-enterdown"]:last')) {
            return $current.closest("tr").next().find("input:text:first");
        }
        addParam();
        return $table.find("[data-param-name]:last");
    }
    this.addAction({
        enterdown: "param-enterdown"
    }, function() {
        this.event.preventDefault();
        getNextInputToFocus(this.el).focus();
    });
    this.addAction({
        click: "add-param-row"
    }, function() {
        this.event.preventDefault();
        addParam();
        $table.find("[data-param-name]:last").focus();
    });
    function isParamsChanged() {
        const cleanInitParams = initParams.map(function(param) {
            const cleanParam = _.omit(param, "mailingID", "mailingInfoID", "changeDate");
            Object.keys(cleanParam).forEach(function(key) {
                if (cleanParam[key] === null) {
                    cleanParam[key] = "";
                }
            });
            return cleanParam;
        });
        return JSON.stringify(cleanInitParams) !== JSON.stringify(AGN.Opt.collectMailinParams());
    }
    this.addAction({
        click: "delete-param-row"
    }, function() {
        this.el.closest("tr").remove();
        $("#mailingSettingsForm").dirty("setAsDirty");
        controlParamsDirtyState();
    });
    this.addAction({
        change: "param-enterdown"
    }, function() {
        controlParamsDirtyState();
    });
    function isDirtyOnlyMailingParamsFields() {
        return $("#mailingSettingsForm").dirty("showDirtyFields").filter(function(_, e) {
            return !$(e).closest("[data-param-row]").length;
        }).length === 0;
    }
    function controlParamsDirtyState() {
        const $form = $("#mailingSettingsForm");
        if (isDirtyOnlyMailingParamsFields() && !isParamsChanged()) {
            $form.dirty("setAsClean");
        }
    }
    function insertRow(index, name, value, description) {
        if (isUniqueRow(name, value)) {
            $table.append(rowTemplate({
                index: index,
                name: name,
                value: value,
                description: description,
                isChangeable: isChangeable
            }));
        }
    }
    function getLastParamRow() {
        return $table.find("[data-param-row]:last-child");
    }
    function appendLastRow(name, value, description) {
        var lastIndex = getLastParamRow().data("param-row") || 0;
        insertRow(++lastIndex, name, value, description);
    }
    function isUniqueRow(name, value) {
        var unique = true;
        _.each($table.find("[data-param-row]"), function(row) {
            var $row = $(row);
            if (unique) {
                if (getCellValByCol($row, "name") == name && getCellValByCol($row, "value") == value) {
                    unique = false;
                }
            }
        });
        return unique;
    }
    function replaceNewButtonWithDeleteButton() {
        var newBtn = $table.find("#newParamBtn");
        newBtn.after("<a href='#' class='btn btn-regular btn-alert' data-action='delete-param-row'>" + "<i class='icon icon-trash-o'></i></a>");
        newBtn.remove();
    }
    function getCellValByCol($row, col) {
        return $row.find("[data-param-" + col + "]").val();
    }
});

AGN.Lib.Controller.new("mailing-predelivery", function() {
    var providers = {
        aol: "aolonelinespam",
        yahoo: "yahoospam",
        gmailnew: "gmailnewspam",
        ol2003: "ol2003spam"
    };
    this.addAction({
        change: "adjustSpamProvider"
    }, function() {
        var $el = $(this.el);
        var spamProvider = providers[$el.attr("name")];
        if (!spamProvider) {
            return;
        }
        var $spanProvider = $('[name="' + spamProvider + '"]');
        if ($el.prop("checked")) {
            $spanProvider.prop("disabled", false);
        } else {
            $spanProvider.prop("disabled", true);
            $spanProvider.prop("checked", false);
        }
    });
    this.addInitializer("readjustSpamProviders", function() {
        _.each(providers, function(spamProvider, provider) {
            var $provider = $("[name=" + provider + "]");
            if ($provider.length === 0) {
                return;
            }
            var $spamProvider = $('[name="' + spamProvider + '"]');
            if ($provider.prop("checked")) {
                $spamProvider.prop("disabled", false);
            } else {
                $spamProvider.prop("disabled", true);
                $spamProvider.prop("checked", false);
            }
        });
    });
    function toggleCheckboxes($el, isChecked) {
        var checkboxes = $el.closest(".list-group").find('input[type="checkbox"]:enabled');
        checkboxes.prop("checked", isChecked);
        checkboxes.trigger("change");
    }
    this.addAction({
        click: "toggle-checkboxes-on"
    }, function() {
        toggleCheckboxes($(this.el), true);
    });
    this.addAction({
        click: "toggle-checkboxes-off"
    }, function() {
        toggleCheckboxes($(this.el), false);
    });
});

AGN.Lib.Controller.new("mailing-preview", function() {
    var Form = AGN.Lib.Form, Messages = AGN.Lib.Messages, Helpers = AGN.Lib.Helpers, Select = AGN.Lib.Select, Storage = AGN.Lib.Storage;
    var RECIPIENT_MODE, TARGET_MODE;
    var MAILING_ID;
    var needReload = false;
    this.addDomInitializer("mailing-preview", function($frame) {
        var config = this.config;
        RECIPIENT_MODE = config.RECIPIENT_MODE;
        TARGET_MODE = config.TARGET_MODE;
        MAILING_ID = config.MAILING_ID;
        restoreFields();
        var form = Form.get($("#container-preview"));
        if (form.getValue("reload") == "false") {
            form.setValue("reload", true);
            form.submit().done(function() {
                $("[data-stored-field]").on("change", function() {
                    var $field = $(this);
                    Storage.saveChosenFields($field);
                    needReload = needReload || isTriggeredField($field.prop("name"));
                });
                form.initFields();
                form.initValidator();
                AGN.Lib.CoreInitializer.run("view");
                controlTestRunVisibility();
            });
        }
    });
    this.addAction({
        click: "refresh-preview"
    }, function() {
        needReload = false;
        updatePreview();
    });
    this.addAction({
        change: "change-stored-header-data"
    }, function() {
        if (needReload) {
            needReload = false;
            updatePreview();
        }
    });
    this.addAction({
        change: "change-header-data"
    }, function() {
        updatePreview();
    });
    this.addAction({
        click: "toggle-tab-recipientMode"
    }, function() {
        changePreviewMode(RECIPIENT_MODE);
    });
    this.addAction({
        click: "toggle-tab-targetGroupMode"
    }, function() {
        changePreviewMode(TARGET_MODE);
    });
    function changePreviewMode(value) {
        var $field = $('[name="modeTypeId"]');
        if ($field.exists()) {
            $field.val(value);
            $field.trigger("change");
        }
    }
    function updatePreview(formCallback) {
        var form = Form.get($("#preview"));
        if (formCallback && typeof formCallback == "function") {
            formCallback(form);
        }
        form.setValue("reload", false);
        form.setResourceSelectorOnce("#preview");
        form.submit();
    }
    function restoreFields() {
        var needReload = false;
        $("[data-stored-field]").each(function() {
            var $e = $(this), name = $e.prop("name");
            if (!isTriggeredField(name)) {
                if (Storage.restoreChosenFields($e)) {
                    needReload = true;
                }
            }
        });
        synchronizeModeWithActiveTab();
        Storage.restoreChosenFields($("[name='modeTypeId']"));
        Storage.restoreChosenFields($("[name='customerATID']"));
        Storage.restoreChosenFields($("[name='customerEmail']"));
        Storage.restoreChosenFields($("[name='targetGroupId']"));
    }
    function synchronizeModeWithActiveTab() {
        var targetMode = Storage.get("toggle_tab#preview-targetModeContent");
        if (targetMode && !targetMode.hidden) {
            $("[name='modeTypeId']").val(TARGET_MODE);
            Storage.saveChosenFields($("[name='modeTypeId']"));
        }
        var recipientMode = Storage.get("toggle_tab#preview-recipientModeContent");
        if (recipientMode && !recipientMode.hidden) {
            $("[name='modeTypeId']").val(RECIPIENT_MODE);
            Storage.saveChosenFields($("[name='modeTypeId']"));
        }
    }
    function isTriggeredField(fieldName) {
        if (!fieldName) {
            return false;
        }
        return fieldName == "customerATID" || fieldName == "customerEmail" || fieldName == "modeTypeId" || fieldName == "targetGroupId";
    }
    function controlTestRunVisibility() {
        controlTestRunContainerVisibility();
        controlAddToTestRunBtnVisibility();
    }
    this.addAction({
        click: "change-preview-customer-options"
    }, function() {
        controlAddToTestRunBtnVisibility();
    });
    function controlTestRunContainerVisibility() {
        const $testRecipients = getTestRecipients$();
        if (!$testRecipients.exists()) {
            return;
        }
        const hidden = $testRecipients.val().length <= 0;
        $("#personalized-test-run-container").toggleClass("hidden", hidden);
    }
    function getTestRecipients$() {
        return $("#personalized-test-recipients");
    }
    function controlAddToTestRunBtnVisibility() {
        const previewRecipientEmail = getEmailOfCurrentPreviewRecipient();
        const isVisible = Select.get(getTestRecipients$()).getSelectedValue().indexOf(previewRecipientEmail) === -1;
        $('[data-action="add-to-personalized-test-run"]').toggle(!!isVisible);
    }
    function getEmailOfCurrentPreviewRecipient() {
        if (isRecipientChosenByInput()) {
            return $("#customerEmail").val();
        }
        return $('[name="customerATID"]').find(":selected").data("email");
    }
    function isRecipientChosenByInput() {
        return $('[name="useCustomerEmail"]:checked').val() !== "false";
    }
    function validateEmailOfCurrentPreviewRecipient() {
        return new Promise(function(resolve, reject) {
            var email = getEmailOfCurrentPreviewRecipient();
            if (!Helpers.isValidEmail(email)) {
                Messages(t("defaults.error"), t("defaults.invalidEmail"), "alert");
                return;
            }
            $.get(AGN.url("/mailing/preview/" + MAILING_ID + "/isRecipient.action"), {
                email: email
            }).done(function(resp) {
                if (resp.success) {
                    resolve(email);
                } else {
                    AGN.Lib.JsonMessages(resp.popups, true);
                    reject();
                }
            });
        });
    }
    this.addAction({
        input: "change-personalized-test-recipients",
        change: "change-personalized-test-recipients"
    }, function() {
        controlTestRunVisibility();
    });
    this.addAction({
        click: "add-to-personalized-test-run"
    }, function() {
        validateEmailOfCurrentPreviewRecipient().then(function(email) {
            const $testRecipients = getTestRecipients$();
            const testRecipients = Select.get($testRecipients);
            if (!testRecipients.hasOption(email)) {
                $testRecipients.append($("<option>", {
                    value: email,
                    text: email
                }));
            }
            $testRecipients.val(_.union($testRecipients.val(), [ email ]));
            AGN.Lib.CoreInitializer.run("select", $testRecipients);
            controlTestRunVisibility();
        });
    });
    this.addAction({
        click: "personalized-test-run"
    }, function() {
        const testRecipients$ = getTestRecipients$();
        const recipientIds = testRecipients$.val();
        $.post(AGN.url("/mailing/send/" + MAILING_ID + "/personalized-test.action"), {
            mailingTestRecipients: recipientIds
        }).done(function(resp) {
            if (resp && resp.success === true) {
                testRecipients$.val([]);
                AGN.Lib.CoreInitializer.run("select", testRecipients$);
                controlTestRunContainerVisibility();
            }
            AGN.Lib.JsonMessages(resp.popups, true);
        });
    });
});

AGN.Lib.Controller.new("mailing-priorities", function() {
    var Template = AGN.Lib.Template, Helpers = AGN.Lib.Helpers, DateFormat = AGN.Lib.DateFormat;
    var DATE_BASED_TYPE = 2;
    var NORMAL_TYPE = 0;
    var $saveButton, $priorityCount, $orderedArea, $unorderedDateBasedArea, $unorderedNormalArea;
    var mailingsMap;
    var originPrioritizedIds;
    var originPriorityCount;
    var createEntry;
    function updateBadges() {
        var index = 1;
        var nextDateBasedIndex = 10;
        $orderedArea.children(".l-mailing-entry").each(function() {
            var $e = $(this);
            var priority = 0;
            if ($e.data("type") == DATE_BASED_TYPE) {
                priority = nextDateBasedIndex;
                index = nextDateBasedIndex;
                nextDateBasedIndex += 10;
            } else {
                priority = index;
                if (index > nextDateBasedIndex) {
                    nextDateBasedIndex = Math.round(index / 10) * 10;
                }
            }
            index++;
            $e.find(".l-badge .badge").text(priority);
        });
    }
    function collectPrioritizedIds(separator) {
        var ids = [];
        $orderedArea.children(".l-mailing-entry").each(function() {
            var id = $(this).data("id");
            if (id > 0) {
                ids.push(id);
            }
        });
        return separator ? ids.join(separator) : ids;
    }
    function countPrioritizedTemplates() {
        var count = 0;
        $orderedArea.children(".l-mailing-entry").each(function() {
            if ($(this).data("id") > 0) {
                count++;
            }
        });
        return count;
    }
    function checkOriginChanges(reset) {
        var newPrioritizedIds = collectPrioritizedIds(";");
        var newPriorityCount = $priorityCount.val();
        if (originPrioritizedIds == null && originPriorityCount == null || reset) {
            originPrioritizedIds = newPrioritizedIds;
            originPriorityCount = newPriorityCount;
            if (newPriorityCount > 0) {
                $saveButton.prop("disabled", true);
            } else {
                var count = countPrioritizedTemplates();
                $priorityCount.val(count);
                $saveButton.prop("disabled", !count);
            }
        } else {
            $saveButton.prop("disabled", newPrioritizedIds == originPrioritizedIds && newPriorityCount == originPriorityCount);
        }
    }
    function clear() {
        $("#datebased-container, #normal-container, #ordered-area").find(".l-mailing-entry").remove();
    }
    function strDateToArray(date, stub) {
        return DateFormat.toArray(DateFormat.parse(date), stub);
    }
    function arrayDateToStr(date) {
        return Helpers.pad(date[0], 4) + "-" + Helpers.pad(parseInt(date[1]) + 1, 2) + "-" + Helpers.pad(date[2], 2);
    }
    function shiftDateArray(dateArray, years, months, days) {
        var newDate = _.clone(dateArray);
        if (!!years) {
            newDate[0] = dateArray[0] + years;
        }
        if (!!months) {
            newDate[1] = dateArray[1] + months;
        }
        if (!!days) {
            newDate[2] = dateArray[2] + days;
        }
        return newDate;
    }
    function minDay() {
        return _.reduce(_.keys(mailingsMap), function(a, b) {
            return a < b ? a : b;
        });
    }
    var getAllDateBasedMailingsPriority = function(excludeIds) {
        var dateBasedMailings = [];
        var exclude = _.clone(excludeIds);
        _.keys(mailingsMap).forEach(function(date) {
            mailingsMap[date].forEach(function(e) {
                if (e.mailingType == DATE_BASED_TYPE && !exclude.includes(e.id)) {
                    var m = _.clone(e);
                    exclude.push(m.id);
                    dateBasedMailings.push(e);
                }
            });
        });
        return dateBasedMailings;
    };
    function collectMailingEntries(day) {
        var entries = mailingsMap[day] || [];
        entries = entries.filter(function(e) {
            return e.mailingType != DATE_BASED_TYPE || e.mailingType == DATE_BASED_TYPE && e.priority > 0;
        });
        var excludeIds = entries.map(function(e) {
            return e.id;
        });
        return _.union(entries, getAllDateBasedMailingsPriority(excludeIds), "id").sort(function(a, b) {
            return a.priority > b.priority ? 1 : -1;
        });
    }
    function select(day) {
        var entries = collectMailingEntries(day);
        clear();
        moveToProperBox(entries);
        checkOriginChanges(true);
    }
    function moveToProperBox(entries) {
        if (entries && entries.length) {
            entries.forEach(function(e) {
                updateIconClass(e);
                var html = createEntry(e);
                var ordered = e.priority;
                var type = e.mailingType;
                if (ordered) {
                    $orderedArea.find(".l-stub").before(html);
                } else {
                    if (type == DATE_BASED_TYPE) {
                        $unorderedDateBasedArea.find(".l-stub").before(html);
                    }
                    if (type == NORMAL_TYPE) {
                        $unorderedNormalArea.find(".l-stub").before(html);
                    }
                }
            });
        }
    }
    function updateIconClass(e) {
        var iconClass = "normal-mailing-icon";
        if (e.mailingType == DATE_BASED_TYPE) {
            iconClass = "datebase-mailing-icon";
        }
        e.iconClass = iconClass;
    }
    var isAppropriateType = function(targetId, mailingType) {
        var isDateBasedArea = targetId === $unorderedDateBasedArea.attr("id");
        var isNormalArea = targetId === $unorderedNormalArea.attr("id");
        var isOrderedArea = targetId === $orderedArea.attr("id");
        return isOrderedArea || isDateBasedArea && mailingType == DATE_BASED_TYPE || isNormalArea && mailingType == NORMAL_TYPE;
    };
    var highlightBackground = function($target, activate) {
        if (activate) {
            $target.parent().addClass("highlight");
        } else {
            $target.parent().removeClass("highlight");
        }
    };
    var findDateBasedStart = function(dates) {
        for (var key in dates) {
            var firstMailing = mailingsMap[dates[key]].find(function(value) {
                return value.mailingType == DATE_BASED_TYPE;
            });
            if (!!firstMailing) {
                return dates[key];
            }
        }
        return "";
    };
    var computeDisableConstraints = function(dates) {
        var constraints = [ true ];
        var dateBasedStart = strDateToArray(findDateBasedStart(dates));
        var filteredDates = !dateBasedStart ? dates : dates.filter(function(d) {
            return d < dateBasedStart;
        });
        filteredDates.forEach(function(str) {
            var date = strDateToArray(str);
            if (date) {
                constraints.push(date);
            }
        });
        if (!!dateBasedStart) {
            constraints.push({
                from: dateBasedStart,
                to: shiftDateArray(dateBasedStart, 50)
            });
        }
        return constraints;
    };
    var activateAvailableDates = function(mailingsMap) {
        var $picker = $("#date-picker");
        var dates = _.keys(mailingsMap).sort();
        if (dates.length) {
            var constraints = computeDisableConstraints(dates, mailingsMap);
            $picker.pickadate(_.merge({
                editable: true,
                disable: constraints,
                klass: {
                    input: "picker__input js-datepicker",
                    holder: "datepicker__holder picker__holder datepicker__holder-right"
                }
            }, Helpers.objFromString($picker.data("datepicker-options"))));
            var picker = $picker.pickadate("picker");
            if (!picker.get("select")) {
                picker.set("select", strDateToArray(minDay()));
            }
        } else {
            $picker.pickadate({
                editable: false
            });
        }
        $picker.trigger("change");
    };
    function init(config) {
        $saveButton = $("#save-button");
        $priorityCount = $("#priorityCount");
        $orderedArea = $("#ordered-area");
        $unorderedDateBasedArea = $("#datebased-container");
        $unorderedNormalArea = $("#normal-container");
        mailingsMap = config.mailingsMap;
        createEntry = Template.prepare("draggable-mailing-entry");
    }
    this.addDomInitializer("mailing-priorities", function() {
        var self = this;
        init(self.config);
        var $container = $(".l-content-area");
        $(".priority-container").sortable({
            opacity: .4,
            connectWith: ".priority-container",
            items: ".l-mailing-entry",
            helper: "clone",
            containment: $container,
            appendTo: $container,
            update: function() {
                if (this.id === $orderedArea.attr("id")) {
                    updateBadges();
                    checkOriginChanges();
                }
            },
            out: function() {
                highlightBackground($(this), false);
            },
            over: function(e, ui) {
                highlightBackground($(e.target), false);
                highlightBackground($(this), true);
            },
            start: function() {
                highlightBackground($(this), true);
            },
            stop: function() {
                highlightBackground($(this), false);
            },
            receive: function(e, ui) {
                var mailingType = ui.item.data("type");
                var targetId = e.target.id;
                if (!isAppropriateType(targetId, mailingType)) {
                    ui.sender.sortable("cancel");
                }
            }
        });
        activateAvailableDates(mailingsMap);
    });
    this.addAction({
        click: "back"
    }, function() {
        window.history.back();
    });
    this.addAction({
        click: "save"
    }, function() {
        var form = AGN.Lib.Form.get(this.el);
        form.setValueOnce("prioritizedIds", collectPrioritizedIds());
        form.submit();
    });
    this.addAction({
        change: "priorityCount"
    }, function() {
        checkOriginChanges();
    });
    this.addAction({
        change: "change-date"
    }, function() {
        var d = this.el.pickadate("picker").get("select");
        if (d) {
            select(arrayDateToStr([ d.year, d.month, d.date ]));
        } else {
            select();
        }
    });
});

AGN.Lib.Controller.new("reference-content-settings", function() {
    var Template = AGN.Lib.Template;
    var isAvailable = false;
    var disable = false;
    var createItemHtml;
    var items = [];
    var initialItems = [];
    var $form;
    function setEnabled(enabled) {
        $("#tile-mailingReferenceContent").toggleClass("hidden", !enabled);
    }
    function selectTable() {
        var $select = $("#referenceTableSelect");
        var $option = $select.children("option:selected");
        $("#keyColumnText").val($option.exists() ? $option.data("key-column") : "");
    }
    function createItem(index, value) {
        return $(createItemHtml({
            name: "Item" + index,
            value: value,
            disable: disable
        }));
    }
    function addItem(value) {
        var $item = createItem(items.length + 1, value);
        $("#reference-content-items").append($item);
        items.push($item);
    }
    this.addDomInitializer("reference-content-settings", function() {
        $form = $("#mailingSettingsForm");
        selectTable();
        createItemHtml = Template.prepare("mailing-reference-content-item");
        isAvailable = this.config.isAvailable;
        disable = this.config.disable;
        items = [];
        if (isAvailable) {
            if ($.isArray(this.config.items)) {
                this.config.items.forEach(function(value) {
                    addItem(value);
                });
                initialItems = this.config.items.slice();
            }
            setEnabled(this.config.isEnabled);
        } else {
            setEnabled(false);
        }
        $form.dirty("setAsClean");
        $form.dirty("refreshEvents");
    });
    this.addAction({
        change: "enable-reference-content"
    }, function() {
        if (isAvailable) {
            setEnabled(this.el.prop("checked"));
        } else {
            AGN.Lib.Messages(t("defaults.warning"), t("mailing.default.item_referencetable_warning"), "warning");
            $(this.el).prop("checked", false).trigger("change.dirty");
        }
    });
    this.addAction({
        change: "select-reference-table"
    }, function() {
        selectTable();
    });
    this.addAction({
        click: "add-reference-content-item"
    }, function() {
        addItem("");
        $form.dirty("setAsDirty");
    });
    this.addAction({
        click: "delete-reference-content-item"
    }, function() {
        var row = this.el.closest(".form-group")[0];
        var position = items.findIndex(function($row) {
            return $row[0] == row;
        });
        while (position + 1 < items.length) {
            var $input1 = items[position].find("input");
            var $input2 = items[position + 1].find("input");
            $input1.val($input2.val());
            position++;
        }
        items[position].remove();
        items.pop();
        var isTheSameItems = initialItems.length === items.length && initialItems.every(function(value) {
            return items.includes(value);
        });
        if (!isTheSameItems) {
            $form.dirty("setAsDirty");
        }
    });
});

AGN.Lib.Controller.new("mailing-send", function() {
    const Form = AGN.Lib.Form, Modal = AGN.Lib.Modal, Confirm = AGN.Lib.Confirm, Page = AGN.Lib.Page, Template = AGN.Lib.Template;
    const RECIPIENT_TEST_RUN_OPTION = "RECIPIENT";
    const TARGET_TEST_RUN_OPTION = "TARGET";
    const SEND_TO_SELF_TEST_RUN_OPTION = "SEND_TO_SELF";
    const Helpers = {
        disableSendButtons: function() {
            $("#test-send-controls-group #adminSendButton").addClass("disabled");
            $("#test-send-controls-group #testSendButton").addClass("disabled");
        },
        enableSendButtons: function() {
            $("#test-send-controls-group #adminSendButton").removeClass("disabled");
            $("#test-send-controls-group #testSendButton").removeClass("disabled");
        },
        hideGreenMarks: function() {
            $(".transmission-mark").remove();
            $("#recipient-add-btn, .recipient-remove-btn").removeClass("hidden");
        },
        updateWorkStatus: function(workStatus, tooltip) {
            const $statusIcon = $(Template.text("mailing-workstatus-icon", {
                workstatus: workStatus,
                tooltip: tooltip
            }));
            $("#workstatus-icon").replaceWith($statusIcon);
        }
    };
    this.addAction({
        click: "configure-delivery-mailing-size-warning"
    }, function() {
        const $e = this.el;
        Confirm.createFromTemplate({}, "warning-mailing-size-modal").done(function() {
            $e.prop("disabled", true);
            Page.reload($e.data("url"));
        });
    });
    this.addAction({
        click: "configure-delivery-mailing-size-error"
    }, function() {
        Modal.createFromTemplate({}, "error-mailing-size-modal");
    });
    this.addAction({
        click: "resume-sending"
    }, function() {
        const $e = this.el;
        const link = $e.data("link");
        const jqxhr = $.post(link);
        jqxhr.done(function(resp) {
            Page.render(resp);
            $e.closest(".form-group").remove();
        });
    });
    this.addAction({
        click: "configure-delivery"
    }, function() {
        this.el.prop("disabled", true);
        Page.reload(this.el.data("url"), true);
        this.el.prop("disabled", false);
    });
    this.addAction({
        click: "start-delivery"
    }, function() {
        if ($("#test-run-options").val() == RECIPIENT_TEST_RUN_OPTION) {
            var isTestRecipientsRequired = true;
            $('input[name="mailingTestRecipients"]').each(function() {
                const address = $(this).val();
                if (address && address.trim()) {
                    isTestRecipientsRequired = false;
                }
            });
            if (isTestRecipientsRequired) {
                AGN.Lib.Messages(t("defaults.error"), t("error.enterEmailAddresses"), "alert");
                return;
            }
        }
        Helpers.disableSendButtons();
        const form = Form.get(this.el);
        form.setActionOnce(this.el.data("url"));
        form.submit();
    });
    this.addAction({
        click: "recipients-row-remove"
    }, function() {
        var emailAddresses, $emailAddressFields, $row = this.el.closest("tr"), $emailAddresses = $('[name="statusmailRecipients"]');
        $row.remove();
        $emailAddressFields = $('[name^="statusmailRecipient_"]');
        emailAddresses = _.map($emailAddressFields, function(field) {
            return $(field).val();
        });
        $emailAddresses.val(emailAddresses.join(" "));
        Form.get(this.el).submit();
    });
    this.addAction({
        click: "recipients-row-add",
        keydown: "recipients-row-field"
    }, function() {
        if (this.event.type == "keydown" && this.event.keyCode != 13) {
            return;
        }
        var emailAddresses, $email = $("#newStatusMail"), $emailAddressFields = $('[name^="statusmailRecipient_"]'), $emailAddresses = $('[name="statusmailRecipients"]');
        emailAddresses = _.map($emailAddressFields, function(field) {
            return $(field).val();
        });
        emailAddresses.push($email.val());
        $emailAddresses.val(emailAddresses.join(" "));
        Form.get(this.el).submit().done(function() {
            $("#newStatusMail").trigger("focus");
        });
    });
    this.addInitializer("statusmailRecipients", function($scope) {
        var emailAddresses, $emailAddresses = $('[name="statusmailRecipients"]'), $target = $("#statusEmailContainer");
        $(".js-recipients-row").remove();
        if ($emailAddresses.val() == "") {
            return;
        }
        emailAddresses = $emailAddresses.val() || "";
        emailAddresses = emailAddresses.split(" ");
        _.each(emailAddresses, function(email) {
            if (email == "") {
                return;
            }
            $target.prepend(Template.text("recipients-row", {
                email: email
            }));
        });
    });
    this.addDomInitializer("delivery-status-view", function() {
        if (!this.config.isTransmissionRunning) {
            Helpers.hideGreenMarks();
        }
        const workStatus = this.config.workStatus;
        const workStatusTooltip = this.config.workStatusTooltip;
        if (workStatus && workStatusTooltip) {
            Helpers.updateWorkStatus(workStatus, workStatusTooltip);
        }
    });
    this.addAction({
        click: "add-test-recipient",
        enterdown: "new-test-recipient"
    }, function() {
        this.event.preventDefault();
        const $currentRow = this.el.closest("tr");
        const $currentInput = this.el.is("input") ? this.el : $currentRow.find("input");
        const $newRow = Template.dom("test-recipient-row", {
            value: $currentInput.val() || ""
        });
        $currentRow.before($newRow);
        $currentInput.val("");
        AGN.runAll($newRow);
        $currentInput.focus();
        changeSaveTestRunTargetBtnState(false);
    });
    this.addAction({
        input: "new-test-recipient"
    }, function() {
        changeSaveTestRunTargetBtnState(false);
    });
    this.addAction({
        input: "edit-test-recipient",
        enterdown: "edit-test-recipient"
    }, function() {
        this.event.preventDefault();
        changeSaveTestRunTargetBtnState(false);
    });
    this.addAction({
        input: "edit-test-run-target-name"
    }, function() {
        changeSaveTestRunTargetBtnState(false);
    });
    this.addAction({
        enterdown: "edit-test-run-target-name"
    }, function() {
        this.event.preventDefault();
    });
    this.addAction({
        click: "remove-test-recipient"
    }, function() {
        const $tr = this.el.closest("tr");
        $tr.remove();
        changeSaveTestRunTargetBtnState(false);
    });
    var approvalOptions;
    this.addDomInitializer("test-run-recipients", function() {
        approvalOptions = JSON.parse(this.config ? this.config.approvalOptions : "[]");
        controlTestRunOptionsDisplaying();
        $("#get-approval-switch").on("change", function() {
            controlTestRunOptionsDisplaying();
        });
        controlTestRunRecipientsDisplaying();
        $("#test-run-options").on("change", function() {
            controlTestRunRecipientsDisplaying();
        });
    });
    function controlTestRunOptionsDisplaying() {
        const filterOptions = $("#get-approval-switch").prop("checked");
        const $optionsSelect = $("#test-run-options");
        $optionsSelect.find("option:not([value='" + approvalOptions.join("']):not([value='") + "']").attr("disabled", filterOptions);
        if (filterOptions && approvalOptions.indexOf($optionsSelect.val()) === -1) {
            $optionsSelect.val($optionsSelect.find("option:not(:disabled):first").val()).trigger("change");
        }
    }
    function controlTestRunRecipientsDisplaying() {
        const $testRunDropdown = $("#test-run-options");
        if (!$testRunDropdown.length) {
            return;
        }
        const isSingleRecipientOption = $testRunDropdown.val() == RECIPIENT_TEST_RUN_OPTION;
        const isTargetIdRunOption = $testRunDropdown.val() == TARGET_TEST_RUN_OPTION;
        const isSendToSelfRunOption = $testRunDropdown.val() == SEND_TO_SELF_TEST_RUN_OPTION;
        const newTargetElementsHidden = !isSingleRecipientOption || !$("#save-target-toggle").prop("checked");
        $("#test-recipients-table").toggleClass("hidden", !isSingleRecipientOption);
        $("#adminSendButton").toggleClass("hidden", isSingleRecipientOption || isTargetIdRunOption || isSendToSelfRunOption);
        $("#testTargetSaveButton").toggleClass("hidden", newTargetElementsHidden);
        $("#test-run-target-name-input").toggleClass("hidden", newTargetElementsHidden);
        $("#adminTargetGroupSelect").prop("disabled", !isTargetIdRunOption);
        $("#test-recipients-table input").prop("disabled", !isSingleRecipientOption);
    }
    function changeSaveTestRunTargetBtnState(saved) {
        const $testRunTargetBtn = $("#testTargetSaveButton");
        const $btnIcon = $testRunTargetBtn.find("i");
        if (saved) {
            $btnIcon.hide();
        }
        $testRunTargetBtn.toggleClass("btn-primary", !saved, 500);
        $testRunTargetBtn.toggleClass("btn-success", saved, 500);
        if (saved) {
            $testRunTargetBtn.css({
                cursor: "not-allowed",
                "pointer-events": "none"
            });
        } else {
            $testRunTargetBtn.css({
                cursor: "",
                "pointer-events": ""
            });
        }
        $btnIcon.toggleClass("icon-save", !saved);
        $btnIcon.toggleClass("icon-check", saved);
        $btnIcon.show(500);
    }
    function isValidTestTargetNameField() {
        const $targetName = $('input[name="targetName"]');
        const errors = AGN.Lib.Validator.get("length").errors($targetName, {
            min: 3,
            required: true
        });
        const form = Form.get($targetName);
        if (!errors.length) {
            form.cleanErrors();
            return true;
        }
        errors.forEach(function(error) {
            form.showFieldError$($targetName, error.msg);
        });
        return false;
    }
    function saveTargetName() {
        $.ajax({
            type: "POST",
            url: AGN.url("/mailing/send/test/saveTarget.action"),
            data: {
                mailingTestRecipients: collectTestRunEmails(),
                targetName: $('input[name="targetName"]').val().trim()
            }
        }).done(function(resp) {
            if (resp.success === true) {
                changeSaveTestRunTargetBtnState(true);
            } else {
                AGN.Lib.JsonMessages(resp.popups);
            }
        });
    }
    this.addAction({
        click: "save-target-for-test-run"
    }, function() {
        if (!isValidTestTargetNameField()) {
            return;
        }
        saveTargetName();
    });
    function collectTestRunEmails() {
        return $('input[name="mailingTestRecipients"]').map(function() {
            return this.value.trim();
        }).get().filter(function(email) {
            return email;
        });
    }
    function initializeFormFields($form) {
        const form = AGN.Lib.Form.get($form);
        form.initFields();
    }
    this.addAction({
        change: "prioritization-toggle"
    }, function() {
        toggleButton($(this.el), "isPrioritizationDisallowed");
    });
    this.addAction({
        change: "encrypted-send-toggle"
    }, function() {
        toggleButton($(this.el), "isEncryptedSend");
    });
    this.addAction({
        change: "sendStatusOnErrorOnly-toggle"
    }, function() {
        toggleButton($(this.el), "statusOnErrorEnabled");
    });
    function toggleButton($toggle, propertyName) {
        const isChecked = $toggle.prop("checked");
        $toggle.prop("disabled", true);
        function failed() {
            $toggle.prop("checked", !isChecked);
            AGN.Lib.Messages(t("defaults.error"), t("defaults.error"), "alert");
        }
        const data = {};
        data[propertyName] = $toggle.is(":checked");
        $.ajax({
            type: "POST",
            url: $toggle.data("url"),
            data: data
        }).done(function(resp) {
            if (resp && resp.success) {
                AGN.Lib.Messages(t("defaults.success"), t("defaults.saved"), "success");
            } else {
                failed();
            }
        }).fail(failed).always(function() {
            $toggle.prop("disabled", false);
        });
    }
    AGN.Lib.Controller.new("mailing-deletion-modal", function() {
        this.addDomInitializer("mailing-deletion-modal", function() {
            this.el.find(".js-confirm-positive").on("click", function() {
                const $deliveryStatusBox = $("#delivery-status-box");
                if ($deliveryStatusBox.exists()) {
                    AGN.Lib.Load.get($deliveryStatusBox).stop();
                }
            });
        });
    });
});

AGN.Lib.Controller.new("delivery-settings-view", function() {
    this.addDomInitializer("delivery-settings-view", function() {
        var decimalSeparator;
        if (this.config.adminLocale === "en_US") {
            decimalSeparator = ",";
        } else {
            decimalSeparator = ".";
        }
        const $maxRecipients = $("#maxRecipients");
        $maxRecipients.val("");
        $maxRecipients.focusout(function() {
            if ($(this).val() === "0") {
                $maxRecipients.val("");
            }
        });
        $("#sendBtn").mousedown(function() {
            if ($maxRecipients.val() === "") {
                $maxRecipients.val("0");
            }
        });
        _.each($(".commaSplitLabel"), function(elem) {
            const $e = $(elem);
            const separatedText = $e.text().replace(/\B(?=(\d{3})+(?!\d))/g, decimalSeparator);
            $e.text(separatedText);
        });
    });
});

AGN.Lib.Controller.new("mailing-settings-view", function() {
    var Form = AGN.Lib.Form;
    var scrollOffset = 0;
    var config;
    var isChangeMailing = false;
    var targetGroupIds = [];
    var mailingListSelect;
    var lastMailingListId = 0;
    var lastDataForCountingRecipients;
    var mediaTypePriorityChanged = false;
    var refreshTargetModeLabel = function() {
        var $targetModeDesc = $("#target-mode-desc");
        if ($("[name='targetMode']:checked").val() == config.TARGET_MODE_OR) {
            $targetModeDesc.text(t("mailing.default.targetmode_or"));
        } else {
            $targetModeDesc.text(t("mailing.default.targetmode_and"));
        }
    };
    var collectMailingParams = function() {
        var $table = $("#mailingParamsTable tbody");
        if ($table && $table.length) {
            return _.map($table.find("[data-param-row]"), function(row) {
                var $row = $(row);
                return {
                    name: getParamValInRowByCol($row, "name"),
                    value: getParamValInRowByCol($row, "value"),
                    description: getParamValInRowByCol($row, "description")
                };
            }).filter(function(param) {
                return param.name || param.value || param.description;
            });
        }
        return [];
    };
    const updateCharCounter = function($el) {
        if (!$el.length) {
            return;
        }
        const count = $el.val().length;
        $('[data-char-counter-for="' + $el.attr("id") + '"]').find("span:first").text(t("fields.content.charactersEntered", count));
    };
    this.addDomInitializer("mailing-settings-view", function() {
        config = this.config;
        targetGroupIds = $("#targetGroupIds").val() || [];
        $("#targetModeAndBtn").closest(".form-group").toggle(targetGroupIds.length > 1);
        mailingListSelect = $("#settingsGeneralMailingList");
        mailingListSelect.select2("readonly", false);
        if (lastMailingListId > 0) {
            lastMailingListId = mailingListSelect.select2("val", lastMailingListId);
        }
        if (config.selectedRemovedMailinglistId) {
            showRemovedMailinglistError();
        }
        updateGeneralMailingTypeView(config.mailingType);
        if (!config.isMailingGrid || config.mailingId || config.isCopying) {
            redrawMediatypeTiles();
        }
        configureFormChangesTracking();
        refreshTargetModeLabel();
        scrollPage();
        if ($("#email-tile").length) {
            updateCharCounter($("#emailSubject"));
            updateCharCounter($("#pre-header"));
        }
        AGN.Opt.collectMailinParams = collectMailingParams;
    });
    function showRemovedMailinglistError() {
        var form = Form.get($("#mailingSettingsForm"));
        form.showFieldError("mailinglistId", t("fields.mailinglist.errors.removed"), true);
    }
    function scrollPage() {
        if (scrollOffset > 0) {
            var wrapper = $("#gt-wrapper");
            if (wrapper.exists()) {
                wrapper.animate({
                    scrollTop: scrollOffset
                }, 50);
            } else {
                $(document).scrollTop(scrollOffset + 50);
            }
        } else {
            var shortname = $("#mailingSettingsForm").find('[name="shortname"]');
            if ($(shortname).exists()) {
                $(shortname).focus();
            }
        }
        scrollOffset = 0;
    }
    function isDirtyOnlyNonEditableFields($form) {
        var dirtyFields = $form.dirty("showDirtyFields");
        if (dirtyFields.length > 0) {
            var filtered = dirtyFields.filter(function(_, e) {
                var $el = $(e);
                return !($el.prop("readonly") === true || $el.is(":disabled") || $el.prop("type") === "hidden");
            });
            return filtered.length === 0;
        } else {
            return false;
        }
    }
    function configureFormChangesTracking() {
        const $form = $("#mailingSettingsForm");
        $form.dirty("destroy");
        $form.dirty({
            preventLeaving: true,
            leavingMessage: t("grid.layout.leaveQuestion"),
            onDirty: function() {
                if (isDirtyOnlyNonEditableFields($form) && !mediaTypePriorityChanged) {
                    $form.dirty("setAsClean");
                }
            }
        });
        if (isDirtyOnlyNonEditableFields($form) && !mediaTypePriorityChanged) {
            $form.dirty("setAsClean");
        }
        mediaTypePriorityChanged = false;
    }
    window.onbeforeunload = function() {
        if (!$("#mailingSettingsForm").dirty("isDirty") === true) {
            AGN.Lib.Loader.show();
        }
    };
    this.addAction({
        change: "selectTargetGroups"
    }, function() {
        var ids = this.el.val() || [];
        var $mode = $("#targetModeAndBtn");
        var $modeControls = $mode.closest(".form-group");
        if (ids.length > 1 && targetGroupIds.length <= 1) {
            $mode.prop("checked", true);
        }
        $modeControls.toggle(ids.length > 1);
        targetGroupIds = ids;
    });
    function getFieldsData(selectors) {
        var data = {};
        selectors.forEach(function(selector) {
            var $input = $(selector);
            if ($input.exists() && $input.closest(".form-group").is(":visible") && !$input.prop("disabled")) {
                var name = $input.prop("name");
                var value = $input.val();
                if (name) {
                    data[name] = value;
                }
            }
        });
        return data;
    }
    this.addAction({
        click: "calculateRecipients"
    }, function() {
        if (config) {
            lastDataForCountingRecipients = getDataForCountingRecipients();
            $.ajax({
                type: "POST",
                url: AGN.url("/mailing/ajax/" + config.mailingId + "/calculateRecipients.action"),
                traditional: true,
                data: lastDataForCountingRecipients
            }).always(function(resp) {
                if (resp && resp.success === true) {
                    setRecipientsCountValue(resp.count);
                } else {
                    setRecipientsCountValue("?");
                    AGN.Lib.Messages(t("defaults.error"), t("defaults.error"), "alert");
                }
            });
        }
    });
    this.addAction({
        change: "change-mailing-settings"
    }, function() {
        isChangeMailing = true;
        resetRecipientsCountIfNecessary();
    });
    function resetRecipientsCountIfNecessary() {
        if (!lastDataForCountingRecipients) {
            return;
        }
        const actualDataForCountingRecipients = getDataForCountingRecipients();
        if (!_.isEqual(actualDataForCountingRecipients, lastDataForCountingRecipients)) {
            lastDataForCountingRecipients = null;
            setRecipientsCountValue("?");
        }
    }
    function getDataForCountingRecipients() {
        const fields = [ "#settingsGeneralMailingList", "#settingsTargetgroupsListSplit", "#settingsTargetgroupsListSplitPart", "#lightWeightMailingList", "#assignTargetGroups", "#targetGroupIds", "#altgIds", "#followUpType" ];
        return $.extend(getFieldsData(fields), {
            changeMailing: isChangeMailing,
            targetMode: $('[name="targetMode"]:checked').val(),
            isWmSplit: config.wmSplit
        });
    }
    function setRecipientsCountValue(value) {
        const $count = $("#calculatedRecipientsBadge");
        $count.text(value);
    }
    this.addAction({
        change: "set-parent-mail-mailinglist"
    }, function() {
        setMailingListSelectByFollowUpMailing();
    });
    this.addAction({
        change: "scroll-to"
    }, function() {
        var position = getPosition(this.el);
        scrollOffset = Math.round(position);
    });
    function getPosition($e) {
        var $tile = $e.closest(".tile");
        if ($tile.exists()) {
            return $tile.position().top;
        } else {
            return $e.position().top;
        }
    }
    this.addAction({
        change: "change-general-mailing-type"
    }, function() {
        var self = this;
        var mailingType = self.el.val();
        mailingListSelect.select2("readonly", false);
        if (lastMailingListId > 0) {
            mailingListSelect.select2("val", lastMailingListId);
        }
        updateGeneralMailingTypeView(mailingType);
    });
    this.addAction({
        change: "save-mailing-list-id"
    }, function() {
        const mailinglistId = this.el.select2("val");
        const mailingType = $("#settingsGeneralMailType").val();
        if (!isFollowUpMailing(mailingType)) {
            lastMailingListId = mailinglistId;
        }
        if (config.selectedRemovedMailinglistId) {
            mailingListSelect.find('option[value="' + config.selectedRemovedMailinglistId + '"]').remove();
            var form = Form.get($(this.el));
            form.cleanFieldError("mailinglistId");
        }
        if (config.allowedMailinglistsAddresses) {
            const mailinglistData = config.mailinglists.find(function(data) {
                return data.id == mailinglistId;
            });
            if (mailinglistData) {
                if (mailinglistData.senderEmail) {
                    $("#emailSenderMail").val(mailinglistData.senderEmail).trigger("change");
                }
                if (mailinglistData.replyEmail) {
                    $("#emailReplyEmail").val(mailinglistData.replyEmail);
                }
                if (mailinglistData.senderEmail && mailinglistData.replyEmail) {
                    AGN.Lib.Messages(t("defaults.info"), t("mailing.default.sender_and_reply_emails_changed"), "info");
                } else if (mailinglistData.senderEmail) {
                    AGN.Lib.Messages(t("defaults.info"), t("mailing.default.sender_email_changed"), "info");
                } else if (mailinglistData.replyEmail) {
                    AGN.Lib.Messages(t("defaults.info"), t("mailing.default.reply_email_changed"), "info");
                }
            }
        }
    });
    this.addAction({
        change: "change-target-mode"
    }, refreshTargetModeLabel);
    function setMailingListSelectByFollowUpMailing() {
        var selectedParentMailingId = $("#lightWeightMailingList").val();
        var selectedParentMailingMailingListId = $("#parentmailing-" + selectedParentMailingId + "-mailinglist").attr("data-mailing-list-id");
        mailingListSelect.select2("val", selectedParentMailingMailingListId);
        mailingListSelect.select2("readonly", true);
    }
    var isFollowUpMailing = function(mailingType) {
        return config.FOLLOWUP_MAILING_TYPE == mailingType;
    };
    var isActionBasedMailing = function(mailingType) {
        return config.ACTIONBASED_MAILING_TYPE == mailingType;
    };
    var isDateBasedMailing = function(mailingType) {
        return config.DATEBASED_MAILING_TYPE == mailingType;
    };
    function updateGeneralMailingTypeView(mailingType) {
        var showFollowUpControls = false;
        if (config.followUpAllowed) {
            if (isFollowUpMailing(mailingType)) {
                setMailingListSelectByFollowUpMailing();
                showFollowUpControls = true;
            }
            toggle(showFollowUpControls, "#followUpControls");
        }
        toggle(isDateBasedMailing(mailingType), "#mailing-bcc-recipients");
        var showTargetGroups = isActionBasedMailing(mailingType) ? config.campaignEnableTargetGroups : true;
        toggle(showTargetGroups, "#mailingTargets");
    }
    function toggle(show, selector) {
        var container = $(selector);
        if (container) {
            if (show) {
                container.removeClass("hidden");
                container.show();
            } else {
                container.hide();
            }
        }
    }
    this.addAction({
        change: "change-mediatype"
    }, function() {
        var $el = $(this.el);
        var active = isMediatypeListElemActive($el);
        redrawMediatypeCheckboxes($el, active);
        redrawMediatypeTiles();
    });
    function isMediatypeListElemActive($el) {
        return $el.find("input:checkbox:first").is(":checked");
    }
    function prioritizeMediatypeCheckboxes() {
        var checkboxesContainer = $("#tile-mediaTypes").find(".list-group");
        var checkboxes = getSortedMediatypeCheckboxes();
        checkboxesContainer.empty();
        checkboxes.forEach(function(item) {
            checkboxesContainer.append(item);
        });
    }
    function getSortedMediatypeCheckboxes() {
        return $("#tile-mediaTypes").find(".list-group li").toArray().sort(function(a, b) {
            var $a = $(a);
            var $b = $(b);
            if (!isMediatypeListElemActive($a) && isMediatypeListElemActive($b)) return 1;
            if (isMediatypeListElemActive($a) && !isMediatypeListElemActive($b)) return -1;
            return $a.data("priority") - $b.data("priority");
        });
    }
    function redrawMediatypeCheckboxes($el, active) {
        prioritizeMediatypeCheckboxes();
        displayArrows($el, active);
    }
    function removeEmailTileIfNecessary() {
        if (config.isMailingGrid) {
            return;
        }
        const $emailCheckboxItem = $("#tile-mediaTypes").find('[data-mediatype="email"]');
        if (!isMediatypeListElemActive($emailCheckboxItem)) {
            $("#frame-tile").remove();
            $("#email-tile").remove();
        }
    }
    function renderEmailTileIfNotExists() {
        const tilesExist = $("#frame-tile").length && $("#email-tile").length;
        if (!tilesExist) {
            const $emailTile = $("#email-tile-template").html();
            const $frameTile = $("#frame-tile-template").html();
            const $baseInfoTile = $("#base-info-tile");
            $baseInfoTile.after($emailTile);
            $baseInfoTile.after($frameTile);
        }
    }
    function redrawMediatypeTiles() {
        renderEmailTileIfNotExists();
        removeEmailTileIfNecessary();
        var $mediatypesTile = $("#mediatypes-tile");
        $("#tile-mediaTypes").find(".list-group li").toArray().filter(function(el) {
            return $(el).data("mediatype") !== "email" && $(el).data("mediatype") !== "post";
        }).reverse().forEach(function(el) {
            var $el = $(el);
            var mediatype = $el.data("mediatype");
            $("#" + mediatype + "-tile").remove();
            if (isMediatypeListElemActive($el)) {
                var $tile = AGN.Lib.Template.dom(mediatype + "-tile-template");
                $mediatypesTile.after($tile);
            }
        });
        AGN.Lib.Form.get($("#mailingSettingsForm")).initFields();
        AGN.Lib.CoreInitializer.run("tab-toggle");
        AGN.Lib.CoreInitializer.run("ace");
        AGN.Lib.CoreInitializer.run("select");
    }
    function displayArrows($el, active) {
        if (active) {
            $el.find("label").after("          <div class='list-group-item-controls'>              <a href='#' data-action='prioritise-mediatype-down'>                <i class='icon icon-chevron-circle-down'></i>              </a>              <a href='#' data-action='prioritise-mediatype-up'>               <i class='icon icon-chevron-circle-up'></i>              </a>          </div>      ");
        } else {
            $el.find(".list-group-item-controls").remove();
        }
    }
    this.addAction({
        click: "prioritise-mediatype-up"
    }, function() {
        prioritiseMediatypes($(this.el).closest("li"), true);
    });
    this.addAction({
        click: "prioritise-mediatype-down"
    }, function() {
        prioritiseMediatypes($(this.el).closest("li"), false);
    });
    function moveMediatypeUp($current) {
        var $prev = $current.prev();
        var currentPriority = $current.attr("data-priority");
        $current.attr("data-priority", $prev.attr("data-priority"));
        $prev.attr("data-priority", currentPriority);
        $prev.before($current);
    }
    function moveMediatypeDown($current) {
        var $next = $current.next();
        var currentPriority = $current.attr("data-priority");
        $current.attr("data-priority", $next.attr("data-priority"));
        $next.attr("data-priority", currentPriority);
        $next.after($current);
    }
    function isMediatypeCanBeMoved($el, up) {
        return up && $el.prev().length || !up && $el.next().length && isMediatypeListElemActive($el.next());
    }
    function prioritiseMediatypes($el, up) {
        var $form = Form.getWrapper($el);
        mediaTypePriorityChanged = true;
        if (isMediatypeCanBeMoved($el, up)) {
            if (up) {
                moveMediatypeUp($el);
            } else {
                moveMediatypeDown($el);
            }
            $form.dirty("setAsDirty");
            redrawMediatypeTiles();
        }
    }
    this.addAction({
        submission: "save"
    }, function() {
        const form = Form.get(this.el);
        $("#tile-mediaTypes").find(".list-group li").toArray().forEach(function(el) {
            const $el = $(el);
            const mediatype = $el.data("mediatype");
            form.setValueOnce(mediatype + "Mediatype.priority", $el.data("priority"));
        });
        setParamsToForm(form);
        form.submit();
    });
    function setParamsToForm(form) {
        _.each(collectMailingParams(), function(param, index) {
            form.setValueOnce("params[" + index + "].name", param.name);
            form.setValueOnce("params[" + index + "].value", param.value);
            form.setValueOnce("params[" + index + "].description", param.description);
        });
    }
    function getParamValInRowByCol($row, col) {
        return $row.find("[data-param-" + col + "]").val();
    }
    this.addAction({
        input: "count-text-chars",
        textarea: "count-text-chars",
        "editor:create": "count-textarea-chars",
        "editor:change": "count-textarea-chars"
    }, function() {
        updateCharCounter(this.el);
    });
});

AGN.Lib.Controller.new("mailing-styles", function() {
    function updatePreview() {
        const $mailingForm = $("form#mailingStylesForm");
        const $previewForm = $("form#mailingPreviewForm");
        const $sources = $mailingForm.find('input[name^="styles["]');
        $.each($sources, function(index, source) {
            const $source = $(source);
            const name = $source.attr("name");
            const $destination = $previewForm.find('input[name="' + name + '"]');
            $destination.val($source.val());
        });
        $previewForm.submit();
    }
    this.addAction({
        submission: "updatePreview"
    }, function() {
        updatePreview();
    });
    this.addAction({
        click: "updateMailingPreview"
    }, function() {
        updatePreview();
    });
    this.addAction({
        click: "saveMailingStyles"
    }, function() {
        $("form#mailingStylesForm").submit();
    });
});

AGN.Lib.Controller.new("mailinglist-list", function() {
    var config = null;
    function getTableApi() {
        var $table = $(".js-data-table-body");
        if ($table.exists()) {
            var table = $table.data("_table");
            if (table && table.api) {
                return table.api;
            }
        }
        return null;
    }
    function requestBulkDelete(ids) {
        var deferred = $.Deferred();
        if (ids && ids.length) {
            var jqxhr = $.ajax(config.urls.MAILINGLIST_BULK_DELETE, {
                method: "POST",
                traditional: true,
                data: {
                    bulkIds: ids
                }
            }).fail(function() {
                deferred.reject();
            });
            AGN.Lib.Confirm.request(jqxhr).done(function(resp) {
                AGN.Lib.Page.render(resp);
            }).then(deferred.resolve, deferred.reject);
        } else {
            deferred.reject();
            AGN.Lib.Messages(t("Error"), t("messages.error.nothing_selected"), "alert");
        }
        return deferred.promise();
    }
    this.addDomInitializer("mailinglist-list", function() {
        config = this.config;
    });
    this.addAction({
        click: "bulk-delete"
    }, function() {
        var api = getTableApi();
        if (api) {
            var rows = api.getSelectedRows();
            var ids = rows.map(function(row) {
                return row.id;
            });
            requestBulkDelete(ids).done(function() {
                api.updateRowData({
                    remove: rows
                });
            });
        }
    });
});

AGN.Lib.Controller.new("manage-table-import", function() {
    const Form = AGN.Lib.Form;
    var NEW_COLUMN_FORMAT = "#new-default-column-format";
    var NEW_COLUMN_VALUE = "#new-default-column-value";
    var NEW_COLUMN_ENCRYPTED = "#new-default-column-encrypted";
    var MAPPING_ROW = ".manage-tables-mapping-row";
    var Template = AGN.Lib.Template;
    var config = null;
    var $columnMappingsTable;
    var columnMappingRowTemplate;
    this.addDomInitializer("manage-table-import", function() {
        config = this.config;
        renderMappings(config.mappings);
    });
    this.addAction({
        click: "add-default-column"
    }, function() {
        var currentCount = $(MAPPING_ROW).length;
        var formatInputValue = $(NEW_COLUMN_FORMAT).val(), defaultInputValue = $(NEW_COLUMN_VALUE).val(), encryptedInputChecked = !!$(NEW_COLUMN_ENCRYPTED).prop("checked"), valueType = $("#new-default-column-type").val();
        if ("value" === valueType && !(defaultInputValue.startsWith("'") && defaultInputValue.endsWith("'"))) {
            defaultInputValue = "'" + defaultInputValue + "'";
        }
        var $rowTemplate = Template.dom("manage-tables-import-row", {
            index: currentCount,
            targetColumns: config.importColumns,
            format: formatInputValue,
            value: defaultInputValue,
            encrypted: encryptedInputChecked
        });
        $("#manage-tables-tbody").append($rowTemplate);
        $(NEW_COLUMN_FORMAT).val("");
        $(NEW_COLUMN_VALUE).val("");
        $(NEW_COLUMN_ENCRYPTED).prop("checked", false);
    });
    this.addAction({
        click: "delete-mapping-row"
    }, function() {
        var $el = this.el, $row = $el.parents(MAPPING_ROW), $tbody = $el.parents("tbody");
        $row.remove();
        recalculateMappingIndexes($tbody.find(MAPPING_ROW));
    });
    this.addAction({
        click: "create-mapping"
    }, function() {
        const form = Form.get(this.el);
        $.ajax(config.urls.CREATE_MAPPINGS, {
            type: "POST",
            dataType: "json",
            enctype: "multipart/form-data",
            processData: false,
            contentType: false,
            data: form.data()
        }).done(function(resp) {
            if (resp.success === true) {
                renderMappings(resp.data);
                AGN.Lib.JsonMessages(resp.popups);
            } else {
                AGN.Lib.JsonMessages(resp.popups);
            }
        });
    });
    this.addAction({
        click: "import-data"
    }, function() {
        const url = this.el.data("url");
        const form = Form.get($("#form"));
        form.setActionOnce(url);
        submitForm(form);
    });
    function renderMappings(mappings) {
        $columnMappingsTable = $("#manage-tables-tbody");
        $columnMappingsTable.html("");
        columnMappingRowTemplate = Template.prepare("column-mapping-table-row");
        for (var colIndex = 0; colIndex < mappings.length; colIndex++) {
            const mapping = mappings[colIndex];
            appendRowToColumnMappingTable(colIndex, mapping.id, mapping.sourceColumn, mapping.targetColumn, mapping.mandatory, mapping.encrypted, mapping.format, mapping.defaultValue);
        }
    }
    function collectMappingsDataFromTable() {
        if (!$columnMappingsTable || !$columnMappingsTable.length) {
            return [];
        }
        return _.map($columnMappingsTable.find("[data-mapping-row]"), function(row) {
            const $row = $(row);
            return {
                sourceColumn: getMappingValueInRowByCol($row, "fileColumn"),
                targetColumn: getMappingValueInRowByCol($row, "db-column"),
                mandatory: getMappingValueInRowByCol($row, "mandatory"),
                encrypted: getMappingValueInRowByCol($row, "encrypted"),
                defaultValue: getMappingValueInRowByCol($row, "defaultValue"),
                format: getMappingValueInRowByCol($row, "format")
            };
        });
    }
    function getMappingValueInRowByCol($row, col) {
        const $input = $row.find("[data-mapping-" + col + "]");
        if ($input.is(":checkbox")) {
            return $input.is(":checked");
        }
        return $input.val();
    }
    function appendRowToColumnMappingTable(index, id, sourceColumn, targetColumn, mandatory, encrypted, format, defaultValue) {
        const $rowTemplate = columnMappingRowTemplate({
            index: index,
            id: id,
            fileColumn: sourceColumn,
            databaseColumn: targetColumn,
            mandatory: mandatory,
            encrypted: encrypted,
            format: format,
            defaultValue: defaultValue
        });
        $columnMappingsTable.append($rowTemplate);
        const $dbColumn = $('[data-mapping-row="' + index + '"]').find("[data-mapping-db-column]");
        AGN.Lib.CoreInitializer.run("select", $dbColumn);
    }
    this.addAction({
        submission: "save"
    }, function() {
        const form = Form.get(this.el);
        submitForm(form);
    });
    function submitForm(form) {
        _.each(collectMappingsDataFromTable(), function(mapping, index) {
            form.setValueOnce("mappings[" + index + "].sourceColumn", mapping.sourceColumn);
            form.setValueOnce("mappings[" + index + "].targetColumn", mapping.targetColumn);
            form.setValueOnce("mappings[" + index + "].mandatory", mapping.mandatory);
            form.setValueOnce("mappings[" + index + "].encrypted", mapping.encrypted);
            form.setValueOnce("mappings[" + index + "].defaultValue", mapping.defaultValue);
            form.setValueOnce("mappings[" + index + "].format", mapping.format);
        });
        form.submit();
    }
    function recalculateMappingIndexes($rows) {
        var currentIndex = 0;
        $rows.each(function() {
            var $row = $(this);
            var $columns = $row.find('[name*="mappings["]');
            $columns.each(function() {
                var $column = $(this);
                var attrValue = $column.attr("name");
                attrValue = attrValue.replace(/mappings\[\d+]/g, "mappings[" + currentIndex + "]");
                $column.attr("name", attrValue);
            });
            currentIndex++;
        });
    }
});

AGN.Lib.Controller.new("manage-tables-viewfield", function() {
    var previousValueNullableField = "true";
    this.addAction({
        change: "typeFieldChangeAction"
    }, function() {
        var $nullableEl = $("#nullable");
        if (this.el.val() === "DATE" || this.el.val() === "DATETIME") {
            previousValueNullableField = $nullableEl.val();
            $nullableEl.val("true");
        } else {
            $nullableEl.val(previousValueNullableField);
        }
    });
});

AGN.Lib.Controller.new("mediapool-element-category-select", function() {
    var Confirm = AGN.Lib.Confirm, Helpers = AGN.Lib.Helpers, Select = AGN.Lib.Select;
    this.addDomInitializer("mediapool-element-category-select", function($e) {
        var config = Helpers.objFromString($e.data("config"));
        if (config && config.categoryId) {
            Select.get($("#mediapool-file-category-id")).selectValueOrSelectFirst(config.categoryId);
        }
    });
    this.addAction({
        change: "selectCategory"
    }, function() {
        var $group = this.el.parents(".form-group");
        $group.removeClass("has-alert has-feedback js-form-error");
        $group.find(".js-form-error-msg").addClass("hidden");
    });
    this.addAction({
        click: "applyCategory"
    }, function() {
        var $select = $("#mediapool-file-category-id");
        var categoryId = parseInt($select.val());
        if (categoryId > 0) {
            Confirm.get(this.el).positive({
                categoryId: categoryId
            });
        } else {
            var $group = $select.parents(".form-group");
            $group.addClass("has-alert has-feedback js-form-error");
            $group.find(".js-form-error-msg").removeClass("hidden");
        }
    });
});

AGN.Lib.Controller.new("mediapool-overview", function() {
    var Helpers = AGN.Lib.Helpers;
    var Template = AGN.Lib.Template;
    var Confirm = AGN.Lib.Confirm;
    var Form = AGN.Lib.Form;
    var Page = AGN.Lib.Page;
    var config;
    var imagesMap;
    var imageToReplace;
    function showReplacementDialog(parameters) {
        var $modal = Template.dom("modal-replace-image", parameters);
        $modal.find("form").data("selected-file", parameters.file);
        if (parameters.preview) {
            $modal.find("#replacement-preview").prop("src", parameters.preview);
        }
        return Confirm.create($modal);
    }
    function setControlsEnabled($area, isEnabled) {
        $area.all("input, textarea, select, button").prop("disabled", !isEnabled);
    }
    function hideUpdateAllDataField() {
        $("#duplication-update-fields:not(.hidden)").addClass("hidden");
    }
    this.addDomInitializer("mediapool-overview", function() {
        imagesMap = {};
        config = this.config;
        this.config.imagesList.forEach(function(image) {
            imagesMap[image.id] = image;
        });
    });
    this.addAction({
        click: "replace-image"
    }, function() {
        var imageId = this.el.data("image-id");
        imageToReplace = imagesMap[imageId];
        if (imageToReplace) {
            var $img = $("#replacement-image");
            Helpers.clearFormField($img);
            $img.trigger("click");
        }
    });
    this.addAction({
        click: "toggle-overwrite-existing-data"
    }, function() {
        var el = this.el;
        var active = $(el).is(":checked");
        var checkboxes = $(el).closest("table").find('[data-action="change-overwriting-state"]');
        checkboxes.prop("checked", active);
        checkboxes.trigger("change");
    });
    this.addAction({
        change: "change-overwriting-state"
    }, function() {
        var $el = $(this.el);
        var active = $el.is(":checked");
        var newTitle = "";
        var newCategory = "";
        var index = parseInt($el.prop("id").replace("overwrite-", ""));
        var imageId = $('[name="images[' + index + '].id"]').val();
        if (active && imagesMap[imageId]) {
            var image = imagesMap[imageId];
            newTitle = image.title;
            newCategory = image.categoryId;
        }
        $("#image-title-" + index).val(newTitle);
        var $select = $("#image-category-id" + index);
        if ($select.data("select2")) {
            $select.select2("val", newCategory);
        }
        var unchecked = $('[id^="duplication-error-"]:not([hidden])').find('[id^="overwrite-"]:not(:checked)');
        $("#updateAllData").prop("checked", unchecked.length === 0);
    });
    this.addAction({
        change: "replacement-image"
    }, function() {
        hideUpdateAllDataField();
        var $file = this.el;
        var files = $file.prop("files");
        if (files && files.length && imageToReplace) {
            var reader = new FileReader();
            var file = files[0];
            reader.onload = function(e) {
                if (imageToReplace) {
                    showReplacementDialog({
                        image: imageToReplace,
                        file: file,
                        preview: e.target.result
                    });
                }
            };
            reader.readAsDataURL(file);
        }
    });
    this.addAction({
        "reset-upload": "mediapool-upload-image"
    }, function() {
        hideUpdateAllDataField();
    });
    this.addAction({
        "upload:add": "mediapool-upload-image"
    }, function() {
        var uploadData = this.data;
        var isAnyDuplicate = !$("#duplication-update-fields").hasClass("hidden");
        nameDuplicationCheckRequest(uploadData.file.name, function(data) {
            uploadData.file.id = data.data;
            isAnyDuplicate = !!data.data || isAnyDuplicate;
        });
        if (isAnyDuplicate) {
            $("#updateAllData").prop("checked", false);
            $("#duplication-update-fields").removeClass("hidden");
        }
    });
    function nameDuplicationCheckRequest(filename, success) {
        $.ajax(config.urls.VERIFY_IMAGE_URL, {
            data: JSON.stringify({
                imageName: filename
            }),
            contentType: "application/json",
            async: false,
            type: "POST",
            success: success
        });
    }
    this.addAction({
        submission: "submit-image-save"
    }, function() {
        var $form = this.el;
        var form = Form.get($form);
        var files = form._dataNextRequest;
        this.event.preventDefault();
        var i = 1;
        var success = true;
        for (key in files) {
            var newName = $("[name='images[" + i + "].fileName']").val();
            var overwrite = $("[id='overwrite-" + i + "']").is(":checked");
            nameDuplicationCheckRequest(newName, function(data) {
                if (data.data && !overwrite) {
                    success = false;
                    $("[name='images[" + i + "].id']").val(data.data);
                    $("[id='duplication-error-" + i + "']").removeAttr("hidden");
                } else if (!overwrite) {
                    $("[id='duplication-error-" + i + "']").hide();
                }
            });
            i++;
        }
        if (success) {
            form.submit();
        }
    });
    this.addAction({
        submission: "submit-image-replace"
    }, function() {
        var $form = this.el;
        var form = Form.get($form);
        var data = new FormData();
        $.each(form.data(), function(name, value) {
            data.append(name, value);
        });
        data.append("file", this.el.data("selected-file"));
        setControlsEnabled($form, false);
        $.ajax(form.getAction(), {
            type: "POST",
            dataType: "html",
            enctype: "multipart/form-data",
            processData: false,
            contentType: false,
            data: data
        }).always(function() {
            setControlsEnabled($form, true);
        }).done(function(resp) {
            Page.render(resp, false);
        });
    });
    this.addAction({
        click: "change-category-bulk"
    }, function() {
        var url = this.el.data("form-url");
        var form = Form.get(this.el);
        var data = form.data();
        if (!data || !data.bulkId || !data.bulkId.length) {
            AGN.Lib.Messages(t("Error"), t("messages.error.nothing_selected"), "alert");
            return;
        }
        Confirm.create(Template.text("modal-element-category-select", {
            categoryId: null
        })).done(function(resp) {
            if (resp && resp.categoryId) {
                form.setActionOnce(url);
                form.setValueOnce("categoryId", resp.categoryId);
                form.submit();
            }
        });
    });
    this.addAction({
        change: "change-mobile-base"
    }, function() {
        var $el = $(this.el);
        var config = Helpers.objFromString($el.data("config"));
        var field = $("#file-name-" + config.count);
        var initialValue = config.initialValue;
        var selectedValue = AGN.Lib.Select.get($el).getSelectedValue();
        var isMobile = selectedValue && selectedValue.length > 0;
        var fileName = isMobile ? config.mobilePrefix + selectedValue : initialValue;
        field.val(fileName);
        field.prop("readonly", isMobile);
    });
    this.addDomInitializer("ai-images-generation", function() {
        appendImportantObjectRow({
            isFirstRow: true
        });
        appendImageGenerationFilterRow({
            isFirstRow: true
        });
    });
    function appendImportantObjectRow(options) {
        const $row = Template.dom("ai-image-generation-important-objects-row", options);
        $("#important-objects-table").find("tbody").append($row);
        AGN.runAll($row);
    }
    function appendImageGenerationFilterRow(options) {
        const $row = Template.dom("ai-image-generation-filter-row", options);
        $("#ai-image-filters-table").find("tbody").append($row);
        AGN.runAll($row);
        AGN.Lib.Field.create($row);
    }
    this.addAction({
        change: "disable-important-objects"
    }, function() {
        const $table = $("#important-objects-table");
        disableTable(this.el, $table);
    });
    this.addAction({
        click: "add-important-object"
    }, function() {
        const $row = this.el.closest("[data-important-object-row]");
        const rowData = getImportantRowData($row);
        const $inputs = $row.find(":input");
        $inputs.each(function() {
            const $input = $(this);
            $input.val("").trigger("change");
            const $colorpicker = $input.closest(".js-colorpicker");
            if ($colorpicker.exists()) {
                $colorpicker.data("colorpicker").updateComponent("transparent");
            }
        });
        appendImportantObjectRow(_.extend({
            isFirstRow: false
        }, rowData));
    });
    this.addAction({
        click: "remove-important-object"
    }, function() {
        this.el.closest("[data-important-object-row]").remove();
    });
    this.addAction({
        change: "disable-image-generation-filters"
    }, function() {
        const $table = $("#ai-image-filters-table");
        disableTable(this.el, $table);
        disable - image - generation - filters;
    });
    function disableTable($toggle, $table) {
        const disable = !$toggle.is(":checked");
        $table.toggleClass("disabled", disable);
        $table.find(":input, button").prop("disabled", disable);
    }
    this.addAction({
        click: "add-generation-filter"
    }, function() {
        const $row = this.el.closest("[data-image-generation-filter-row]");
        const rowData = getImageGenerationFilterRowData($row);
        appendImageGenerationFilterRow(_.extend({
            isFirstRow: false
        }, rowData));
    });
    this.addAction({
        click: "remove-generation-filter"
    }, function() {
        this.el.closest("[data-image-generation-filter-row]").remove();
    });
    this.addAction({
        click: "generate-ai-image"
    }, function() {
        const form = Form.get(this.el);
        setImportantObjectsToForm(form);
        setImageGenerationFiltersToForm(form);
        form.jqxhr().done(function(resp) {
            if (resp.success) {
                updateRemainingGenerationsText(resp.data.remainingGenerationsCount);
                const $generatedImage = $("#ai-generated-image");
                $generatedImage.attr("src", resp.data.url);
                $generatedImage.removeClass("hidden");
                $("#save-generated-img-btn").removeClass("hidden");
            } else {
                AGN.Lib.JsonMessages(resp.popups);
            }
        });
    });
    function updateRemainingGenerationsText(count) {
        if (count <= 0) {
            $("#remaining-generations-text").text(t(`mediapool.imageGeneration.limitExceeded`));
            $("#generate-btn").remove();
        } else {
            $("#remaining-generations-text").text(t(`mediapool.imageGeneration.remainingGenerations`, count));
        }
    }
    function setImportantObjectsToForm(form) {
        collectImportantObjectsFromTable().forEach(function(object, index) {
            Object.keys(object).forEach(function(property) {
                form.setValueOnce("importantObjects[" + index + "]" + "." + property, object[property]);
            });
        });
    }
    function setImageGenerationFiltersToForm(form) {
        const groupedFilters = _.groupBy(collectImageGenerationFiltersFromTable(), "name");
        _.forEach(groupedFilters, function(filterValues, filterName) {
            const valuesArray = _.map(filterValues, "value");
            form.setValueOnce("filters[" + filterName + "]", valuesArray);
        });
    }
    this.addAction({
        click: "save-generated-ai-image"
    }, function() {
        const url = $("#ai-generated-image").attr("src");
        $.post(AGN.url("/mediapool/content/images/saveGenerated.action"), {
            url: url
        }).done(function(resp) {
            Page.render(resp);
        });
    });
    function collectImportantObjectsFromTable() {
        if ($("#important-objects-table").hasClass("disabled")) {
            return [];
        }
        return $("[data-important-object-row]:not(:first)").map(function() {
            return getImportantRowData($(this));
        }).get();
    }
    function collectImageGenerationFiltersFromTable() {
        if ($("#ai-image-filters-table").hasClass("disabled")) {
            return [];
        }
        return $("[data-image-generation-filter-row]:not(:first)").map(function() {
            return getImageGenerationFilterRowData($(this));
        }).get();
    }
    function getImportantRowData($row) {
        return {
            objects: $row.find("[data-row-objects]").val(),
            objectColors: $row.find("[data-row-objects-colours]").val(),
            amount: $row.find("[data-row-amount]").val(),
            layout: $row.find("[data-row-layout]").val()
        };
    }
    function getImageGenerationFilterRowData($row) {
        return {
            name: $row.find("[data-row-filter-name]").val(),
            value: $row.find("[data-row-filter-value]").val()
        };
    }
});

AGN.Lib.Controller.new("news-editor", function() {
    var Template = AGN.Lib.Template;
    var languages = [ "de", "en" ];
    var index = 0;
    this.addDomInitializer("news-editor-init", function() {
        var newsId = $('input[name="newsId"]').val();
        var existentNews = $(".existent-news");
        if (existentNews && existentNews.length > 0 && newsId == 0) {
            $(existentNews).each(function() {
                var language = $(this).find(".existent-news-language").val();
                var title = $(this).find(".existent-news-title").val();
                var content = $(this).find(".existent-news-content").val();
                addNewsContentBlock(language, title, content);
                updateRemoveButtonVisibility();
                updateAddButtonsVisibility();
                $(this).remove();
            });
        } else if (newsId == 0) {
            addNewsContentBlock(getFirstUnusedLanguage(), "", "");
            updateRemoveButtonVisibility();
            updateAddButtonsVisibility();
        }
    });
    this.addAction({
        click: "addNewsContent"
    }, function() {
        addNewsContentBlock(getFirstUnusedLanguage(), "", "");
        updateRemoveButtonVisibility();
        updateAddButtonsVisibility();
    });
    this.addAction({
        click: "removeNewsContent"
    }, function() {
        var parentContentBlock = $(this.el).closest(".l-news-content-block");
        $(parentContentBlock).remove();
        updateRemoveButtonVisibility();
        updateAddButtonsVisibility();
        refreshDropDownLanguages();
    });
    this.addAction({
        change: "changeLanguage"
    }, function() {
        refreshDropDownLanguages();
    });
    function addNewsContentBlock(language, title, content) {
        if (language != "") {
            var $block = Template.dom("news-content-template-row", {
                lang: language,
                index: index,
                title: title,
                content: content
            });
            if ($("#news-content-editor > .l-news-content-block").length == 0) {
                $("#news-content-editor").append('<div class="tile-separator"></div>');
            }
            $block.appendTo("#news-content-editor");
            AGN.runAll($block);
            refreshDropDownLanguages();
            index++;
        }
    }
    function updateAddButtonsVisibility() {
        var usedLanguages = getUsedLanguages();
        var lastContentBlockIndex = $("#news-content-editor > .l-news-content-block").last().find("input[name='index']").val();
        if (languages.length == usedLanguages.length) {
            $("#add-news-" + lastContentBlockIndex).hide();
        } else {
            $("#add-news-" + lastContentBlockIndex).show();
        }
    }
    function updateRemoveButtonVisibility() {
        var contentBlocks = $("#news-content-editor > .l-news-content-block");
        $("button[id^='add-news-']").hide();
        var firstContentBlockIndex = $(contentBlocks).first().find("input[name='index']").val();
        if (contentBlocks.length == 1) {
            $("#delete-news-" + firstContentBlockIndex).hide();
        } else {
            $("#delete-news-" + firstContentBlockIndex).show();
        }
    }
    function refreshDropDownLanguages() {
        var unusedLanguages = getUnusedLanguages();
        $("#news-content-editor > .l-news-content-block").find("select.news-language").each(function() {
            $("option", this).not(":selected").remove();
            var selectItem = $(this);
            $.each(unusedLanguages, function(index, language) {
                $(selectItem).append($("<option>", {
                    value: language,
                    text: language
                }));
            });
        });
    }
    function getUnusedLanguages() {
        var unusedLanguages = [];
        var selectedLanguages = getUsedLanguages();
        $.each(languages, function(index, language) {
            if ($.inArray(language, selectedLanguages) == -1) {
                unusedLanguages.push(language);
            }
        });
        return unusedLanguages;
    }
    function getUsedLanguages() {
        var selectedLanguages = $("#news-content-editor > .l-news-content-block").find("select.news-language").find("option:selected");
        return selectedLanguages.map(function() {
            return $(this).val();
        }).toArray();
    }
    function getFirstUnusedLanguage() {
        var usedLanguages = getUsedLanguages();
        var unusedLanguage = "";
        if (usedLanguages.length == 0) {
            unusedLanguage = languages[0];
        } else {
            $.each(languages, function(index, language) {
                if (usedLanguages.indexOf(language) < 0) {
                    unusedLanguage = language;
                    return false;
                }
            });
        }
        return unusedLanguage;
    }
});

AGN.Lib.Controller.new("notification-global-stat", function() {
    this.addAction({
        change: "selectReportType"
    }, function() {
        var $stats = $("#globalStatInfo");
        switch (this.el.val()) {
          case "STATUS":
            setChartsVisibility(false, true, false);
            $stats.show();
            break;

          case "BROWSER":
            setChartsVisibility(false, false, true);
            $stats.hide();
            break;

          case "PROGRESS":
            setChartsVisibility(true, false, false);
            $stats.show();
            break;
        }
    });
    this.addAction({
        click: "close"
    }, function() {
        var notificationContainer = $("#notifications-container");
        notificationContainer.fadeOut("slow", function() {
            notificationContainer.remove();
        });
    });
    this.addAction({
        click: "refreshStat"
    }, function() {
        updateProgressChart();
    });
    this.addAction({
        change: "select-month"
    }, function() {
        updateProgressChart();
    });
    this.addAction({
        change: "select-year"
    }, function() {
        updateProgressChart();
    });
    this.addAction({
        click: "weekProgressStat"
    }, function() {
        $("#selectMode").val("WEEK");
        setDateControlsVisibility(false, false);
        updateProgressChart();
        setDateSelectModeActivity(true, false, false);
    });
    this.addAction({
        click: "monthProgressStat"
    }, function() {
        $("#selectMode").val("MONTH");
        setDateControlsVisibility(true, false);
        $("#refreshStat").show();
        setDateSelectModeActivity(false, true, false);
        updateProgressChart();
    });
    this.addAction({
        click: "dateRangeProgressStat"
    }, function() {
        $("#selectMode").val("RANGE");
        setDateControlsVisibility(false, true);
        $("#refreshStat").show();
        setDateSelectModeActivity(false, false, true);
        updateProgressChart();
    });
    this.addAction({
        change: "end-date-change"
    }, function() {
        var startDay = $("#startDay").val();
        var endDay = $("#endDay").val();
        $("#startDay").pickadate("picker").set("max", endDay);
        $("#endDay").pickadate("picker").set("min", startDay);
        updateProgressChart();
    });
    this.addAction({
        change: "start-date-change"
    }, function() {
        var startDay = $("#startDay").val();
        var endDay = $("#endDay").val();
        $("#startDay").pickadate("picker").set("max", endDay);
        $("#endDay").pickadate("picker").set("min", startDay);
        updateProgressChart();
    });
    function setDateControlsVisibility(isMonthProgressStatVisible, isDateRangeProgressStatVisible) {
        $("#month-progress-stat").hide();
        $("#daterange-progress-stat").hide();
        if (isMonthProgressStatVisible) {
            $("#month-progress-stat").show();
        }
        if (isDateRangeProgressStatVisible) {
            $("#daterange-progress-stat").show();
        }
    }
    function setDateSelectModeActivity(isWeekActive, isMonthActive, isDateRangeActive) {
        $("#weekProgressStat").removeClass("active");
        $("#monthProgressStat").removeClass("active");
        $("#dateRangeProgressStat").removeClass("active");
        if (isWeekActive) {
            $("#weekProgressStat").addClass("active");
        }
        if (isMonthActive) {
            $("#monthProgressStat").addClass("active");
        }
        if (isDateRangeActive) {
            $("#dateRangeProgressStat").addClass("active");
        }
    }
    function setChartsVisibility(isProgressChartVisible, isStatusChartVisible, isBrowserChartVisible) {
        $("#notificationGlobalStatusStat").hide();
        $("#notificationGlobalBrowserStat").hide();
        $("#notificationGlobalProgressStat").hide();
        if (isProgressChartVisible) {
            AGN.Lib.DomInitializer.try("notification-global-progress-stat");
            $("#notificationGlobalProgressStat").show();
            $("#dateSelectMode").show();
            $("#dateModeControls").show();
        }
        if (isStatusChartVisible) {
            AGN.Lib.DomInitializer.try("notification-global-status-stat");
            $("#notificationGlobalStatusStat").show();
            $("#dateSelectMode").hide();
            $("#dateModeControls").hide();
        }
        if (isBrowserChartVisible) {
            AGN.Lib.DomInitializer.try("notification-global-browser-stat");
            $("#notificationGlobalBrowserStat").show();
            $("#dateSelectMode").hide();
            $("#dateModeControls").hide();
        }
    }
    function updateProgressChart() {
        $("#notifications-container").remove();
        if (isValidDatesRange()) {
            if ($("#monthProgressStat").attr("class") == "active" || $("#dateRangeProgressStat").attr("class") == "active") {
                AGN.Lib.DomInitializer.try("notification-global-progress-stat");
            }
        }
    }
    function isValidDatesRange() {
        if ($("#dateRangeProgressStat").attr("class") == "active") {
            var startDay = $("#startDay").val();
            var endDay = $("#endDay").val();
            if (isEmptyDate(startDay) || isEmptyDate(endDay)) {
                showErrorPeriodFormat();
                return false;
            }
            if (new Date(startDay).getTime() > new Date(endDay).getTime()) {
                showErrorPeriodFormat();
                return false;
            }
        }
        return true;
    }
    function isEmptyDate(date) {
        return typeof date === "undefined" || date == "";
    }
    function showErrorPeriodFormat() {
        AGN.Lib.Messages(t("defaults.error"), t("error.statistic.period_format"), "alert");
        setTimeout(function() {
            var notificationContainer = $("#notifications-container");
            notificationContainer.fadeOut("slow", function() {
                notificationContainer.remove();
            });
        }, 7e3);
    }
});

AGN.Lib.Controller.new("notification-schedule", function() {
    var $beginDate, $endDate, $beginTime, $endTime;
    this.addDomInitializer("notification-schedule", function($elem) {
        $beginDate = $elem.find("#startDate");
        $endDate = $elem.find("#endDate");
        $beginTime = $elem.find("#startTime");
        $endTime = $elem.find("#endTime");
        $beginDate.pickadate("picker").on("set", calculateEndDateAndConstraints);
        $beginTime.on("change", calculateEndDateAndConstraints);
        $endDate.pickadate("picker").on("set", disableEndDateCalculation);
        $endTime.on("change", disableEndDateCalculation);
    });
    function getBeginDate() {
        var date = $beginDate.pickadate("get", "select");
        return date && new Date(date.obj);
    }
    function calculateEndDateAndConstraints() {
        var picker = $endDate.pickadate("picker");
        var begin = getBeginDate();
        picker.off("set");
        if (begin) {
            var end = getMaxExpiredDate(begin);
            assignEndDateConstraints(begin, end);
            assignEndDate(end);
            assignEndTime($beginTime.val());
        } else {
            assignEndDateConstraints(true, false);
            assignEndDate(null);
            assignEndTime(null);
        }
        picker.on("set", disableEndDateCalculation);
    }
    function calculateConstraints() {
        var begin = getBeginDate();
        if (begin) {
            assignEndDateConstraints(begin, getMaxExpiredDate(begin));
        } else {
            assignEndDateConstraints(true, false);
        }
    }
    function assignEndDate(date) {
        var picker = $endDate.pickadate("picker");
        if (date) {
            picker.set("select", date);
        } else {
            picker.clear();
        }
    }
    function assignEndDateConstraints(min, max) {
        var picker = $endDate.pickadate("picker");
        picker.set("min", min);
        picker.set("max", max);
        picker.set("select", picker.get("select"));
    }
    function assignEndTime(time) {
        $endTime.val(time);
    }
    function getMaxExpiredDate(startDate) {
        var expiredDate = new Date(startDate);
        expiredDate.setDate(expiredDate.getDate() + 28);
        return expiredDate;
    }
    function disableEndDateCalculation() {
        $endDate.removeClass("enableable");
        $endTime.removeClass("enableable");
        $endDate.pickadate("off", "set");
        $endTime.unbind("change");
        $beginDate.pickadate("off", "set");
        $beginDate.pickadate("picker").on("set", calculateConstraints);
        $beginTime.unbind("change");
        $beginTime.on("change", calculateConstraints);
    }
});

AGN.Lib.Controller.new("notification-settings", function() {
    this.addAction({
        "editor:create": "content",
        "editor:change": "content"
    }, function() {
        var count = this.el.val().length;
        $("#contentSize").text(t("fields.content.charactersEntered", count));
    });
});

AGN.Lib.Controller.new("preview-header-new", function() {
    var self = this;
    this.addInitializer("set-preview-customer-options", function() {
        var isUsedCustomerEmail = $('[name="useCustomerEmail"]:checked').val() == "true";
        $('[name="customerEmail"]').prop("disabled", !isUsedCustomerEmail);
        $("#btnCustomEmailRefresh").prop("disabled", !isUsedCustomerEmail);
        $('select[name="customerID"]').prop("disabled", isUsedCustomerEmail);
    });
    this.addAction({
        change: "change-preview-customer-options"
    }, function() {
        self.runInitializer("set-preview-customer-options");
    });
});

AGN.Lib.Controller.new("profile-field-view", function() {
    const Form = AGN.Lib.Form;
    var config;
    this.addDomInitializer("profile-field-view", function() {
        config = this.config;
    });
    this.addAction({
        submission: "submit-profile-field-save"
    }, function() {
        const $form = this.el;
        const $stateIcons = $("span[class*='icon-state-']");
        $form.find($stateIcons).each(function() {
            const $e = $(this);
            $e.show();
            $e.closest(".form-group").addClass("has-feedback");
        });
        const form = Form.get($form);
        if (config.targetUrl) {
            form.setValueOnce("targetUrl", config.targetUrl);
        }
        form.submit();
    });
});

AGN.Lib.Controller.new("recipient-import-errors-edit", function() {
    const Page = AGN.Lib.Page;
    this.addDomInitializer("recipient-import-errors-edit", function() {
        if (isPageReloaded()) {
            Page.reload(AGN.url("/recipient/import/chooseMethod.action?cancelImport=true"));
        } else {
            window.onbeforeunload = function() {
                return "If you leave the page, the import will be canceled automatically!";
            };
        }
    });
    function isPageReloaded() {
        if (typeof performance === "undefined" || typeof performance.getEntriesByType !== "function") {
            return false;
        }
        const entries = performance.getEntriesByType("navigation");
        if (entries.length > 0) {
            return entries[0].type === "reload";
        }
        return false;
    }
    this.addAction({
        submission: "save-errors"
    }, function() {
        unbindUnloadEvents();
        const form = AGN.Lib.Form.get(this.el);
        form.submit("static");
    });
    this.addAction({
        click: "ignore-errors"
    }, function() {
        unbindUnloadEvents();
        Page.reload(AGN.url("/recipient/import/errors/ignore.action"));
    });
    this.addAction({
        click: "cancel"
    }, function() {
        unbindUnloadEvents();
        Page.reload(AGN.url("/recipient/import/cancel.action"));
    });
    function unbindUnloadEvents() {
        window.onbeforeunload = null;
    }
});

AGN.Lib.Controller.new("recipient-import-view", function() {
    this.addAction({
        click: "delete-file"
    }, function() {
        const jqxhr = $.post(AGN.url("/recipient/import/file/delete.action"));
        jqxhr.done(function() {
            $("#uploaded-file-container").remove();
            $("#uploadFile").removeClass("hidden");
        });
    });
    this.addDomInitializer("recipient-import-view", function() {
        const attachmentCsvFileID = this.config.attachmentCsvFileID;
        if (attachmentCsvFileID > 0) {
            const $csvUploadToggle = $("#useCsvUpload");
            $csvUploadToggle.prop("checked", true);
            $csvUploadToggle.trigger("change");
        }
    });
});

AGN.Lib.Controller.new("recipient-list", function() {
    var Action = AGN.Lib.Action, Modal = AGN.Lib.Modal, Form = AGN.Lib.Form, Messages = AGN.Lib.Messages, Storage = AGN.Lib.Storage;
    const ADVANCED_SUFFIX = "_advanced";
    const NO_MAILINGLIST_VALUE = "-1";
    var initialRules = {};
    var searchFieldsUpdatingRequired = false;
    var mailinglistId;
    var $basicSearch;
    var $advancedSearch;
    Action.new({
        "qb:invalidrules": "#targetgroup-querybuilder"
    }, function() {
        Messages(t("defaults.error"), t("querybuilder.errors.invalid_definition"), "alert");
    });
    this.addDomInitializer("recipient-list", function() {
        initializeList(this.config, false);
    });
    this.addDomInitializer("recipient-duplicate-list", function() {
        initializeList(this, true);
    });
    this.addAction({
        enterdown: "search-recipient"
    }, function() {
        searchFieldsUpdatingRequired = true;
    });
    function initializeList(config, isDuplicate) {
        $basicSearch = $("#basicSearch");
        $advancedSearch = $("#advancedSearch");
        $basicSearch.on("click", function() {
            onBasicSearch();
        });
        $advancedSearch.on("click", function() {
            onAdvancedSearch();
        });
        if (!isAdvancedSearch()) {
            mailinglistId = $("#tab-basicSearch").find('[data-action="change-mailinglist-id"]').val();
            onBasicSearch();
        }
        if (isAdvancedSearch()) {
            mailinglistId = $("#tab-advancedSearch").find('[data-action="change-mailinglist-id"]').val();
            onAdvancedSearch();
        }
        if (isDuplicate) {
            onDuplicateList();
        } else {
            onGeneralList(config);
        }
        updateMlDependentFieldsStates();
    }
    function onDuplicateList() {
        var controls = $("#recipientForm").find(".table-controls .well");
        controls.first().html(controls.last().html());
    }
    function onGeneralList(config) {
        searchFieldsUpdatingRequired = false;
        if (config && config.initialRules) {
            initialRules = $.extend({}, JSON.parse(config.initialRules));
        }
        var $queryBuilder = $("#targetgroup-querybuilder");
        $queryBuilder.on("change", function() {
            $("#target-group-save-button").toggleClass("hidden", !containsNotEmptyRule());
        });
        $queryBuilder.on("afterClear.queryBuilder", function() {
            $("#target-group-save-button").toggleClass("hidden", true);
        });
        $queryBuilder.on("afterReset.queryBuilder " + "afterDeleteGroup.queryBuilder " + "afterDeleteRule.queryBuilder " + "afterSetRules.queryBuilder " + "afterUpdateRuleFilter.queryBuilder", function(e) {
            $("#target-group-save-button").toggleClass("hidden", !containsNotEmptyRule());
        });
    }
    function onBasicSearch() {
        $("input[name=advancedSearch]").val(false);
        resetNotAppliedRules();
        disableDuplicatedSearchFields(true, true);
        disableDuplicatedSearchFields(false, false);
    }
    function onAdvancedSearch() {
        $("input[name=advancedSearch]").val(true);
        disableDuplicatedSearchFields(false, true);
        disableDuplicatedSearchFields(true, false);
    }
    function isAdvancedSearch() {
        return !$basicSearch.hasClass("tab active") && $advancedSearch.hasClass("tab active");
    }
    this.addAction({
        validation: "search-recipient"
    }, function() {
        if (searchFieldsUpdatingRequired) {
            var validationOptions = this.data;
            this.data = _.merge({}, validationOptions, {
                ignore_qb_validation: false,
                skip_empty: false
            });
        } else if (this.data && this.data.ignore_qb_validation) {
            resetNotAppliedRules();
        }
    });
    this.addAction({
        submission: "search-recipient"
    }, function() {
        if (searchFieldsUpdatingRequired) {
            var isAdvancedSearch = $("input[name=advancedSearch]").val();
            if (isAdvancedSearch == true) {
                updateBasicFieldsBasedOnQbRules();
            } else {
                updateQbRulesBasedOnBasicFields();
            }
            submitForm($(this.el), {
                ignore_qb_validation: false
            });
        }
    });
    function resetNotAppliedRules() {
        var api = getQbApi();
        if (api) {
            api.clearErrors();
            api.setRules(initialRules);
            updateBasicFieldsBasedOnQbRules();
        }
    }
    this.addAction({
        click: "target-group-save"
    }, function() {
        var api = getQbApi();
        if (api) {
            api.clearErrors();
        }
        var form = Form.get($(this.el));
        var isValid = form.validate(_.merge({}, form.validatorOptions, {
            ignore_qb_validation: false,
            skip_empty: false
        }));
        if (isValid) {
            Modal.createFromTemplate({}, "target-group-save");
        }
    });
    function updateMlDependentFieldsStates() {
        const disable = mailinglistId === NO_MAILINGLIST_VALUE;
        if (disable || !isAdvancedSearch()) {
            $("#search_recipient_type").prop("disabled", disable);
            $("#search_recipient_state").prop("disabled", disable);
        }
        if (disable || isAdvancedSearch()) {
            $("#search_recipient_type_advanced").prop("disabled", disable);
            $("#search_recipient_state_advanced").prop("disabled", disable);
        }
    }
    this.addAction({
        change: "change-target-group"
    }, function() {
        var value = $("#search_targetgroup").val();
        $("#search_targetgroup_advanced").select2("val", value);
    });
    this.addAction({
        change: "change-recipient-type"
    }, function() {
        var value = $("#search_recipient_type").val();
        $("#search_recipient_type_advanced").select2("val", value);
    });
    this.addAction({
        change: "change-user-status"
    }, function() {
        var value = $("#search_recipient_state").val();
        $("#search_recipient_state_advanced").select2("val", value);
    });
    this.addAction({
        change: "change-target-group-advanced"
    }, function() {
        var value = $("#search_targetgroup_advanced").val();
        $("#search_targetgroup").select2("val", value);
    });
    this.addAction({
        change: "change-recipient-type-advanced"
    }, function() {
        var value = $("#search_recipient_type_advanced").val();
        $("#search_recipient_type").select2("val", value);
    });
    this.addAction({
        change: "change-user-status-advanced"
    }, function() {
        var value = $("#search_recipient_state_advanced").val();
        $("#search_recipient_state").select2("val", value);
    });
    this.addAction({
        click: "choose-advanced-search"
    }, function() {
        if (updateQbRulesBasedOnBasicFields()) {
            submitForm($(this.el), {
                ignore_qb_validation: false
            });
        }
    });
    this.addAction({
        click: "toggle-recipient-tab"
    }, function() {
        var $el = $(this.el);
        var siblings = $('[data-action="toggle-recipient-tab"]');
        _.each(siblings, function(sibling) {
            Storage.set("toggle_tab" + $(sibling).data("tab-id"), {
                hidden: true
            });
        });
        Storage.set("toggle_tab" + $el.data("tab-id"), {
            hidden: false
        });
        var url = $el.data("url");
        if (!!url) {
            window.location.href = url;
        }
    });
    this.addAction({
        click: "reset-search"
    }, function() {
        $("#search_first_name").val("");
        $("#search_name").val("");
        $("#search_email").val("");
        $("#search_mailinglist").select2("val", 0);
        $("#search_targetgroup").select2("val", 0);
        $("#search_recipient_type").select2("val", "");
        $("#search_recipient_state").select2("val", 0);
        $("#search_mailinglist_advanced").select2("val", 0);
        $("#search_targetgroup_advanced").select2("val", 0);
        $("#search_recipient_type_advanced").select2("val", "");
        $("#search_recipient_state_advanced").select2("val", 0);
        resetQueryBuilderRules();
        submitForm($(this.el), {
            ignore_qb_validation: false
        });
    });
    this.addAction({
        click: "createNewTarget"
    }, function() {
        var api = getQbApi();
        if (api) {
            api.clearErrors();
        }
        var form = Form.get($(this.el));
        var isValid = form.validate(_.merge({}, form.validatorOptions, {
            ignore_qb_validation: false,
            skip_empty: false
        }));
        if (isValid) {
            AGN.Lib.Confirm.createFromTemplate({
                rules: form.get$().find('[name="searchQueryBuilderRules"]').val()
            }, "new-targetgroup-modal").done(function(resp) {
                form.updateHtml(resp);
            });
        }
    });
    this.addAction({
        change: "change-mailinglist-id"
    }, function() {
        mailinglistId = $(this.el).select2("val");
        updateMlDependentFieldsStates();
    });
    this.addAction({
        click: "refresh-basic-search"
    }, function() {
        updateQbRulesBasedOnBasicFields();
        submitForm($(this.el), {
            ignore_qb_validation: false
        });
    });
    this.addAction({
        click: "refresh-advanced-search"
    }, function() {
        updateBasicFieldsBasedOnQbRules();
        submitForm($(this.el), {
            ignore_qb_validation: false
        });
    });
    function disableDuplicatedSearchFields(onAdvancedTab, disable) {
        const suffix = onAdvancedTab ? ADVANCED_SUFFIX : "";
        const fieldsSelectors = [ "#search_mailinglist", "#search_altg", "#search_targetgroup" ];
        if (mailinglistId !== NO_MAILINGLIST_VALUE || disable) {
            fieldsSelectors.push("#search_recipient_type", "#search_recipient_state");
        }
        fieldsSelectors.forEach(function(selector) {
            $(selector + suffix).prop("disabled", disable);
        });
    }
    function updateQbRulesBasedOnBasicFields() {
        var fieldsMap = {
            firstname: $("#search_first_name").val().trim(),
            lastname: $("#search_name").val().trim(),
            email: $("#search_email").val().trim()
        };
        var rules = Object.keys(fieldsMap).map(function(key) {
            return {
                id: key,
                value: fieldsMap[key],
                operator: "like"
            };
        });
        return addOrReplaceRules(rules, true);
    }
    function updateBasicFieldsBasedOnQbRules() {
        var valueMap = getQbFieldsValue([ "firstname", "lastname", "email" ]);
        $("#search_first_name").val(valueMap.firstname);
        $("#search_name").val(valueMap.lastname);
        $("#search_email").val(valueMap.email);
    }
    function submitForm($el, options) {
        var form = Form.get($el);
        form.submit("", _.merge({
            ignore_qb_validation: true,
            skip_empty: true
        }, form.validatorOptions, options));
    }
    function getQbApi() {
        return $("#targetgroup-querybuilder").prop("queryBuilder");
    }
    function containsNotEmptyRule() {
        var api = getQbApi();
        if (api) {
            return api.containsNotEmptyRule();
        } else {
            return false;
        }
    }
    function resetQueryBuilderRules() {
        var api = getQbApi();
        if (api) {
            api.clearErrors();
            return api.reset();
        } else {
            return false;
        }
    }
    function getQbFieldsValue(fieldNames) {
        var api = getQbApi();
        var result = {};
        if (api) {
            var qbRules = api.getRules({
                allow_invalid: true,
                skip_empty: true
            });
            fieldNames.forEach(function(field) {
                var rule = api.findRuleByField(qbRules, field, true);
                result[field] = rule ? rule.value : "";
            });
        }
        return result;
    }
    function addOrReplaceRules(rules, recursively) {
        var api = getQbApi();
        if (api) {
            return rules.reduce(function(accumulator, rule) {
                var qbRules = api.getRules({
                    allow_invalid: true,
                    skip_empty: true
                });
                if (rule.id) {
                    if (rule.value) {
                        return api.setOrReplaceRule(qbRules, rule, recursively) === true || accumulator;
                    } else {
                        return api.deleteRuleByField(null, rule.id, recursively) === true || accumulator;
                    }
                } else {
                    return accumulator;
                }
            }, false);
        } else {
            return false;
        }
    }
});

AGN.Lib.Controller.new("recipient-statistics-view", function() {
    this.addAction({
        change: "type-change"
    }, function() {
        const $el = this.el;
        var selectedOption = $el.find("option:selected");
        const $mailinglist = $("#mailinglist-select");
        if (selectedOption.is("[data-mailinglist-required]") && $mailinglist.val() === "0") {
            AGN.Lib.Select.get($mailinglist).selectNext();
        }
        AGN.Lib.Form.get($el).submit();
    });
});

AGN.Lib.Controller.new("recipient-view", function() {
    var RESULT_OK = "OK";
    var RESULT_USED = "USED";
    var RESULT_BLACKLISTED = "BLACKLISTED";
    var Form = AGN.Lib.Form, Confirm = AGN.Lib.Confirm, Template = AGN.Lib.Template, Tile = AGN.Lib.Tile;
    var checker;
    var isActiveSaveSubmenu = false;
    var config;
    this.addDomInitializer("recipient-view", function($e) {
        var form = Form.get($e);
        var self = this;
        config = this.config;
        checker = new AddressChecker(self.config.urls.CHECK_ADDRESS, function(result) {
            var status = result.status;
            switch (status) {
              case RESULT_OK:
                form.cleanFieldError("email");
                break;

              case RESULT_USED:
                var btnUrl = self.config.urls.EXISTING_USER_URL_PATTERN.replace(":recipientID:", result.recipientID);
                var messageErrorInUseUser = '<div style="display: flex; width: 100%; justify-content: space-between; align-items: center;">' + t("error.inUse") + '<a href="' + btnUrl + '" class="btn btn-regular btn-inverse">' + t("recipient.existing.btn") + "</a>" + "</div>";
                form.showFieldError("email", messageErrorInUseUser, true);
                break;

              case RESULT_BLACKLISTED:
                form.showFieldError("email", t("error.isBlacklisted"), true);
                break;
            }
        });
        $("#recipient-email").on("change input", _.debounce(function() {
            checker.check($(this).val());
        }, 300));
        updateBindingsUserTypesProps();
    });
    this.addAction({
        mouseleave: "toggleSaveAndBack"
    }, function() {
        var $el = this.el;
        var parent = $el.parent();
        setTimeout(function() {
            if (!isActiveSaveSubmenu && !$el.is(":hover")) {
                parent.removeClass("open");
            }
        }, 400);
    });
    this.addAction({
        mouseenter: "toggleSaveAndBack"
    }, function() {
        this.el.parent().addClass("open");
    });
    this.addAction({
        mouseenter: "toggleSubmenuSaveAndBack"
    }, function() {
        isActiveSaveSubmenu = true;
    });
    this.addAction({
        mouseleave: "toggleSubmenuSaveAndBack"
    }, function() {
        isActiveSaveSubmenu = false;
        this.el.closest(".dropdown").removeClass("open");
    });
    this.addAction({
        submission: "recipient-save"
    }, function() {
        var form = Form.get(this.el);
        var address = $("#recipient-email").val();
        this.event.preventDefault();
        var checkAltgMatchCallback = function() {
            $.post(config.urls.CHECK_MATCH_ALTG, form.params()).done(function(response) {
                if (response.popups && response.popups.alert && response.popups.alert.length > 0) {
                    AGN.Lib.JsonMessages(response.popups);
                } else if (!response.success || response.success.length === 0) {
                    Confirm.create(Template.text("hide-recipient-confirmation-modal")).done(function() {
                        form.setActionOnce(config.urls.SAVE_AND_BACK_TO_LIST);
                        form.submit();
                    });
                } else {
                    form.submit();
                }
            }).fail(function() {
                form.submit();
            });
        };
        if (checker && address && address.trim()) {
            checker.jqxhr(address.trim()).done(function(resp) {
                if (resp.isBlacklisted === true) {
                    Confirm.create(Template.text("email-confirmation-modal", {
                        question: t("recipient.blacklisted.question")
                    })).done(function() {
                        if (resp.inUse === true) {
                            Confirm.create(Template.text("email-confirmation-modal", {
                                question: t("recipient.duplicate.question")
                            })).done(checkAltgMatchCallback);
                        } else {
                            checkAltgMatchCallback();
                        }
                    });
                } else if (resp.inUse === true) {
                    Confirm.create(Template.text("email-confirmation-modal", {
                        question: t("recipient.duplicate.question")
                    })).done(checkAltgMatchCallback);
                } else {
                    checkAltgMatchCallback();
                }
            }).fail(checkAltgMatchCallback);
        } else {
            checkAltgMatchCallback();
        }
    });
    function updateBindingsUserTypesProps() {
        $(".not-allowed-usertype").each(function() {
            const $el = $(this);
            if ($el.prop("selected")) {
                $el.parent("select").prop("disabled", true);
            } else {
                $el.prop("disabled", true);
            }
        });
    }
    function AddressChecker(url, callback) {
        this.url = url;
        this.running = false;
        this.callback = $.isFunction(callback) ? callback : $.noop;
        this.lastAddress = null;
        this.lastResult = null;
        this.scheduledCheck = null;
    }
    AddressChecker.prototype.jqxhr = function(address) {
        return $.get(this.url, {
            email: address
        });
    };
    AddressChecker.prototype.scheduleCheck = function(address) {
        var self = this;
        if (self.scheduledCheck) {
            clearTimeout(self.scheduledCheck);
        }
        if (self.running) {
            self.scheduledCheck = setTimeout(function() {
                self.scheduleCheck(address);
            }, 300);
        } else {
            self.running = true;
            self.lastAddress = null;
            self.lastResult = null;
            try {
                self.jqxhr(address).always(function() {
                    self.running = false;
                }).done(function(resp) {
                    self.lastAddress = address;
                    self.lastResult = {
                        status: resp.isBlacklisted === true ? RESULT_BLACKLISTED : resp.inUse === true ? RESULT_USED : RESULT_OK,
                        recipientID: resp.existingRecipientId || 0
                    };
                    self.report();
                });
            } catch (e) {
                self.running = false;
            }
        }
    };
    AddressChecker.prototype.check = function(address) {
        address = address ? address.trim() : "";
        if (address) {
            if (this.lastAddress == address) {
                this.report();
            } else {
                this.scheduleCheck(address);
            }
        } else {
            this.report(RESULT_OK);
        }
    };
    AddressChecker.prototype.report = function(result) {
        if (arguments.length) {
            this.callback.call(null, result);
        } else {
            if (this.lastAddress) {
                this.report(this.lastResult);
            }
        }
    };
});

AGN.Lib.Controller.new("reference-table-settings-modal", function() {
    $(document).on("shown.bs.modal", ".modal[reference-table-settings-modal]", function() {
        var modalInputs = $(this).find("input[data-associated-with], select[data-associated-with]");
        modalInputs.each(function() {
            var input = $(this);
            var associatedWithField = $(input.data("associated-with"));
            if (input.is(":checkbox")) {
                input.prop("checked", associatedWithField.val() === "true");
            } else {
                input.val(associatedWithField.val());
            }
        });
    });
    this.addAction({
        click: "apply-button"
    }, function() {
        var $button = $(this.el);
        var agnForm = AGN.Lib.Form.get($button);
        var valid = agnForm.validate();
        if (valid) {
            var modalInputs = $button.closest(".modal").find("input[data-associated-with], select[data-associated-with]");
            modalInputs.each(function() {
                var input = $(this);
                var associatedWithField = $(input.data("associated-with"));
                if (input.is(":checkbox")) {
                    associatedWithField.val(input.prop("checked"));
                } else {
                    associatedWithField.val(input.val());
                }
            });
            AGN.Lib.Modal.getWrapper($button).modal("hide");
        }
    });
});

AGN.Lib.Controller.new("sidemenu", function() {
    var STATUSPANEL_HEIGHT_PX = 20;
    var WebStorage = AGN.Lib.WebStorage;
    var submenuCloseDelay = 500;
    var tooltipCloseDelay = 400;
    var submenuOpenDelay = 1e3 / 3;
    this.addAction({
        mouseenter: "activateSubmenu"
    }, function() {
        var $item = $(this.el).find(".menu-item");
        var $submenu = $item.next(".submenu");
        var $subitems = $submenu.find(".subitems");
        $(".submenu.open").not($submenu).each(function() {
            closeSubmenu($(this));
        });
        if (!checkIfSidebarIsWide()) {
            clearTimeout($item.data("closeTimerId"));
            $submenu.addClass("open");
            var $arrow = $submenu.find(".arrow");
            setSubmenuOffset($arrow, $submenu, $item);
            setArrowOffset($arrow, $submenu, $item);
            $item.data("openTimerId", setTimeout(function() {
                if ($submenu.is(".open")) {
                    $subitems.addClass("open");
                }
            }, submenuOpenDelay));
        }
    });
    this.addAction({
        click: "switch-to-new-design"
    }, function() {
        const $el = this.el;
        $.post(AGN.url("/ui-design/switch.action")).done(function() {
            $el.prop("disabled", true);
            window.setTimeout(function() {
                AGN.Lib.Page.reload($el.data("switch-url"));
            }, 500);
        }).fail(function() {
            $el.prop("checked", !$el.prop("checked"));
        });
    });
    this.addAction({
        mouseleave: "activateSubmenu"
    }, function() {
        var $item = $(this.el).find(".menu-item");
        var $submenu = $item.next(".submenu");
        var $subitems = $submenu.find(".subitems");
        if (!checkIfSidebarIsWide()) {
            clearTimeout($item.data("openTimerId"));
            var closeDelay = $subitems.is(".open") ? submenuCloseDelay : tooltipCloseDelay;
            $item.data("closeTimerId", setTimeout(function() {
                closeSubmenu($submenu);
            }, closeDelay));
        }
    });
    this.addAction({
        click: "expandMenu"
    }, function() {
        if (checkIfSidebarIsWide()) {
            collapseMenu();
        } else {
            expandMenu();
        }
        $(window).trigger("viewportChanged");
    });
    function closeSubmenu($submenu) {
        $submenu.removeClass("open");
        $submenu.find(".subitems").removeClass("open");
    }
    function setSubmenuOffset($arrow, $submenu, $menuItem) {
        var $header = $submenu.find(".submenu-header");
        var top = $menuItem.scrollTop() + $menuItem.offset().top + $menuItem.outerHeight() / 2 - $header.outerHeight() / 2;
        var left = $menuItem.offset().left + $menuItem.outerWidth() + $arrow.outerWidth();
        var $window = $(window);
        var subMenuHeight = $header.outerHeight() + getSubitemsHeight($submenu);
        if (top + subMenuHeight > $window.height() + $window.scrollTop()) {
            top = $window.height() + $window.scrollTop() - subMenuHeight - STATUSPANEL_HEIGHT_PX;
        }
        if (top - $window.scrollTop() < 0) {
            top = $window.scrollTop();
        }
        $submenu.offset({
            top: top,
            left: left
        });
    }
    function getSubitemsHeight($submenu) {
        return $submenu.find(".subitems").find("li").first().height() * $submenu.find(".subitems").find("li").length;
    }
    function setArrowOffset($arrow, $submenu, $menuItem) {
        var top = $menuItem.offset().top + $menuItem.outerHeight() / 2 - $arrow.outerHeight() / 2;
        $arrow.offset({
            top: top,
            left: $arrow.offset().left
        });
    }
    function expandMenu() {
        saveIfSidebarIsWide(true);
        $("body").addClass("wide-sidebar");
    }
    function collapseMenu() {
        saveIfSidebarIsWide(false);
        $("body").removeClass("wide-sidebar");
    }
    function saveIfSidebarIsWide(val) {
        if (val !== true) {
            val = false;
        }
        WebStorage.set("is-wide-sidebar", {
            value: val
        });
        $.ajax(AGN.url("/sidebar/ajax/setIsWide.action"), {
            type: "GET",
            data: {
                isWide: val
            }
        });
    }
    function checkIfSidebarIsWide() {
        return $("body").hasClass("wide-sidebar");
    }
});

AGN.Lib.Controller.new("support", function() {
    var Form = AGN.Lib.Form, Popover = AGN.Lib.Popover, JsonMessages = AGN.Lib.JsonMessages;
    function updateContentLengthIndicator() {
        var content = $("#support-mail-text").val();
        var length = 0;
        if (content) {
            length = content.length;
        }
        $("#support-message-length").text(t("fields.content.charactersEntered", length));
    }
    this.addDomInitializer("support", function() {
        updateContentLengthIndicator();
        $("#support-mail-text").on("change input", _.throttle(function() {
            updateContentLengthIndicator();
        }, 100));
    });
    this.addAction({
        submission: "send-support-request"
    }, function() {
        this.event.preventDefault();
        Form.get(this.el).submit();
    });
    this.addAction({
        submitted: "send-support-request"
    }, function() {
        if (this.data.success) {
            var popover = Popover.get(this.el);
            if (popover) {
                popover.hide();
            }
        }
        JsonMessages(this.data.popups);
    });
});

AGN.Lib.Controller.new("target-create-mailinglist", function() {
    this.addAction({
        click: "select-mediatype"
    }, function() {
        var $form = this.el.closest("form");
        var $okButton = $form.find("#createMailinglistOkBtn");
        if (!$form.find('input:checked[name="mediatypes"]').length) {
            $okButton.attr("disabled", "disabled");
        } else {
            $okButton.removeAttr("disabled");
        }
    });
});

AGN.Lib.Controller.new("target-scheduler", function() {
    var ScheduleTimeTable = AGN.Lib.ScheduleTimeTable, PeriodRow = AGN.Lib.ScheduleTimeTable.PeriodRow;
    var scheduleTimeTable;
    this.addAction({
        submission: "save-scheduler-data"
    }, function() {
        var form = AGN.Lib.Form.get($(this.el));
        form.setValueOnce("intervalAsJson", scheduleTimeTable.getSubmissionJson("period"));
        form.submit();
    });
    this.addDomInitializer("target-scheduler-init", function($el) {
        var data = $el.json();
        if (scheduleTimeTable) {
            scheduleTimeTable.clean();
        }
        scheduleTimeTable = new ScheduleTimeTable($("#tile-schedule-time"));
        var period = [];
        if (data.intervalAsJson) {
            period = JSON.parse(data.intervalAsJson).map(function(object) {
                return PeriodRow.deserialize(object);
            });
        }
        period.forEach(function(day) {
            scheduleTimeTable.addRow(day);
        });
        if (period.length === 0) {
            scheduleTimeTable.addEmptyPeriodRow();
        }
        var form = AGN.Lib.Form.get($el);
        form.initFields();
    });
});

AGN.Lib.Controller.new("target-group-view", function($scope) {
    var Action = AGN.Lib.Action, Form = AGN.Lib.Form, Editor = AGN.Lib.Editor;
    Action.new({
        "qb:invalidrules": "#targetgroup-querybuilder"
    }, function() {
        AGN.Lib.Messages(t("defaults.error"), t("querybuilder.errors.general"), "alert");
    });
    this.addDomInitializer("target-group-view", function() {
        var $el = $(this.el);
        $("[data-toggle-tab]").on("click", function(e) {
            var isValid = Form.get($el).validate({
                skip_empty: true
            });
            if (!isValid) {
                e.preventDefault();
                return false;
            }
        });
        if (this.config.errorPositionDetails) {
            handleEqlErrorDetails(this.config.errorPositionDetails);
        }
    });
    this.addAction({
        click: "switch-tab-viewEQL"
    }, function() {
        var element = this.el, form = AGN.Lib.Form.get($(element));
        form.setValueOnce("viewFormat", "EQL");
        form.submit("", {
            skip_empty: true
        });
    });
    this.addAction({
        click: "switch-tab-viewQB"
    }, function() {
        var element = this.el, form = AGN.Lib.Form.get($(element));
        form.setValueOnce("viewFormat", "QUERY_BUILDER");
        const jqxhr = form.submit("", {
            skip_empty: true
        });
        jqxhr.done(function(resp) {
            handleFormSaveResponse(resp);
            AGN.Lib.Tab.show($("#eql-editor-tab-trigger"));
            $("#eql-alert").remove();
            $("#eql").before(getNotificationMessage(resp.popups.alert[0]));
        });
    });
    this.addAction({
        submission: "save-target"
    }, function() {
        Form.get(this.el).submit(this.el.data("submit-type")).done(handleFormSaveResponse);
    });
    function handleFormSaveResponse(resp) {
        if (resp.success) {
            return;
        }
        handleEqlErrorDetails(resp.data);
        AGN.Lib.JsonMessages(resp.popups);
    }
    function handleEqlErrorDetails(details) {
        const eqlEditor = Editor.get($("#eql")).editor;
        eqlEditor.focus();
        eqlEditor.gotoLine(details.line, details.column);
    }
    function getNotificationMessage(msg) {
        return '<ul = id="eql-alert">' + '         <div class="tile">' + '             <li class="tile-notification tile-notification-alert">' + msg + "</li>" + "         </div>" + "    </ul>";
    }
});

AGN.Lib.Controller.new("template-css", function() {
    this.addAction({
        click: "updatePreview"
    }, function() {
        var $previewForm = $("#layoutPreviewForm");
        $previewForm.find('input[name="css"]').val($("#cssContents").val());
        $previewForm.submit();
    });
    this.addAction({
        click: "saveLayoutCss"
    }, function() {
        var formObj = AGN.Lib.Form.get($("#gridTemplateForm"));
        var mailingsIds = $('#save-css-approve-modal-form select[name="templatesToUpdate"]').val();
        var currentTemplateId = formObj.getValue("templateId");
        if (currentTemplateId) {
            mailingsIds.push(currentTemplateId);
        }
        formObj.setValueOnce("bulkIds", mailingsIds);
        formObj.submit();
    });
});

AGN.Lib.Controller.new("template-outer-html-edit", function() {
    this.addAction({
        click: "updatePreview"
    }, function() {
        var $previewForm = $("#layoutPreviewForm");
        $previewForm.find('input[name="outerHTML"]').val($("#templateOuterHTML").val());
        $previewForm.submit();
    });
    this.addAction({
        click: "saveOuterHTML"
    }, function() {
        $("#gridTemplateForm").submit();
    });
});

AGN.Lib.Controller.new("template-styles", function() {
    function updatePreview() {
        var $templateForm = $("form#gridTemplateForm");
        var $previewForm = $("form#layoutPreviewForm");
        var $sources = $templateForm.find('input[name^="styles."]');
        $.each($sources, function(index, source) {
            var $source = $(source);
            var name = $source.attr("name");
            var $destination = $previewForm.find('input[name="' + name + '"]');
            $destination.val($source.val());
        });
        $previewForm.submit();
    }
    this.addAction({
        submission: "updatePreview"
    }, function() {
        updatePreview();
    });
    this.addAction({
        click: "updateLayoutPreview"
    }, function() {
        updatePreview();
    });
    this.addAction({
        click: "saveLayoutStyles"
    }, function() {
        $("form#gridTemplateForm").submit();
    });
});

AGN.Lib.Controller.new("trackable-link-list", function() {
    var scrollToElemId;
    var KEEP_UNCHANGED;
    AGN.Opt.DefaultExtensions = {};
    var TrackableLinkExtensions = new AGN.Lib.TrackableLinkExtensions();
    var SAVE_ALL_URL;
    this.addDomInitializer("trackable-link-list", function() {
        KEEP_UNCHANGED = this.config.KEEP_UNCHANGED;
        SAVE_ALL_URL = this.config.SAVE_ALL_URL;
        AGN.Opt.DefaultExtensions = this.config.defaultExtensions;
        if (this.config.scrollToLinkId) {
            scrollTo($("#link-" + this.config.scrollToLinkId));
        }
    });
    this.addDomInitializer("trackable-link-extensions", function() {
        TrackableLinkExtensions.load(this.config.extensions, getExtensionsTable());
    });
    AGN.Lib.Action.new({
        change: "[id^=link-], #tile-trackableLinkEditAll"
    }, function() {
        scrollToElemId = this.el.attr("id");
    });
    this.addAction({
        scrollTo: "scroll-to"
    }, function() {
        if (scrollToElemId) {
            scrollTo($(this.el).find("#" + scrollToElemId));
        }
    });
    this.addAction({
        click: "save-bulk-actions",
        enterdown: "description-enterdown, bulkActionExtensionsEnterdown"
    }, function() {
        var form = AGN.Lib.Form.get($("#trackableLinkForm"));
        var bulkActionsFormData = $("#bulkActionsForm").serializeFormDataObject();
        form._data = {};
        $.each(bulkActionsFormData, function(k, v) {
            form.setValue(k, v);
        });
        form.setValue("modifyAllLinksExtensions", false);
        setExtensionsToForm(form);
        form.setActionOnce(SAVE_ALL_URL);
        form.submit();
        AGN.Lib.Modal.getWrapper(this.el).modal("hide");
    });
    this.addAction({
        click: "save",
        enterdown: "settingsExtensionsEnterdown"
    }, function() {
        this.event.preventDefault();
        var form = AGN.Lib.Form.get($("#trackableLinkForm"));
        form._data = {};
        form.setValue("modifyBulkLinksExtensions", false);
        keepBulkSettingsUnchanged(form);
        setExtensionsToForm(form);
        form.setActionOnce(SAVE_ALL_URL);
        form.submit();
    });
    function scrollTo($target) {
        if ($target && $target.length > 0) {
            var $scrollContainer = $target.closest('[data-sizing="scroll"]');
            if ($scrollContainer.length > 0) {
                var highestOffsetTop = $scrollContainer.find(":first-child").offset().top;
                var targetOffsetTop = $target.offset().top;
                $scrollContainer.scrollTop(0);
                $scrollContainer.scrollTop(targetOffsetTop - highestOffsetTop);
            }
        }
    }
    function setExtensionsToForm(form) {
        _.each(TrackableLinkExtensions.collect(), function(extension, index) {
            form.setValue("extensions[" + index + "].name", extension.name);
            form.setValue("extensions[" + index + "].value", extension.value);
        });
    }
    function keepBulkSettingsUnchanged(form) {
        form.setValue("bulkUsage", KEEP_UNCHANGED);
        form.setValue("bulkAction", KEEP_UNCHANGED);
        form.setValue("bulkDeepTracking", KEEP_UNCHANGED);
        form.setValue("bulkStatic", KEEP_UNCHANGED);
    }
    function getExtensionsTable() {
        return isModalOpened() ? $("#bulkActionExtensions tbody") : $("#settingsExtensions tbody");
    }
    function isModalOpened() {
        return $(".modal").is(":visible");
    }
});

AGN.Lib.Controller.new("trackable-link", function() {
    var self = this;
    var TrackableLinkExtensions = new AGN.Lib.TrackableLinkExtensions();
    this.addDomInitializer("trackable-link-extensions", function() {
        TrackableLinkExtensions.load(this.config.extensions, $("#extensions tbody"));
    });
    this.addAction({
        click: "save"
    }, function() {
        this.event.preventDefault();
        var form = AGN.Lib.Form.get($("#trackableLinkForm"));
        setExtensionsToForm(form);
        form.submit("static");
    });
    function setExtensionsToForm(form) {
        _.each(TrackableLinkExtensions.collect(), function(extension, index) {
            form.setValue("extensions[" + index + "].name", extension.name);
            form.setValue("extensions[" + index + "].value", extension.value);
        });
    }
    this.addAction({
        change: "link-details-trackable"
    }, function() {
        self.runInitializer("trackableAction");
    });
    this.addInitializer("trackableAction", function($scope) {
        var $trigger = $('[data-action="link-details-trackable"] :selected');
        var $linkAction = $("#linkAction");
        $linkAction.prop("disabled", $linkAction.prop("disabled") || $trigger.val() == 0);
    });
});

AGN.Lib.Controller.new("user|groups-permissions", function() {
    var permissions;
    this.addDomInitializer("user|groups-permissions", function() {
        permissions = this.config.permissionCategories.map(function(permission) {
            return permission.subCategories;
        }).flatMap(function(subcategories) {
            return Object.values(subcategories);
        }).flatMap(function(subcategory) {
            return subcategory.permissions;
        });
    });
    this.addAction({
        click: "reset-filter"
    }, function() {
        $("#permission-filter").val("").trigger("change");
        showAllCategories();
        showAllPermissions();
    });
    function showPermissionsByFilters(filters) {
        permissions.filter(function(permission) {
            return shouldBeShownByFilters(permission, filters);
        }).forEach(function(permission) {
            $('[id="' + permission.name + '"]').closest("li").show();
        });
    }
    this.addAction({
        click: "apply-filter"
    }, function() {
        var filters = $("#permission-filter").val();
        if (!filters.length) {
            return;
        }
        hideAllPermissions();
        showPermissionsByFilters(filters);
        controlCategoriesDisplaying();
    });
    function shouldBeShownByFilters(permission, filters) {
        var shouldBeShown = false;
        filters.forEach(function(filter) {
            if (getPredicateByFilter(filter)(permission)) {
                shouldBeShown = true;
            }
        });
        return shouldBeShown;
    }
    function getPredicateByFilter(filter) {
        switch (filter) {
          case "granted":
            return function(permission) {
                return permission.granted;
            };

          case "grantedForUser":
            return function(permission) {
                return permission.granted && !permission.showInfoTooltip;
            };

          case "grantedByGroup":
            return function(permission) {
                return permission.showInfoTooltip;
            };

          case "grantable":
            return function(permission) {
                return !permission.granted && permission.changeable;
            };

          case "notGrantable":
            return function(permission) {
                return !permission.granted && !permission.changeable;
            };

          case "new":
            return function(permission) {
                return permission.recent;
            };

          default:
            return function() {
                return true;
            };
        }
    }
    function showAllSubCategories() {
        $(".sub-category-header").each(function() {
            return $(this).show();
        });
    }
    function showAllCategoriesTiles() {
        getCategoriesTiles$().each(function() {
            this.show();
        });
    }
    function getCategoriesTiles$() {
        return $(".permission-categories-tile").map(function() {
            return $(this);
        });
    }
    function controlCategoriesDisplaying() {
        showAllCategories();
        getCategoriesTiles$().each(function() {
            this.toggle(this.has(".list-group-item:visible").length > 0);
        });
        $(".sub-category-header").each(function() {
            return $(this).toggle($(this).next("div").find("li:visible").length > 0);
        });
    }
    function showAllCategories() {
        showAllCategoriesTiles();
        showAllSubCategories();
    }
    function showAllPermissions() {
        $(".list-group-item").each(function() {
            $(this).show();
        });
    }
    function hideAllPermissions() {
        $(".list-group-item").each(function() {
            $(this).hide();
        });
    }
});

AGN.Lib.Controller.new("userform-view", function() {
    var FormBuilder = AGN.Lib.FormBuilder.FormBuilder;
    var Editor = AGN.Lib.Editor;
    var Confirm = AGN.Lib.Confirm;
    var actionURLPattern;
    var formId = 0;
    this.addDomInitializer("userform-view", function() {
        var config = this.config;
        actionURLPattern = config.actionURLPattern;
        formId = config.formId;
        $("#userFormForm").dirty();
    });
    this.addAction({
        click: "activate-and-test"
    }, function() {
        const $el = this.el;
        const url = $el.attr("href");
        Confirm.createFromTemplate({}, "userform-activate-and-test").done(function() {
            $.post(AGN.url("/webform/" + formId + "/activate.action")).done(function(resp) {
                AGN.Lib.JsonMessages(resp.popups, true);
                if (resp.success) {
                    $("#is-active-switch").prop("checked", true);
                    $el.removeAttr("data-action");
                    window.open(url, "_blank");
                }
            });
        });
    });
    this.addAction({
        change: "change-intro-action"
    }, function() {
        var link = $("#startActionLink");
        var actionId = this.el.val();
        changeLinkState(link, actionId);
    });
    this.addAction({
        change: "change-final-action"
    }, function() {
        var $link = $("#finalActionLink");
        var actionId = this.el.val();
        changeLinkState($link, actionId);
    });
    this.addAction({
        click: "check-velocity-script"
    }, function() {
        var $el = $(this.el);
        var options = AGN.Lib.Helpers.objFromString($el.data("action-options"));
        checkVelocityScripts(options.type);
    });
    this.addAction({
        click: "saveUserForm"
    }, function() {
        var successFBChanged = isFormbuilderChanged("successFormBuilder");
        var errorFBChanged = isFormbuilderChanged("errorFormBuilder");
        var isSuccessTabsDiffContent = successFBChanged && isTemplateCodeChanged("successTemplate");
        var isErrorTabsDiffContent = errorFBChanged && isTemplateCodeChanged("errorTemplate");
        if (isSuccessTabsDiffContent || isErrorTabsDiffContent) {
            Confirm.createFromTemplate({
                needSuccessCodeChoose: isSuccessTabsDiffContent,
                needErrorCodeChoose: isErrorTabsDiffContent
            }, "warning-save-different-tabs");
        } else {
            var successMode = successFBChanged ? "FORM_BUILDER" : "HTML";
            var errorMode = errorFBChanged ? "FORM_BUILDER" : "HTML";
            save(successMode, errorMode);
        }
    });
    this.addAction({
        click: "save-specific-code-mode"
    }, function() {
        var $form = $("#choose-code-format-modal-form");
        var successMode = $form.find('[name="success_template_mode"]:checked').val();
        var errorMode = $form.find('[name="error_template_mode"]:checked').val();
        save(successMode, errorMode);
    });
    this.addAction({
        change: "formTestRecipient"
    }, function() {
        var $a = $("#formTestLink");
        var $s = $("#formTestRecipient");
        $a.attr("href", $s.val());
    });
    function isTemplateCodeChanged(editorId) {
        var ckeditor = CKEDITOR.instances[editorId];
        if (ckeditor) {
            ckeditor.updateElement();
        }
        return $("#userFormForm").dirty("isFieldDirty", $("#" + editorId));
    }
    function isFormbuilderChanged(id) {
        if (FormBuilder.isCreated("#" + id)) {
            return FormBuilder.get("#" + id).isChanged();
        }
        return false;
    }
    function save(successCodeMode, errorCodeMode) {
        var form = AGN.Lib.Form.get($("form#userFormForm"));
        if (FormBuilder.isCreated("#successFormBuilder")) {
            var successFB = FormBuilder.get("#successFormBuilder");
            if (successCodeMode === "FORM_BUILDER") {
                Editor.get($("#successTemplate")).val(successFB.generateHtml());
            }
            var successFormBuilderJson = successFB.getJson();
            form.setValueOnce("successSettings.formBuilderJson", successFormBuilderJson);
            var successFormDisabledFields = $("#successFormBuilder").find("input:enabled,select:enabled");
            successFormDisabledFields.prop("disabled", true);
        }
        if (FormBuilder.isCreated("#errorFormBuilder")) {
            var errorFB = FormBuilder.get("#errorFormBuilder");
            if (errorCodeMode === "FORM_BUILDER") {
                Editor.get($("#errorTemplate")).val(errorFB.generateHtml());
            }
            var errorFormBuilderJson = errorFB.getJson();
            form.setValueOnce("errorSettings.formBuilderJson", errorFormBuilderJson);
            var errorFormDisabledFields = $("#errorFormBuilder").find("input:enabled,select:enabled");
            errorFormDisabledFields.prop("disabled", true);
        }
        form.submit();
        if (successFormDisabledFields) {
            successFormDisabledFields.prop("disabled", false);
        }
        if (errorFormDisabledFields) {
            errorFormDisabledFields.prop("disabled", false);
        }
    }
    function checkVelocityScripts(type) {
        var text = AGN.Lib.Editor.get($("#" + type + "Template")).val();
        if (text.match(/#(?:set|include|macro|parse|if|foreach)/gi)) {
            AGN.Lib.Messages(t("defaults.error"), t("userform.error.velocity_not_allowed"), "alert");
            var link = $('[data-toggle-tab="#tab-' + type + '-template-html"]');
            if (link) {
                link.trigger("click");
            }
        }
    }
    function changeLinkState($link, actionId) {
        if ($link.exists()) {
            if (actionId > 0) {
                $link.attr("href", actionURLPattern.replace(":action-ID:", actionId));
                $link.removeClass("hidden");
            } else {
                $link.attr("href", "#");
                $link.addClass("hidden");
            }
        }
    }
});

AGN.Lib.Controller.new("workflow-list", function() {
    var config = null;
    function getTableApi() {
        var $table = $(".js-data-table-body");
        if ($table.exists()) {
            var table = $table.data("_table");
            if (table && table.api) {
                return table.api;
            }
        }
        return null;
    }
    this.addDomInitializer("workflow-list", function() {
        config = this.config;
    });
    function requestBulk(ids, url) {
        var deferred = $.Deferred();
        if (ids && ids.length) {
            var jqxhr = $.ajax(url, {
                method: "POST",
                traditional: true,
                data: {
                    bulkIds: ids
                }
            }).fail(function() {
                deferred.reject();
            });
            AGN.Lib.Confirm.request(jqxhr).then(deferred.resolve, deferred.reject);
        } else {
            deferred.reject();
            AGN.Lib.Messages(t("Error"), t("messages.error.nothing_selected"), "alert");
        }
        return deferred.promise();
    }
    this.addAction({
        click: "bulk-delete"
    }, function() {
        var api = getTableApi();
        if (api) {
            var rows = api.getSelectedRows();
            var ids = rows.map(function(row) {
                return row.id;
            });
            requestBulk(ids, config.urls.WORKFLOW_BULK_DELETE).done(function() {
                api.updateRowData({
                    remove: rows
                });
            });
        }
    });
    this.addAction({
        click: "bulk-deactivate"
    }, function() {
        var api = getTableApi();
        if (api) {
            var rows = api.getSelectedRows();
            var rowNodes = api.getSelectedNodes();
            var ids = rows.map(function(row) {
                return row.id;
            });
            requestBulk(ids, config.urls.WORKFLOW_BULK_DEACTIVATE).done(function() {
                rowNodes.forEach(function(row) {
                    row.setDataValue("status", {
                        name: "inactive",
                        messageKey: "default.status.inActive"
                    });
                });
                api.refreshClientSideRowModel("filter");
                api.deselectAll();
            });
        }
    });
});

AGN.Lib.Controller.new("workflow-view", function() {
    var Def = AGN.Lib.WM.Definitions, Editor = AGN.Lib.WM.Editor, Node = AGN.Lib.WM.Node, EditorsHelper = AGN.Lib.WM.EditorsHelper, MailingEditorHelper = AGN.Lib.WM.MailingEditorHelper, Dialogs = AGN.Lib.WM.Dialogs, MailingSelector = AGN.Lib.WM.MailingSelector, Confirm = AGN.Lib.Confirm, Template = AGN.Lib.Template, Utils = AGN.Lib.WM.Utils, Select = AGN.Lib.Select, DateTimeUtils = AGN.Lib.WM.DateTimeUtils, Form = AGN.Lib.Form;
    var controller = this;
    var editor;
    if (!jsPlumb.Connectors["FixedBezierConnector"]) {
        jsPlumbUtil.extend(AGN.Opt.Components.JsPlumbFixedBezierConnector, jsPlumb.Connectors.AbstractConnector);
        jsPlumb.Connectors["FixedBezierConnector"] = AGN.Opt.Components.JsPlumbFixedBezierConnector;
    }
    this.addDomInitializer("workflow-view", function() {
        var config = this.config;
        Def.constants = config.constants;
        Def.workflowId = config.workflowId;
        Def.shortname = config.shortname;
        Def.statisticUrl = config.statisticUrl;
        var nodes = config.icons.map(Node.deserialize);
        var connections = Node.deserializeConnections(config.icons, Node.toMap(nodes));
        if (editor) {
            editor.recycle();
        }
        editor = new Editor(config.isEditable !== false, config.isContextMenuEnabled !== false, config.isFootnotesEnabled === true);
        editor.setOnInitialized(function() {
            editor.batch(function() {
                nodes.forEach(function(node) {
                    editor.add(node);
                });
                connections.forEach(function(connection) {
                    editor.connect(connection.source, connection.target);
                });
            });
            editor.updateNodeTitles();
            editor.updateFootnotes();
            if (Def.workflowId === 0) {
                Def.intialSchema = editor.serializeIcons();
            }
        });
        editor.setMinimapEnabled(config.isMinimapEnabled !== false);
        var slider = $("#slider");
        if (slider.exists()) {
            slider.slider({
                min: Def.MIN_ZOOM,
                max: Def.MAX_ZOOM,
                value: Def.DEFAULT_ZOOM,
                step: Def.ZOOM_STEP,
                create: function() {
                    var slider = $(this).slider("instance");
                    editor.setZoom(Def.DEFAULT_ZOOM);
                    editor.setOnZoom(function(scale) {
                        slider.value(scale);
                    });
                },
                slide: function(event, ui) {
                    editor.setZoom(ui.value);
                }
            });
        }
        if (config.fitPdfPage === true) {
            editor.fitPdfPage();
        }
        window.status = config.initializerFinishStatus || "";
    });
    this.addDomInitializer("mailing-data-transfer-modal", function($e) {
        var $inputsPerParam = $e.find("input[data-mailing-param]");
        var $all = $e.find("#transferAllSettings");
        var checkedParamsMap = {};
        var checkedParams = [];
        $inputsPerParam.on("change", function() {
            var $checkbox = $(this);
            var param = $checkbox.data("mailing-param");
            if ($checkbox.prop("checked")) {
                checkedParamsMap[param] = true;
            } else {
                delete checkedParamsMap[param];
            }
            checkedParams = Object.keys(checkedParamsMap);
            $all.prop("checked", checkedParams.length == $inputsPerParam.length);
        });
        $all.on("change", function() {
            var isChecked = $all.prop("checked");
            $inputsPerParam.prop("checked", isChecked);
            if (isChecked) {
                $inputsPerParam.each(function() {
                    checkedParamsMap[$(this).data("mailing-param")] = true;
                });
                checkedParams = Object.keys(checkedParamsMap);
            } else {
                checkedParamsMap = {};
                checkedParams = [];
            }
        });
        this.addAction({
            click: "transfer-mailing-data"
        }, function() {
            Confirm.get($e).positive(checkedParams);
        });
    });
    this.addDomInitializer("own-workflow-expanding-modal", function($e) {
        var $select = $e.find("#workflow-select");
        var $radios = $e.find('input[name="copyContent"]');
        this.addAction({
            click: "expand-own-workflow"
        }, function() {
            Confirm.get($e).positive({
                workflowId: $select.val(),
                copyContent: $radios.filter(":checked").val() == "true"
            });
        });
    });
    this.addDomInitializer("icon-comment-editor-initializer", function() {
        var nodeEditor = EditorsHelper.registerEditor("icon-comment", {
            formName: "iconCommentForm",
            safeToSave: true,
            fillEditor: function(node) {
                $("#iconComment").val(node.getComment());
            },
            saveEditor: function() {
                EditorsHelper.saveIconComment($("#iconComment").val());
                this.cancelEditor();
            },
            cancelEditor: function() {
                $("#icon-comment-editor").dialog("close");
                return false;
            }
        });
        controller.addAction({
            click: "icon-comment-editor-save"
        }, function() {
            nodeEditor.saveEditor();
        });
        controller.addAction({
            click: "icon-comment-editor-cancel"
        }, function() {
            nodeEditor.cancelEditor();
        });
    });
    this.addDomInitializer("parameter-editor-initializer", function() {
        EditorsHelper.registerEditor("parameter", {
            formName: "parameterForm",
            getTitle: function() {
                return t("workflow.parameter");
            },
            fillEditor: function(node) {
                var $form = $('form[name="' + this.formName + '"]');
                Select.get($form.find("select[name=value]")).setOptions(editor.getParametersOptions(node));
                var data = node.getData();
                $form.submit(false);
                $form.get(0).reset();
                EditorsHelper.fillFormFromObject(this.formName, data, "");
            },
            saveEditor: function() {
                return EditorsHelper.formToObject(this.formName);
            }
        });
        controller.addAction({
            click: "parameter-editor-save"
        }, function() {
            EditorsHelper.saveCurrentEditorWithUndo();
        });
    });
    this.addDomInitializer("deadline-editor-initializer", function() {
        var nodeEditor = EditorsHelper.registerEditor("deadline", {
            panelIds: [ "fixedDeadlinePanel", "delayDeadlinePanel" ],
            timeUnitIds: [ "deadlineTimeUnitMinute", "deadlineTimeUnitHour", "deadlineTimeUnitDay", "deadlineTimeUnitWeek", "deadlineTimeUnitMonth" ],
            formName: "deadlineForm",
            getDefaultDelayData: function(deadlineType) {
                var defaultData = {};
                if (deadlineType === Def.constants.deadlineTypeDelay && this.isPrecededByImportIcon) {
                    defaultData = {
                        timeUnit: Def.constants.deadlineTimeUnitHour,
                        delayValue: Def.constants.defaultImportDelayLimit
                    };
                }
                return defaultData;
            },
            getTitle: function() {
                return t("workflow.deadline.title");
            },
            fillEditor: function(node) {
                var data = node.getData();
                $("#deadline-editor").find(".editor-error-messages").css("display", "none");
                this.isPrecededByImportIcon = this.checkPrecededByImportIcon(node);
                var $form = $('form[name="' + this.formName + '"]');
                $form.submit(false);
                $('form[name="' + this.formName + '"] #deadlineDate').pickadate("picker").set("select", this.dateAsUTC(data.date || new Date()));
                this.fillDelayData($form, data);
                $('form[name="' + this.formName + '"] #time').val(("0" + data.hour).slice(-2) + ":" + ("0" + data.minute).slice(-2));
            },
            fillDelayData: function($form, data) {
                $form.get(0).reset();
                var type = $('form[name="' + this.formName + '"] input[name="deadlineType"]:checked').val();
                var defaultValues = this.getDefaultDelayData(type);
                EditorsHelper.fillFormFromObject(this.formName, data, "", defaultValues);
                this.updateVisibility();
                var delayValue = data.delayValue || defaultValues.delayValue;
                EditorsHelper.initSelectWithValueOrChooseFirst($('form[name="' + this.formName + '"] select[name="delayValue"]'), delayValue);
            },
            saveEditor: function() {
                var data = EditorsHelper.formToObject(this.formName);
                var time = $('form[name="' + this.formName + '"] #time').val();
                data.date = $('form[name="' + this.formName + '"] #deadlineDate').pickadate("picker").get("select").obj;
                data.hour = time.substring(0, 2);
                data.minute = time.substring(3, 5);
                return data;
            },
            updateVisibility: function() {
                var $form = $('form[name="' + this.formName + '"]');
                var type = $form.find('input[name="deadlineType"]:checked').val();
                if (this.checkPresentNodeOfType([ Def.NODE_TYPE_ACTION_BASED_MAILING, Def.NODE_TYPE_DATE_BASED_MAILING ])) {
                    $form.find("input#typeFixedDeadline").parent().parent().parent().hide();
                    $form.find('input[value="' + Def.constants.deadlineTypeDelay + '"]').prop("checked", true);
                    type = Def.constants.deadlineTypeDelay;
                } else {
                    $form.find("input#typeFixedDeadline").parent().parent().parent().show();
                }
                if (type === Def.constants.deadlineTypeDelay) {
                    this.switchPanelsVisibility("delayDeadlinePanel");
                    this.switchTimeContainerVisibility(false);
                    var timeUnit = $form.find('select[name="timeUnit"]').val();
                    switch (timeUnit) {
                      case Def.constants.deadlineTimeUnitMinute:
                        this.switchTimeUnitsVisibility("deadlineTimeUnitMinute");
                        break;

                      case Def.constants.deadlineTimeUnitHour:
                        this.switchTimeUnitsVisibility("deadlineTimeUnitHour");
                        break;

                      case Def.constants.deadlineTimeUnitDay:
                        this.switchTimeUnitsVisibility("deadlineTimeUnitDay");
                        this.switchTimeContainerVisibility(true);
                        $("#deadlineTimeHelp").removeAttr("style");
                        break;

                      case Def.constants.deadlineTimeUnitWeek:
                        this.switchTimeUnitsVisibility("deadlineTimeUnitWeek");
                        break;

                      case Def.constants.deadlineTimeUnitMonth:
                        this.switchTimeUnitsVisibility("deadlineTimeUnitMonth");
                        break;
                    }
                    $form.find('input[name="useTime"]').css("display", "inline");
                } else if (type === Def.constants.deadlineTypeFixedDeadline) {
                    this.switchPanelsVisibility("fixedDeadlinePanel");
                    this.switchTimeContainerVisibility(true);
                    this.hideDiv("deadlineTimeHelp");
                    $form.find('input[name="useTime"]').css("display", "none");
                }
            },
            switchPanelsVisibility: function(selectedPanelId) {
                var self = this;
                this.panelIds.forEach(function(itemId) {
                    if (itemId !== selectedPanelId) {
                        self.hideDiv(itemId);
                    }
                });
                this.showDiv(selectedPanelId);
            },
            switchTimeUnitsVisibility: function(selectedTimeUnitId) {
                var self = this;
                this.timeUnitIds.forEach(function(itemId) {
                    if (itemId !== selectedTimeUnitId) {
                        self.hideDiv(itemId);
                        $("#" + itemId + " select").removeAttr("name");
                    }
                });
                this.showDiv(selectedTimeUnitId);
                $("#" + selectedTimeUnitId + " select").attr("name", "delayValue");
            },
            switchTimeContainerVisibility: function(isVisible) {
                var self = this;
                if (isVisible) {
                    self.showDiv("deadlineTimeContainer");
                } else {
                    self.hideDiv("deadlineTimeContainer");
                }
            },
            hideAllItems: function(itemIds) {
                var self = this;
                itemIds.forEach(function(itemId) {
                    self.hideDiv(itemId);
                });
            },
            validateEditor: function() {
                var valid = true;
                var hourLimit = Def.constants.defaultImportDelayLimit;
                if (this.isPrecededByImportIcon) {
                    var $form = $('form[name="' + this.formName + '"]');
                    var type = $form.find('input[name="deadlineType"]:checked').val();
                    if (type === Def.constants.deadlineTypeDelay) {
                        var timeUnit = $form.find('select[name="timeUnit"]').val();
                        if (timeUnit === Def.constants.deadlineTimeUnitMinute) {
                            valid = false;
                        } else if (timeUnit === Def.constants.deadlineTimeUnitHour) {
                            if ($("#deadlineTimeUnitHour select").val() < hourLimit) {
                                valid = false;
                            }
                        }
                    }
                }
                if (valid) {
                    EditorsHelper.saveCurrentEditorWithUndo();
                } else {
                    var $message = $("#deadline-editor").find(".editor-error-messages");
                    $message.html(t("error.workflow.deadlineIsTooShortForImport", hourLimit));
                    $message.css("display", "block");
                }
            },
            onTimeChanged: function() {
                var $form = $('form[name="' + this.formName + '"]');
                var type = $form.find('input[name="deadlineType"]:checked').val();
                var timeUnit = $form.find('select[name="timeUnit"]').val();
                if (type == Def.constants.deadlineTypeDelay && timeUnit == Def.constants.deadlineTimeUnitDay) {
                    $form.find('input[name="useTime"]').prop("checked", true);
                }
            },
            hideDiv: function(id) {
                $('form[name="' + this.formName + '"] #' + id).css("display", "none");
            },
            showDiv: function(id) {
                $('form[name="' + this.formName + '"] #' + id).css("display", "block");
            },
            dateAsUTC: function(date) {
                if (date) {
                    return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
                } else {
                    return null;
                }
            },
            checkPresentNodeOfType: function(types) {
                return EditorsHelper.getNodesByTypes(types).length > 0;
            },
            checkPrecededByImportIcon: function(node) {
                return EditorsHelper.getNodesByIncomingConnections(node).some(function(n) {
                    return Def.NODE_TYPE_IMPORT == n.getType();
                });
            }
        });
        controller.addAction({
            change: "deadline-editor-update"
        }, function() {
            nodeEditor.updateVisibility();
        });
        controller.addAction({
            change: "deadline-editor-time-change"
        }, function() {
            nodeEditor.onTimeChanged();
        });
        controller.addAction({
            click: "deadline-editor-save"
        }, function() {
            nodeEditor.validateEditor();
        });
    });
    this.addDomInitializer("archive-editor-initializer", function() {
        var nodeEditor = EditorsHelper.registerEditor("archive", {
            formName: "archiveForm",
            safeToSave: true,
            getTitle: function() {
                return t("workflow.mailing.archive");
            },
            createNewArchive: function() {
                EditorsHelper.processForward(Def.constants.forwardArchiveCreate, "#settings_general_campaign", submitWorkflowForm);
            },
            fillEditor: function(node) {
                var $form = $('form[name="' + this.formName + '"]');
                var data = node.getData();
                $form.submit(false);
                $form.get(0).reset();
                EditorsHelper.fillFormFromObject(this.formName, data, "");
            },
            saveEditor: function() {
                return EditorsHelper.formToObject(this.formName);
            }
        });
        controller.addAction({
            click: "archive-editor-new"
        }, function() {
            nodeEditor.createNewArchive();
        });
    });
    this.addDomInitializer("recipient-editor-initializer", function() {
        var isAltgExtended = Def.constants.isAltgExtended;
        var nodeEditor = EditorsHelper.registerEditor("recipient", {
            formName: "recipientForm",
            targetSelector: "#recipientTargetSelect",
            altgSelector: "#recipientAltgSelect",
            safeToSave: true,
            getTargetFieldSelect: function() {
                return new Select($(this.targetSelector).select2({
                    formatSelection: function(target) {
                        if ($(target.element).data("editable")) {
                            return '<a href="#" class="btn-link-light" ' + 'data-action="recipient-editor-target-edit" data-target-id="' + target.id + '">' + target.text + "</a>";
                        } else {
                            return target.text;
                        }
                    }
                }));
            },
            getAltgFieldSelect: function() {
                return new Select($(this.altgSelector).select2({
                    formatSelection: function(target) {
                        return target.text;
                    }
                }));
            },
            createNewTarget: function() {
                EditorsHelper.processForward(Def.constants.forwardTargetGroupCreate, this.targetSelector, submitWorkflowForm);
            },
            editTarget: function(targetId) {
                $("#forwardTargetItemId").val(targetId);
                EditorsHelper.processForward(Def.constants.forwardTargetGroupEdit, this.targetSelector, submitWorkflowForm);
            },
            getTitle: function() {
                return t("workflow.recipient");
            },
            fillEditor: function(node) {
                var data = node.getData();
                if (!isAltgExtended) {
                    if (Def.constants.accessLimitTargetId > 0) {
                        data.targets = _.union([ Def.constants.accessLimitTargetId ], data.targets);
                        data.targetsOption = "ALL_TARGETS_REQUIRED";
                    }
                }
                var $form = $('form[name="' + this.formName + '"]');
                $form.submit(false);
                $form.get(0).reset();
                EditorsHelper.fillFormFromObject(this.formName, data, "");
                this.getTargetFieldSelect().selectValue(data.targets);
                if (isAltgExtended) {
                    this.getAltgFieldSelect().selectValue(data.altgs);
                }
            },
            saveEditor: function() {
                var data = EditorsHelper.formToObject(this.formName);
                data.targets = this.getTargetFieldSelect().getSelectedValue();
                if (isAltgExtended) {
                    data.altgs = this.getAltgFieldSelect().getSelectedValue();
                }
                return data;
            }
        });
        controller.addAction({
            click: "recipient-editor-create-new-target"
        }, function() {
            nodeEditor.createNewTarget();
        });
        controller.addAction({
            click: "recipient-editor-save"
        }, function() {
            if (isAltgExtended) {
                var form = AGN.Lib.Form.get($("#" + nodeEditor.formName));
                if (form.valid({})) {
                    form.cleanErrors();
                    EditorsHelper.saveCurrentEditorWithUndo();
                } else {
                    form.handleErrors();
                }
            } else {
                EditorsHelper.saveCurrentEditorWithUndo();
            }
        });
        controller.addAction({
            click: "recipient-editor-target-edit"
        }, function() {
            nodeEditor.editTarget(this.el.data("target-id"));
        });
    });
    this.addDomInitializer("export-editor-initializer", function() {
        var exportData = this.config;
        var nodeEditor = EditorsHelper.registerEditor("export", {
            formName: "exportForm",
            safeToSave: true,
            getTitle: function() {
                return t("auto_export");
            },
            createNewAutoExport: function() {
                EditorsHelper.processForward(Def.constants.forwardAutoExportCreate, 'form[name="' + this.formName + '"] select[name=importexportId]', submitWorkflowForm);
            },
            editAutoExport: function() {
                var autoExportSelector = $('form[name="' + this.formName + '"] select[name=importexportId]');
                var autoExportIdVal = autoExportSelector.val();
                $("#forwardTargetItemId").val(autoExportIdVal);
                EditorsHelper.processForward(Def.constants.forwardAutoExportEdit, 'form[name="' + this.formName + '"] select[name=importexportId]', submitWorkflowForm);
            },
            fillEditor: function(node) {
                var $messages = $("#export-editor .editor-error-messages");
                var $form = $('form[name="' + this.formName + '"]');
                var data = node.getData();
                $form.submit(false);
                $form.get(0).reset();
                EditorsHelper.fillFormFromObject(this.formName, data, "");
                this.addLinks();
                if (exportData.isDisabled == "true") {
                    $messages.html(t("error.workflow.autoExportPermission"));
                    $messages.css("display", "block");
                } else {
                    $messages.css("display", "none");
                }
            },
            validateEditor: function() {
                var $messages = $("#export-editor .editor-error-messages");
                var autoExportSelector = $('form[name="' + this.formName + '"] select[name=importexportId]');
                if (autoExportSelector.val() > 0) {
                    $.ajax({
                        type: "POST",
                        url: AGN.url("/workflow/validateDependency.action"),
                        data: {
                            workflowId: Def.workflowId || 0,
                            type: Def.DEPENDENCY_TYPE_AUTO_EXPORT,
                            entityId: autoExportSelector.val()
                        }
                    }).done(function(data) {
                        if (data.valid === true) {
                            EditorsHelper.saveCurrentEditorWithUndo();
                        } else {
                            $messages.html(t("error.workflow.autoExportInUse"));
                            $messages.css("display", "block");
                        }
                    }).fail(function() {
                        $messages.html(t("Error"));
                        $messages.css("display", "block");
                    });
                } else {
                    $messages.html(t("error.workflow.noExport"));
                    $messages.css("display", "block");
                }
            },
            onChange: function() {
                this.addLinks();
            },
            addLinks: function() {
                var formSelector = $('form[name="' + this.formName + '"] select[name=importexportId]');
                var formIdVal = formSelector.val();
                if (formIdVal > 0) {
                    $("#export-editor #editAutoExportLink").css("display", "block");
                    $("#export-editor #createAutoExportLink").css("display", "none");
                } else {
                    $("#export-editor #createAutoExportLink").css("display", "block");
                    $("#export-editor #editAutoExportLink").css("display", "none");
                }
            },
            saveEditor: function() {
                return EditorsHelper.formToObject(this.formName);
            },
            isSetFilledAllowed: function() {
                var $select = $('form[name="' + this.formName + '"] select[name=importexportId]');
                var $option = $select.find(":selected");
                return !($select.val() == 0 || $option.data("is-available") != true);
            }
        });
        controller.addAction({
            change: "export-editor-change"
        }, function() {
            nodeEditor.onChange();
        });
        controller.addAction({
            click: "export-editor-new"
        }, function() {
            nodeEditor.createNewAutoExport();
        });
        controller.addAction({
            click: "export-editor-autoexport"
        }, function() {
            nodeEditor.editAutoExport();
        });
        controller.addAction({
            click: "export-editor-save"
        }, function() {
            nodeEditor.validateEditor();
        });
    });
    this.addDomInitializer("import-editor-initializer", function() {
        var importData = this.config;
        var nodeEditor = EditorsHelper.registerEditor("import", {
            formName: "importForm",
            safeToSave: true,
            getTitle: function() {
                return t("auto_import");
            },
            createNewAutoImport: function() {
                EditorsHelper.processForward(Def.constants.forwardAutoImportCreate, "#importexportId", submitWorkflowForm);
            },
            editAutoImport: function() {
                var autoImportSelector = $('form[name="' + this.formName + '"] select[name=importexportId]');
                var autoImportIdVal = autoImportSelector.val();
                $("#forwardTargetItemId").val(autoImportIdVal);
                EditorsHelper.processForward(Def.constants.forwardAutoImportEdit, 'form[name="' + this.formName + '"] select[name=importexportId]', submitWorkflowForm);
            },
            fillEditor: function(node) {
                var $messages = $("#import-editor .editor-error-messages");
                var $form = $('form[name="' + this.formName + '"]');
                var data = node.getData();
                $form.submit(false);
                $form.get(0).reset();
                EditorsHelper.fillFormFromObject(this.formName, data, "");
                this.addLinks();
                if (importData.isDisabled == "true") {
                    $messages.html(t("error.workflow.autoImportPermission"));
                    $messages.css("display", "block");
                } else {
                    $messages.css("display", "none");
                }
            },
            validateEditor: function() {
                var $messages = $("#import-editor .editor-error-messages");
                var autoImportSelector = $('form[name="' + this.formName + '"] select[name=importexportId]');
                if (autoImportSelector.val() > 0) {
                    $.ajax({
                        type: "POST",
                        url: AGN.url("/workflow/validateDependency.action"),
                        data: {
                            workflowId: Def.workflowId || 0,
                            type: Def.DEPENDENCY_TYPE_AUTO_IMPORT,
                            entityId: autoImportSelector.val()
                        }
                    }).done(function(data) {
                        if (data.valid === true) {
                            EditorsHelper.saveCurrentEditorWithUndo();
                        } else {
                            $messages.html(t("error.workflow.autoImportInUse"));
                            $messages.css("display", "block");
                        }
                    }).fail(function() {
                        $messages.html(t("Error"));
                        $messages.css("display", "block");
                    });
                } else {
                    $messages.html(t("error.workflow.noImport"));
                    $messages.css("display", "block");
                }
            },
            onChange: function() {
                this.addLinks();
            },
            addLinks: function() {
                var formSelector = $('form[name="' + this.formName + '"] select[name=importexportId]');
                var formIdVal = formSelector.val();
                if (formIdVal > 0) {
                    $("#import-editor #editAutoImportLink").css("display", "block");
                    $("#import-editor #createAutoImportLink").css("display", "none");
                } else {
                    $("#import-editor #createAutoImportLink").css("display", "block");
                    $("#import-editor #editAutoImportLink").css("display", "none");
                }
            },
            saveEditor: function() {
                return EditorsHelper.formToObject(this.formName);
            },
            isSetFilledAllowed: function() {
                var $select = $('form[name="' + this.formName + '"] select[name=importexportId]');
                var $option = $select.find(":selected");
                return !($select.val() == 0 || $option.data("is-available") != true);
            }
        });
        controller.addAction({
            change: "import-editor-change"
        }, function() {
            nodeEditor.onChange();
        });
        controller.addAction({
            click: "import-editor-new"
        }, function() {
            nodeEditor.createNewAutoImport();
        });
        controller.addAction({
            click: "import-editor-update"
        }, function() {
            nodeEditor.editAutoImport();
        });
        controller.addAction({
            click: "import-editor-save"
        }, function() {
            nodeEditor.validateEditor();
        });
    });
    this.addDomInitializer("start-editor-initializer", function() {
        var startData = this.config;
        var startMailingSelector = new MailingSelector(startData.form, startData.container, startData.selectedName, startData.noMailingOption);
        var startProfileFieldsTypes = startData.profileFields;
        var isBigData = startData.isBigData;
        var nodeEditor = {
            rulesNumber: 0,
            isStartEditor: false,
            timePattern: /^(\d{2}):(\d{2})$/,
            getTitle: function() {
                return this.isStartEditor ? t("workflow.start.title") : t("workflow.stop.title");
            },
            getStartStopDate: function(data) {
                data = data || EditorsHelper.formToObject("startForm");
                var $form = $('form[name="startForm"]');
                var picker = null;
                if (this.isStartEditor) {
                    switch (data.startType) {
                      case Def.constants.startTypeDate:
                        picker = $form.find("#startDate").pickadate("picker");
                        break;

                      case Def.constants.startTypeEvent:
                        picker = $form.find("#executionDate").pickadate("picker");
                        break;
                    }
                } else if (data.endType == Def.constants.endTypeDate) {
                    picker = $form.find("#startDate").pickadate("picker");
                }
                if (picker) {
                    var select = picker.get("select");
                    if (select) {
                        return select.obj;
                    }
                }
                return null;
            },
            generateReminderComment: function() {
                var name = $('#workflowForm input[name="workflow.shortname"]').val();
                var dateString = DateTimeUtils.getDateStr(this.getStartStopDate(), startData.localeDatePattern);
                return (this.isStartEditor ? t("workflow.start.reminder_text") : t("workflow.stop.reminder_text")).replace(/:campaignName/g, name).replace(/:startDate/g, dateString).replace(/:endDate/g, dateString);
            },
            fillEditor: function(node) {
                var data = node.getData();
                var nodeType = node.getType();
                this.isStartEditor = nodeType == "start";
                const showStartEventOption = this.isStartEditor && (node.data.startType === Def.constants.startTypeEvent || !editor.isAutoOptimizationWorkflow(node));
                this.updateEditorType(this.isStartEditor, showStartEventOption);
                var editorForm = $('form[name="startForm"]');
                editorForm.submit(false);
                editorForm.find(".rule-row").each(function() {
                    $(this).remove();
                });
                editorForm.find("#remindCalendarDateTitle").text(this.isStartEditor ? t("workflow.start.start_date") : t("workflow.stop.end_date"));
                if (data.rules != undefined) {
                    for (var i = 0; i < data.rules.length; i++) {
                        var rule = data.rules[i];
                        this.createRuleRow(i, rule);
                    }
                    this.rulesNumber = data.rules.length;
                }
                editorForm.get(0).reset();
                data.adminTimezone = startData.adminTimezone;
                data.sendReminder = data.scheduleReminder;
                EditorsHelper.fillFormFromObject("startForm", data, "");
                startMailingSelector.setMailingId(data.mailingId);
                startMailingSelector.cleanOptions(1);
                var currentDate = new Date();
                editorForm.find("#startDate").pickadate("picker").set("select", this.dateAsUTC(data.date != undefined ? data.date : currentDate));
                editorForm.find("#executionDate").pickadate("picker").set("select", this.dateAsUTC(data.date != undefined ? data.date : currentDate));
                editorForm.find("#remindDate").pickadate("picker").set("select", this.dateAsUTC(data.remindDate != undefined ? data.remindDate : currentDate));
                if (data.date != undefined) {
                    editorForm.find("#startTime").val(this.formatTime(data.hour, data.minute));
                    editorForm.find("#remindTime").val(this.formatTime(data.remindHour, data.remindMinute));
                } else {
                    this.setCurrentTime();
                }
                this.updateChainFieldsVisibility();
                this.updateVisibility();
                this.updateOperatorsAvailability();
                if (data.startType == Def.constants.startTypeEvent && data.event == Def.constants.startEventReaction && data.reaction == Def.constants.reactionClickedLink && data.mailingId != 0 && data.mailingId != null) {
                    this.onMailingSelectChange(data.mailingId, data.linkId);
                }
                if (!data.comment) {
                    editorForm.find("#reminderComment").val(this.generateReminderComment());
                }
                var userType;
                if (data.recipients != "") {
                    userType = 2;
                } else {
                    userType = 1;
                }
                $('#start-editor input[name="userType"][value=' + userType + "]").prop("checked", true).trigger("change");
                $("#start-editor .editor-error-messages").css("display", "none");
                Form.get(editorForm).cleanErrors();
                if (!this.isStartEditor && editor.isAllLinkedFilledStartsHasDateType(node)) {
                    this.hideDiv("end-date-radio");
                } else {
                    this.showDiv("end-date-radio");
                }
            },
            saveEditor: function() {
                var data = EditorsHelper.formToObject("startForm");
                data.date = this.getStartStopDate(data);
                if (data.date == null) {
                    data.date = new Date();
                    data.date.setHours(0);
                    data.date.setMinutes(0);
                    data.date.setSeconds(0);
                    data.date.setMilliseconds(0);
                }
                var match;
                var startTime = $('form[name="startForm"] #startTime').val();
                if (match = this.timePattern.exec(startTime)) {
                    data.hour = match[1];
                    data.minute = match[2];
                } else {
                    data.hour = 0;
                    data.minute = 0;
                }
                data.scheduleReminder = data.sendReminder;
                var remindTime = $('form[name="startForm"] #remindTime').val();
                if (match = this.timePattern.exec(remindTime)) {
                    data.remindHour = match[1];
                    data.remindMinute = match[2];
                } else {
                    data.remindHour = 0;
                    data.remindMinute = 0;
                }
                if ($('input[name="remindSpecificDate"]:checked').val() == "true") {
                    data.remindDate = $('form[name="startForm"] #remindDate').pickadate("picker").get("select").obj;
                } else {
                    data.remindDate = data.date;
                    data.remindHour = 0;
                    data.remindMinute = 0;
                }
                if (data.rules == undefined) {
                    data.rules = [];
                }
                if (data.linkId == undefined || data.linkId == null) {
                    data.linkId = 0;
                }
                if (data.dateFieldOperator != startData.equelsOperatorCode) {
                    data.dateFieldOperator = startData.equelsOperatorCode;
                }
                if (data.userType == 2) {
                    data.remindAdminId = 0;
                    data.recipients = $.trim(data.recipients).toLowerCase().split(/[,;\s\n\r]+/).filter(function(address) {
                        return !!address;
                    }).join(", ");
                } else {
                    data.recipients = "";
                }
                delete data.userType;
                return data;
            },
            validateEditorInternal: function(showErrors) {
                var self = this;
                var valid = true;
                var messageView = $("#start-editor .editor-error-messages");
                var editorForm = $('form[name="startForm"]');
                var type = this.isStartEditor ? editorForm.find('input[name="startType"]:checked').val() : editorForm.find('input[name="endType"]:checked').val();
                if (this.isStartEditor && type == Def.constants.startTypeEvent) {
                    validateStartEvent();
                    validateStartDate();
                }
                if (this.isStartEditor && type == Def.constants.startTypeDate || !this.isStartEditor && type == Def.constants.endTypeDate) {
                    validateStartDate();
                }
                if (valid && editorForm.find("#sendReminder").is(":checked")) {
                    var userType = editorForm.find('input[name="userType"]:checked').val();
                    if (userType == 2) {
                        validateReminderRecipients();
                    }
                }
                return valid;
                function validateStartEvent() {
                    var event = editorForm.find('select[name="event"]').val();
                    switch (event) {
                      case Def.constants.startEventDate:
                        var executionDate = editorForm.find("#executionDate").pickadate("picker").get("select").obj;
                        if (executionDate) {
                            var startTime = editorForm.find("#startTime").val();
                            if (!self.timePattern.test(startTime)) {
                                valid = false;
                            }
                        } else {
                            valid = false;
                        }
                        var dateFieldValue = editorForm.find("#dateFieldValue");
                        if (!$.trim(dateFieldValue.val())) {
                            valid = false;
                            if (showErrors) {
                                messageView.html(t("error.workflow.startDateOmitted"));
                                messageView.css("display", "block");
                            }
                        }
                        const $dateProfileField = editorForm.find("#dateProfileField");
                        if (!$.trim($dateProfileField.val())) {
                            valid = false;
                            if (showErrors) {
                                Form.get($dateProfileField).showFieldError("dateProfileField", t("fields.required.errors.missing"));
                            }
                        }
                        break;

                      case Def.constants.startEventReaction:
                        var reaction = editorForm.find('select[name="reaction"]').val();
                        switch (reaction) {
                          case Def.constants.reactionClickedLink:
                            const linkId = editorForm.find('select[name="linkId"]').val();
                            if (!linkId || parseInt(linkId, 10) <= 0) {
                                valid = false;
                                if (showErrors) {
                                    messageView.html(t("error.workflow.noLinkSelected"));
                                    messageView.css("display", "block");
                                }
                            }

                          case Def.constants.reactionOpened:
                          case Def.constants.reactionClicked:
                            const mailingId = editorForm.find('select[name="mailingId"]').val();
                            if (parseInt(mailingId, 10) <= 0) {
                                valid = false;
                                if (showErrors) {
                                    messageView.html(t("error.workflow.noMailing"));
                                    messageView.css("display", "block");
                                }
                            }
                            break;

                          case Def.constants.reactionChangeOfProfile:
                            if (typeof isBigData != "undefined" && isBigData == true) {
                                var profileField = editorForm.find('select[name="profileField"]').val();
                                if (!profileField) {
                                    valid = false;
                                }
                            }
                            const $startProfileField = editorForm.find("#startProfileField");
                            if (!$.trim($startProfileField.val())) {
                                valid = false;
                                if (showErrors) {
                                    Form.get($startProfileField).showFieldError("profileField", t("fields.required.errors.missing"));
                                }
                            }
                            break;

                          case Def.constants.reactionWaitingForConfirm:
                          case Def.constants.reactionOptIn:
                          case Def.constants.reactionOptOut:
                            break;

                          default:
                            valid = false;
                            break;
                        }
                        break;
                    }
                }
                function validateStartDate() {
                    var startDate = editorForm.find("#startDate").pickadate("picker").get("select").obj;
                    if (startDate) {
                        var startTime = editorForm.find("#startTime").val();
                        if (!self.timePattern.test(startTime)) {
                            valid = false;
                        }
                    } else {
                        valid = false;
                    }
                }
                function validateReminderRecipients() {
                    var emails = $.trim(editorForm.find('textarea[name="recipients"]').val()).split(/[,;\s\n\r]+/).filter(function(address) {
                        return !!address;
                    });
                    if (!emails.length) {
                        if (showErrors) {
                            valid = false;
                            messageView.html(t("error.workflow.emptyRecipientList"));
                            messageView.css("display", "block");
                        }
                    }
                }
            },
            validateEditor: function() {
                if (this.validateEditorInternal(true)) {
                    EditorsHelper.saveCurrentEditorWithUndo();
                }
            },
            isSetFilledAllowed: function() {
                return this.validateEditorInternal(false);
            },
            setCurrentTime: function() {
                var self = this;
                $.ajax({
                    type: "GET",
                    url: AGN.url("/workflow/getCurrentAdminTime.action"),
                    success: function(data) {
                        $('form[name="startForm"] #startTime').val(self.formatTime(data.hour, data.minute));
                        $('form[name="startForm"] #remindTime').val(self.formatTime(data.remindHour, data.remindMinute));
                    }
                });
            },
            updateEditorType: function(isStartEditor, showStartEventOption) {
                var $type = $("#startStopType");
                $type.empty();
                if (isStartEditor) {
                    $type.append(Template.text("start-types", {
                        showStartEventTab: showStartEventOption
                    }));
                    $("#eventReaction").html(t("workflow.start.reaction_based"));
                    $("#eventDate").html(t("workflow.start.date_based"));
                } else {
                    $type.append(Template.text("stop-types"));
                    if (this.checkPresentNodeOfType([ Def.NODE_TYPE_ACTION_BASED_MAILING, Def.NODE_TYPE_DATE_BASED_MAILING ])) {
                        $("#endTypeActiomaticLabel").html(t("workflow.stop.open_end"));
                    } else {
                        $("#endTypeActiomaticLabel").html(t("workflow.stop.automatic_end"));
                    }
                }
            },
            onRulesChanged: function() {
                var ruleIndex = 0;
                $('form[name="startForm"] #profileFieldAddedRules tr').each(function() {
                    var $this = $(this);
                    var ruleId = $this.attr("id");
                    var oldIndex = ruleId.substring(5);
                    var $rule = $("#" + ruleId);
                    $rule.find(".rule-field").attr("name", function(i, name) {
                        return name ? name.replace(oldIndex, ruleIndex + "") : "";
                    });
                    $rule.find(".delete-rule").attr("data-rule-index", function(i, value) {
                        return value == oldIndex ? ruleIndex : value;
                    });
                    $this.attr("id", "rule_" + ruleIndex);
                    ruleIndex++;
                });
                this.updateChainFieldsVisibility();
            },
            updateChainFieldsVisibility: function() {
                if (this.rulesNumber > 0) {
                    $('form[name="startForm"] [name="rules[0].chainOperator"]').css("visibility", "hidden");
                    $('form[name="startForm"] #newRule_chainOperator').css("visibility", "visible");
                } else {
                    $('form[name="startForm"] #newRule_chainOperator').css("visibility", "hidden");
                }
            },
            updateOperatorsAvailability: function() {
                var profileField = $('form[name="startForm"] select[name="profileField"]').val();
                var fieldType = startProfileFieldsTypes[profileField];
                $('form[name="startForm"] select.primary-operator').each(function() {
                    var $select = $(this);
                    $select.children("option").prop("disabled", function() {
                        var types = $(this).data("types");
                        if (types == "*" || !types) {
                            return false;
                        }
                        return types.split(/[\s,]+/).indexOf(fieldType) == -1;
                    });
                    AGN.Lib.CoreInitializer.run("select", $select);
                    if ($select.val() == null) {
                        EditorsHelper.initSelectWithFirstValue($select);
                    }
                });
            },
            addRule: function() {
                var $form = $('form[name="startForm"]');
                var rule = {
                    chainOperator: $form.find("#newRule_chainOperator").val(),
                    parenthesisOpened: $form.find("#newRule_parenthesisOpened").val(),
                    primaryOperator: $form.find("#newRule_primaryOperator").val(),
                    primaryValue: $form.find("#newRule_primaryValue").val(),
                    parenthesisClosed: $form.find("#newRule_parenthesisClosed").val()
                };
                this.createRuleRow(this.rulesNumber, rule);
                EditorsHelper.fillFormFromObject("startForm", rule, "rules[" + this.rulesNumber + "].");
                this.rulesNumber++;
                if ($("#newRule_primaryOperator").val() == Def.constants.operatorIs) {
                    $("#newRule_primaryValue").parents("td").replaceWith(this.createSimpleNewRuleValueField());
                }
                this.updateChainFieldsVisibility();
                this.updateOperatorsAvailability();
                $form.find("#profileFieldRuleAdd select").each(function() {
                    EditorsHelper.initSelectWithFirstValue($(this));
                });
                $form.find("#profileFieldRuleAdd input").each(function() {
                    $(this).val("");
                });
            },
            removeRuleRow: function(index) {
                $('form[name="startForm"] #rule_' + index).remove();
                this.rulesNumber--;
                this.onRulesChanged();
            },
            createRuleRow: function(ruleIndex, rule) {
                var $rules = $('form[name="startForm"] #profileFieldAddedRules');
                var valueElement = this.createSimpleRuleValueField(ruleIndex);
                var options = Utils.arrayAsOptionsHtml(Def.constants.operators);
                if (this.curProfileField && this.curProfileField.toLowerCase() == Def.GENDER_PROFILE_FIELD) {
                    valueElement = this.createGenderSelect();
                } else if (rule.primaryOperator == Def.constants.operatorIs) {
                    valueElement = this.createIsOperatorSelect();
                }
                $rules.append('<tr class="rule-row" id="rule_' + ruleIndex + '">' + '<td><select name="rules[' + ruleIndex + '].chainOperator" class="rule-field">' + '<option value="' + Def.constants.chainOperatorAnd + '">' + t("workflow.defaults.and") + "</option>" + '<option value="' + Def.constants.chainOperatorOr + '">' + t("workflow.defaults.or") + "</option>" + "</select></td>" + '<td><select name="rules[' + ruleIndex + '].parenthesisOpened" class="parentheses-opened rule-field">' + '<option value="0">&nbsp</option>' + '<option value="1">(</option>' + "</select></td>" + '<td><select name="rules[' + ruleIndex + '].primaryOperator" class="primary-operator rule-field" data-action="start-rule-operator-change">' + options + "</select></td>" + valueElement + '<td><select name="rules[' + ruleIndex + '].parenthesisClosed" class="parenthesis-closed rule-field">' + '<option value="0">&nbsp</option>' + '<option value="1">)</option>' + "</select></td>" + '<td><a class="mailing_delete delete-rule btn btn-regular btn-alert" href="#" data-action="start-editor-rule-remove" data-rule-index="' + ruleIndex + '"><i class="icon icon-minus-circle"></i></a></td>' + "</tr>");
                this.addRuleProperties($("#rule_" + ruleIndex + " .primary-value"), ruleIndex);
                AGN.runAll($rules);
            },
            onStartTypeChanged: function() {
                var value = this.isStartEditor ? $('form[name="startForm"] input[name="startType"]:checked').val() : $('form[name="startForm"] input[name="endType"]:checked').val();
                if (this.isStartEditor && value == Def.constants.startTypeDate || !this.isStartEditor && value == Def.constants.endTypeDate) {
                    this.toggleFormat();
                    this.hideDiv("startEventPanel");
                    this.showDiv("startDatePanel");
                    this.showDiv("startIconTime");
                    this.showDiv("startRemindAdmin");
                } else if (this.isStartEditor && value == Def.constants.startTypeEvent) {
                    this.hideDiv("startDatePanel");
                    this.showDiv("startEventPanel");
                    this.showDiv("startIconTime");
                    this.showDiv("startRemindAdmin");
                    this.onStartEventChanged();
                } else if (this.isStartEditor && value == Def.constants.startTypeOpen || !this.isStartEditor && value == Def.constants.endTypeAutomatic) {
                    this.hideDiv("startDatePanel");
                    this.hideDiv("startEventPanel");
                    this.hideDiv("startIconTime");
                    this.hideDiv("startRemindAdmin");
                }
            },
            onStartEventChanged: function() {
                var event = $("#startEvent").val();
                if (event == Def.constants.startEventReaction) {
                    this.toggleFormat();
                    this.hideDiv("dateStartPanel");
                    this.showDiv("reactionStartPanel");
                    this.onExecutionChanged();
                    this.onProfileFieldChanged();
                } else if (event == Def.constants.startEventDate) {
                    this.toggleFormat();
                    this.hideDiv("reactionStartPanel");
                    this.showDiv("dateStartPanel");
                    this.hideDiv("executionDateLabel");
                    this.showDiv("firstExecutionDateLabel");
                    $("#startIconDateFormat").insertAfter("#startIconDateFieldOperator");
                    this.showDiv("startIconDateFormat");
                }
            },
            toggleFormat: function() {
                var timeInput, typeDateInput, startEventInput, checked, isDateBased;
                return function() {
                    startEventInput = startEventInput || $("select#startEvent");
                    typeDateInput = typeDateInput || $("input#typeEvent");
                    timeInput = timeInput || $("input#startTime");
                    checked = typeDateInput.prop("checked");
                    isDateBased = startEventInput.val() == Def.constants.startEventDate;
                    typeDateInput.prop("checked") && isDateBased ? timeInput.inputmask("h:00") : timeInput.inputmask("h:s");
                };
            }(),
            onRuleModeChanged: function() {
                var value = $('input[name="useRules"]:checked').val();
                if (value == "false") {
                    this.hideDiv("profileFieldRules");
                } else {
                    this.showDiv("profileFieldRules");
                }
            },
            onProfileFieldChanged: function() {
                var profileField = $('form[name="startForm"] select[name="profileField"]').val();
                var fieldType = startProfileFieldsTypes[profileField];
                if (fieldType && fieldType.toLowerCase() == Def.FIELD_TYPE_DATE) {
                    $("#startIconDateFormat").insertAfter("#reactionProfileField");
                    this.showDiv("startIconDateFormat");
                } else {
                    this.hideDiv("startIconDateFormat");
                }
                this.updateOperatorsAvailability();
            },
            getRuleIndex: function($element) {
                return $element.attr("id").substring(5);
            },
            onRuleOperatorChanged: function($element) {
                if (this.curProfileField && this.curProfileField.toLowerCase() == Def.GENDER_PROFILE_FIELD) {
                    return;
                }
                var $parent = $element.closest("tr");
                var index = $parent.attr("id") ? this.getRuleIndex($parent) : null;
                if ($element.val() == Def.constants.operatorIs) {
                    var $select = $(this.createIsOperatorSelect());
                    $parent.find(".primary-value").parents("td").replaceWith($select);
                    AGN.Lib.CoreInitializer.run("select", $select);
                } else if ($parent.find(".primary-value").hasClass("null-select")) {
                    var html;
                    if (index == null) {
                        html = this.createSimpleNewRuleValueField();
                    } else {
                        html = this.createSimpleRuleValueField(index);
                    }
                    $parent.find(".primary-value").parents("td").replaceWith(html);
                }
                if (index == null) {
                    this.addNewRuleProperties($parent.find(".primary-value"));
                } else {
                    this.addRuleProperties($parent.find(".primary-value"), index);
                }
            },
            createGenderSelect: function() {
                var options = Utils.mapAsOptionsHtml(Def.constants.genderOptions);
                return '<td><select class="primary-value form-control">' + options + "</select></td>";
            },
            createIsOperatorSelect: function() {
                return '<td><select class="primary-value null-select form-control">' + '<option value="NULL">NULL</option>' + '<option value="NOT_NULL">NOT NULL</option>' + "</select></td>";
            },
            createSimpleRuleValueField: function(ruleIndex) {
                return '<td><input name="rules[' + ruleIndex + '].primaryValue" type="text" class="primary-value rule-field form-control"/></td>';
            },
            createSimpleNewRuleValueField: function() {
                return '<td><input id="newRule_primaryValue" type="text" class="primary-value form-control"/></td>';
            },
            addRuleProperties: function($element, ruleIndex) {
                $element.filter("select, input").attr("name", "rules[" + ruleIndex + "].primaryValue").addClass("rule-field");
            },
            addNewRuleProperties: function($element) {
                $element.filter("select, input").attr("id", "newRule_primaryValue");
            },
            onExecutionChanged: function() {
                var value = $('input[name="executeOnce"]:checked').val();
                if (value == "false") {
                    this.hideDiv("executionDateLabel");
                    this.showDiv("firstExecutionDateLabel");
                } else {
                    this.hideDiv("firstExecutionDateLabel");
                    this.showDiv("executionDateLabel");
                }
            },
            onReactionChanged: function() {
                var selectedReaction = $('form[name="startForm"] #startReaction').val();
                if (selectedReaction == Def.constants.reactionOpened || selectedReaction == Def.constants.reactionNotOpened || selectedReaction == Def.constants.reactionClicked || selectedReaction == Def.constants.reactionNotClicked || selectedReaction == Def.constants.reactionBought || selectedReaction == Def.constants.reactionNotBought || selectedReaction == Def.constants.reactionClickedLink) {
                    this.hideDiv("reactionStartProfile");
                    this.showDiv("reactionStartMailing");
                } else if (selectedReaction == Def.constants.reactionChangeOfProfile) {
                    this.hideDiv("reactionStartMailing");
                    this.showDiv("reactionStartProfile");
                } else {
                    this.hideDiv("reactionStartMailing");
                    this.hideDiv("reactionStartProfile");
                }
                if (selectedReaction == Def.constants.reactionClickedLink) {
                    this.showDiv("reactionStartMailingLink");
                } else {
                    this.hideDiv("reactionStartMailingLink");
                }
            },
            onReminderChanged: function() {
                if ($('input[name="sendReminder"]:checked').val()) {
                    $('form[name="startForm"]').find("#reminderComment").val(this.generateReminderComment());
                    this.showDiv("reminderDetails");
                } else {
                    this.hideDiv("reminderDetails");
                }
                return false;
            },
            onScheduleReminderDateChanged: function() {
                if ($('form[name="startForm"] input[name="remindSpecificDate"]:checked').val() == "true") {
                    this.showDiv("dateTimePicker");
                } else {
                    this.hideDiv("dateTimePicker");
                }
                return false;
            },
            onMailingSelectChange: function(value, selectedValue) {
                var $linkSelect = $('form[name="startForm"] select[name="linkId"]');
                var mailingId = parseInt(value, 10);
                if (mailingId > 0) {
                    $linkSelect.attr("readonly", "readonly");
                    $.ajax({
                        type: "POST",
                        url: AGN.url("/workflow/getMailingLinks.action"),
                        data: {
                            mailingId: mailingId
                        },
                        success: function(data) {
                            $linkSelect.empty();
                            $linkSelect.append($("<option></option>", {
                                value: "",
                                text: Def.EMPTY_OPTION_PLACEHOLDER
                            }));
                            $.each(data, function(index, itemUrl) {
                                $linkSelect.append($("<option></option>", {
                                    value: itemUrl.id,
                                    text: itemUrl.url
                                }));
                            });
                            $linkSelect.removeAttr("readonly");
                            if (selectedValue != null && selectedValue != undefined) {
                                $linkSelect.val(selectedValue);
                                EditorsHelper.initSelectWithValueOrChooseFirst($linkSelect, selectedValue);
                            } else {
                                EditorsHelper.initSelectWithFirstValue($linkSelect);
                            }
                        }
                    });
                } else {
                    $linkSelect.empty();
                }
            },
            updateVisibility: function() {
                this.onStartTypeChanged();
                this.onStartEventChanged();
                this.onReactionChanged();
                this.onRuleModeChanged();
                this.onExecutionChanged();
                this.onReminderChanged();
                this.onScheduleReminderDateChanged();
            },
            hideDiv: function(id) {
                $('form[name="startForm"] #' + id).css("display", "none");
            },
            showDiv: function(id) {
                $('form[name="startForm"] #' + id).css("display", "");
            },
            dateAsUTC: function(date) {
                if (date) {
                    return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
                } else {
                    return null;
                }
            },
            formatTime: function(hours, minutes) {
                var h = 0;
                var m = 0;
                hours = parseInt(hours, 10);
                if (hours >= 0) {
                    h = hours;
                }
                minutes = parseInt(minutes, 10);
                if (minutes >= 0) {
                    m = minutes;
                }
                return (h < 10 ? "0" + h : h) + ":" + (m < 10 ? "0" + m : m);
            },
            checkPresentNodeOfType: function(types) {
                return EditorsHelper.getNodesByTypes(types).length > 0;
            }
        };
        EditorsHelper.registerEditor("start", nodeEditor);
        EditorsHelper.registerEditor("stop", nodeEditor);
        controller.addAction({
            change: "start-editor-execution-changed"
        }, function() {
            nodeEditor.onExecutionChanged();
        });
        controller.addAction({
            change: "start-editor-event-changed"
        }, function() {
            nodeEditor.onStartEventChanged();
        });
        controller.addAction({
            change: "start-editor-type-changed"
        }, function() {
            nodeEditor.onStartTypeChanged();
        });
        controller.addAction({
            change: "start-editor-rule-changed"
        }, function() {
            nodeEditor.onRuleModeChanged();
        });
        controller.addAction({
            change: "start-editor-reaction-changed"
        }, function() {
            nodeEditor.onReactionChanged();
        });
        controller.addAction({
            change: "start-editor-profile-field-changed"
        }, function() {
            nodeEditor.onProfileFieldChanged();
        });
        controller.addAction({
            click: "start-editor-add-rule"
        }, function() {
            nodeEditor.addRule();
        });
        controller.addAction({
            click: "start-editor-reminder-changed"
        }, function() {
            nodeEditor.onReminderChanged();
        });
        controller.addAction({
            click: "start-editor-schedule-reminder-date-changed"
        }, function() {
            nodeEditor.onScheduleReminderDateChanged();
        });
        controller.addAction({
            click: "start-editor-validate"
        }, function() {
            nodeEditor.validateEditor();
        });
        controller.addAction({
            click: "start-editor-mailing-sort-date"
        }, function() {
            startMailingSelector.onMailingSortClick("date");
        });
        controller.addAction({
            change: "start-editor-mailing-select"
        }, function() {
            nodeEditor.onMailingSelectChange(this.el.val());
        });
        controller.addAction({
            click: "start-editor-mailing-sort-shortname"
        }, function() {
            startMailingSelector.onMailingSortClick("shortname");
        });
    });
    this.addDomInitializer("decision-editor-initializer", function() {
        var decisionData = this.config;
        var decisionProfileFieldsTypes = decisionData.profileFields;
        var decisionMailingSelector = new MailingSelector(decisionData.form, decisionData.container, decisionData.selectName, decisionData.noMailingOption);
        var profileFieldMailingId;
        var nodeEditor = EditorsHelper.registerEditor("decision", {
            rulesNumber: 0,
            rulePrefix: "decision_",
            prevProfileField: "",
            curProfileField: "",
            getTitle: function() {
                return t("workflow.decision");
            },
            fillEditor: function(node) {
                var $form = $('form[name="decisionForm"]');
                profileFieldMailingId = 0;
                var data = node.getData();
                $form.submit(false);
                $form.find(".rule-row").each(function() {
                    $(this).remove();
                });
                this.curProfileField = data.profileField;
                this.possibleToUseAutoOptimization = editor.isAutoOptimizationDecisionAllowed(node);
                if (data.rules != undefined) {
                    for (var i = 0; i < data.rules.length; i++) {
                        var rule = data.rules[i];
                        this.createRuleRow(i, rule);
                    }
                    this.rulesNumber = data.rules.length;
                }
                $form.get(0).reset();
                if (data.profileField) {
                    data.profileField = data.profileField.toLowerCase();
                }
                EditorsHelper.fillFormFromObject("decisionForm", data, "");
                decisionMailingSelector.setMailingId(data.mailingId);
                decisionMailingSelector.cleanOptions(1);
                if (data.decisionDate == undefined) {
                    data.decisionDate = new Date();
                }
                var decisionDatePicker = $form.find("#decisionDate");
                var decisionTimePicker = $form.find("#decisionTime");
                if (this.checkPresentNodeOfType([ Def.NODE_TYPE_ACTION_BASED_MAILING, Def.NODE_TYPE_DATE_BASED_MAILING ])) {
                    decisionDatePicker.parent().parent().parent().parent().hide();
                    decisionTimePicker.parent().parent().parent().parent().hide();
                } else {
                    decisionDatePicker.parent().parent().parent().parent().show();
                    decisionTimePicker.parent().parent().parent().parent().show();
                    decisionDatePicker.pickadate("picker").set("select", this.dateAsUTC(data.decisionDate));
                    decisionTimePicker.val(("0" + data.decisionDate.getHours()).slice(-2) + ":" + ("0" + data.decisionDate.getMinutes()).slice(-2));
                }
                this.updateChainFieldsVisibility();
                this.updateVisibility();
                this.updateDateFormatVisibility();
                this.updateOperatorsAvailability();
                if (data.decisionType == Def.constants.decisionTypeDecision && data.decisionCriteria == Def.constants.decisionReaction && data.reaction == Def.constants.reactionClickedLink && (data.mailingId != 0 && data.mailingId != null)) {
                    this.onMailingSelectChange(data.mailingId, data.linkId);
                } else {
                    EditorsHelper.resetSelect($form.find('select[name="linkId"]'));
                }
                $("#decision-editor .editor-error-messages").css("display", "none");
                Form.get($form).cleanErrors();
            },
            saveEditor: function() {
                var data = EditorsHelper.formToObject("decisionForm");
                if (data.decisionCriteria == Def.constants.decisionProfileField && profileFieldMailingId != 0) {
                    data.mailingId = profileFieldMailingId;
                }
                profileFieldMailingId = 0;
                if (data.rules == undefined) {
                    data.rules = [];
                }
                if (!data.threshold) {
                    data.threshold = "";
                }
                if (this.checkPresentNodeOfType([ Def.NODE_TYPE_ACTION_BASED_MAILING, Def.NODE_TYPE_DATE_BASED_MAILING ])) {
                    data.decisionDate = null;
                } else {
                    var $form = $('form[name="decisionForm"]');
                    data.decisionDate = $form.find("#decisionDate").pickadate("picker").get("select").obj;
                    var time = $form.find("#decisionTime").val();
                    data.decisionDate.setHours(time.substring(0, 2));
                    data.decisionDate.setMinutes(time.substring(3, 5));
                }
                return data;
            },
            validateEditor: function() {
                var $form = $('form[name="decisionForm"]');
                var $messages = $("#decision-editor .editor-error-messages");
                var decisionType = $form.find('input[name="decisionType"]:checked').val();
                var decisionCriteria = $("#decisionCriteria").val();
                var mailingId = $form.find('select[name="mailingId"]').val();
                var linkId = $form.find('select[name="linkId"]').val();
                var reaction = $form.find('select[name="reaction"]').val();
                var threshold = $form.find('input[name="threshold"]').val();
                if (decisionType == Def.constants.decisionTypeDecision && decisionCriteria == Def.constants.decisionReaction && mailingId == 0) {
                    $messages.html(t("error.workflow.noMailing"));
                    $messages.css("display", "block");
                } else if (decisionType == Def.constants.decisionTypeDecision && decisionCriteria == Def.constants.decisionReaction && reaction == Def.constants.reactionClickedLink && (linkId == 0 || linkId == null)) {
                    $messages.html(t("error.workflow.noLinkSelected"));
                    $messages.css("display", "block");
                } else if (decisionType == Def.constants.decisionTypeDecision && decisionCriteria == Def.constants.decisionProfileField) {
                    if (decisionData.isMailtrackingActive == "true") {
                        const $decisionProfileField = $form.find("#decisionProfileField");
                        if (!$.trim($decisionProfileField.val())) {
                            Form.get($form).showFieldError("profileField", t("fields.required.errors.missing"));
                        } else {
                            EditorsHelper.saveCurrentEditorWithUndo();
                        }
                    }
                } else if (decisionType == Def.constants.decisionTypeAutoOptimization) {
                    if (threshold) {
                        var thresholdIntValue = parseInt(threshold, 10);
                        if (thresholdIntValue && thresholdIntValue > 0) {
                            EditorsHelper.saveCurrentEditorWithUndo();
                        } else {
                            $messages.html(t("error.workflow.noValidThreshold"));
                            $messages.css("display", "block");
                        }
                    } else {
                        EditorsHelper.saveCurrentEditorWithUndo();
                    }
                } else {
                    EditorsHelper.saveCurrentEditorWithUndo();
                }
            },
            onTypeChanged: function() {
                var value = $('form[name="decisionForm"] input[name="decisionType"]:checked').val();
                if (!this.possibleToUseAutoOptimization && value === Def.constants.decisionTypeAutoOptimization) {
                    const $messages = $("#decision-editor .editor-error-messages");
                    $messages.html(t("error.workflow.autoOptimizationDecisionForbidden"));
                    $messages.css("display", "block");
                    $('form[name="decisionForm"] input[name="decisionType"]').filter(':radio[value="' + Def.constants.decisionTypeDecision + '"]').prop("checked", true);
                    return;
                }
                if (value == Def.constants.decisionTypeDecision) {
                    this.hideDecisionFormDiv("autoOptimizationPanel");
                    this.showDecisionFormDiv("decisionPanel");
                } else if (value == Def.constants.decisionTypeAutoOptimization) {
                    this.hideDecisionFormDiv("decisionPanel");
                    this.showDecisionFormDiv("autoOptimizationPanel");
                }
                this.updateVisibilityOfRuleMailingReceived();
            },
            onDecisionReactionChanged: function() {
                var value = $('form[name="decisionForm"] select[name="reaction"]').val();
                if (value == Def.constants.reactionClickedLink) {
                    this.showDecisionFormDiv("reactionLinkPanel");
                    var mailingId = $('form[name="decisionForm"] select[name="mailingId"]').val();
                    this.onMailingSelectChange(mailingId, 0);
                } else {
                    this.hideDecisionFormDiv("reactionLinkPanel");
                }
            },
            onCriteriaChanged: function() {
                var value = $('form[name="decisionForm"] select[name="decisionCriteria"]').val();
                if (value == Def.constants.decisionReaction) {
                    this.hideDecisionFormDiv("decisionProfileFieldPanel");
                    this.showDecisionFormDiv("decisionReactionPanel");
                } else if (value == Def.constants.decisionProfileField) {
                    this.hideDecisionFormDiv("decisionReactionPanel");
                    this.showDecisionFormDiv("decisionProfileFieldPanel");
                }
                this.updateVisibilityOfRuleMailingReceived();
            },
            onMailingSelectChange: function(value, selectedValue) {
                var $linkSelect = $('form[name="decisionForm"] select[name="linkId"]');
                var mailingId = parseInt(value, 10);
                if (mailingId > 0) {
                    $linkSelect.attr("readonly", "readonly");
                    $.ajax({
                        type: "POST",
                        url: AGN.url("/workflow/getMailingLinks.action"),
                        data: {
                            mailingId: mailingId
                        },
                        success: function(data) {
                            $linkSelect.empty();
                            $linkSelect.append($("<option></option>", {
                                value: "",
                                text: Def.EMPTY_OPTION_PLACEHOLDER
                            }));
                            $.each(data, function(index, itemUrl) {
                                $linkSelect.append($("<option></option>", {
                                    value: itemUrl.id,
                                    text: itemUrl.url
                                }));
                            });
                            $linkSelect.removeAttr("readonly");
                            if (selectedValue != null && selectedValue != undefined) {
                                $linkSelect.val(selectedValue);
                                EditorsHelper.initSelectWithValueOrChooseFirst($linkSelect, selectedValue);
                            } else {
                                EditorsHelper.initSelectWithFirstValue($linkSelect);
                            }
                        }
                    });
                } else {
                    $linkSelect.empty();
                }
            },
            onRuleOperatorChanged: function($element) {
                if (this.curProfileField && this.curProfileField.toLowerCase() == Def.GENDER_PROFILE_FIELD) {
                    return;
                }
                var $parent = $element.closest("tr");
                var index = $parent.attr("id") ? this.getRuleIndex($parent) : null;
                if ($element.val() == Def.constants.operatorIs) {
                    var $select = $(this.createIsOperatorSelect());
                    $parent.find(".primary-value").parents("td").replaceWith($select);
                    AGN.Lib.CoreInitializer.run("select", $select);
                } else if ($parent.find(".primary-value").hasClass("null-select")) {
                    var html;
                    if (index == null) {
                        html = this.createSimpleNewRuleValueField();
                    } else {
                        html = this.createSimpleRuleValueField(index);
                    }
                    $parent.find(".primary-value").parents("td").replaceWith(html);
                }
                if (index == null) {
                    this.addNewRuleProperties($parent.find(".primary-value"));
                } else {
                    this.addRuleProperties($parent.find(".primary-value"), index);
                }
            },
            getRuleIndex: function($element) {
                return $element.attr("id").substring(14);
            },
            onProfileFieldChanged: function() {
                var $form = $('form[name="decisionForm"]');
                var profileField = $form.find('select[name="profileField"]').val();
                this.curProfileField = profileField;
                var self = this;
                if (profileField && profileField.toLowerCase() == Def.GENDER_PROFILE_FIELD) {
                    $("#decisionProfileFieldRules .primary-value").each(function() {
                        $(this).parents("td").remove();
                    });
                    $form.find(".rule-row").each(function() {
                        var index = self.getRuleIndex($(this));
                        $(this).find(".decision-rule-operator").parents("td").after(self.createGenderSelect());
                        self.addRuleProperties($(this).find(".primary-value"), index);
                    });
                    $("#decision_newRule_primaryOperator").parents("td").after(this.createGenderSelect());
                    this.addNewRuleProperties($("#decisionProfileFieldRuleAdd .primary-value"));
                } else if (this.prevProfileField && this.prevProfileField.toLowerCase() == Def.GENDER_PROFILE_FIELD) {
                    $("#decisionProfileFieldRules .primary-value").each(function() {
                        $(this).parents("td").remove();
                    });
                    $form.find(".rule-row").each(function() {
                        var index = self.getRuleIndex($(this));
                        if ($(this).find(".decision-rule-operator").val() == Def.constants.operatorIs) {
                            $(this).find(".primary-value").parents("td").remove();
                            $(this).find("select").parents("td").after(self.createIsOperatorSelect());
                            self.addRuleProperties($(this).find(".primary-value"), index);
                        } else {
                            $(this).find(".decision-rule-operator").parents("td").after(self.createSimpleRuleValueField(index));
                        }
                    });
                    if ($("#decision_newRule_primaryOperator").val() == Def.constants.operatorIs) {
                        $("#decisionProfileFieldRuleAdd").find("select").parents("td").after(this.createIsOperatorSelect());
                        this.addNewRuleProperties($("#decisionProfileFieldRuleAdd .primaryValue"));
                    } else {
                        $("#decision_newRule_primaryOperator").parents("td").after(this.createSimpleNewRuleValueField());
                    }
                }
                this.updateDateFormatVisibility();
                this.updateOperatorsAvailability();
                this.prevProfileField = profileField;
            },
            updateDateFormatVisibility: function() {
                var profileField = $('form[name="decisionForm"] select[name="profileField"]').val();
                var fieldType = decisionProfileFieldsTypes[profileField];
                if (fieldType && fieldType.toLowerCase() == Def.FIELD_TYPE_DATE) {
                    this.showDecisionFormDiv("decisionDateFormat");
                } else {
                    this.hideDecisionFormDiv("decisionDateFormat");
                }
            },
            updateOperatorsAvailability: function() {
                var $form = $('form[name="decisionForm"]');
                var profileField = $form.find('select[name="profileField"]').val();
                var fieldType = decisionProfileFieldsTypes[profileField];
                $form.find("select.decision-rule-operator").each(function() {
                    var $select = $(this);
                    $select.children("option").prop("disabled", function() {
                        var types = $(this).data("types");
                        if (profileField && profileField.toLowerCase() == Def.GENDER_PROFILE_FIELD) {
                            return this.text != "=" && this.text != "!=";
                        }
                        if (types == "*" || !types) {
                            return false;
                        }
                        return types.split(/[\s,]+/).indexOf(fieldType) == -1;
                    });
                    AGN.Lib.CoreInitializer.run("select", $select);
                    if ($select.val() == null) {
                        EditorsHelper.initSelectWithFirstValue($select);
                    }
                });
            },
            onRulesChanged: function() {
                var ruleIndex = 0;
                var self = this;
                $('form[name="decisionForm"] #decisionProfileFieldAddedRules .rule-row').each(function() {
                    var $this = $(this);
                    var ruleId = $this.attr("id");
                    var oldIndex = self.getRuleIndex($this);
                    var $rule = $("#" + ruleId);
                    $rule.find(".rule-field").attr("name", function(i, name) {
                        return name ? name.replace(oldIndex, ruleIndex + "") : "";
                    });
                    $rule.find(".delete-rule").attr("data-rule-index", function(i, value) {
                        return value == oldIndex ? ruleIndex : value;
                    });
                    $this.attr("id", "decision_rule_" + ruleIndex);
                    ruleIndex++;
                });
                this.updateChainFieldsVisibility();
            },
            updateChainFieldsVisibility: function() {
                var $form = $('form[name="decisionForm"]');
                if (this.rulesNumber > 0) {
                    $form.find('[name="rules[0].chainOperator"]').css("visibility", "hidden");
                    $form.find("#decision_newRule_chainOperator").css("visibility", "visible");
                } else {
                    $form.find("#decision_newRule_chainOperator").css("visibility", "hidden");
                }
            },
            addRule: function() {
                var $form = $('form[name="decisionForm"]');
                var rule = {
                    chainOperator: $form.find("#decision_newRule_chainOperator").val(),
                    parenthesisOpened: $form.find("#decision_newRule_parenthesisOpened").val(),
                    primaryOperator: $form.find("#decision_newRule_primaryOperator").val(),
                    primaryValue: $form.find("#decision_newRule_primaryValue").val(),
                    parenthesisClosed: $form.find("#decision_newRule_parenthesisClosed").val()
                };
                this.createRuleRow(this.rulesNumber, rule);
                EditorsHelper.fillFormFromObject("decisionForm", rule, "rules[" + this.rulesNumber + "].");
                this.rulesNumber++;
                if ($("#decision_newRule_primaryOperator").val() == Def.constants.operatorIs) {
                    $("#decision_newRule_primaryValue").parents("td").replaceWith(this.createSimpleNewRuleValueField());
                }
                this.updateChainFieldsVisibility();
                this.updateOperatorsAvailability();
                $form.find("#decisionProfileFieldRuleAdd select").each(function() {
                    EditorsHelper.initSelectWithFirstValue($(this));
                });
                $form.find("#decisionProfileFieldRuleAdd input").each(function() {
                    $(this).val("");
                });
            },
            removeRuleRow: function(index) {
                $('form[name="decisionForm"] #decision_rule_' + index).remove();
                this.rulesNumber--;
                this.onRulesChanged();
            },
            createRuleRow: function(ruleIndex, rule) {
                var $form = $('form[name="decisionForm"]');
                var valueElement = this.createSimpleRuleValueField(ruleIndex);
                var options = Utils.arrayAsOptionsHtml(Def.constants.operators);
                if (this.curProfileField && this.curProfileField.toLowerCase() == Def.GENDER_PROFILE_FIELD) {
                    valueElement = this.createGenderSelect();
                } else if (rule.primaryOperator == Def.constants.operatorIs) {
                    valueElement = this.createIsOperatorSelect();
                }
                $form.find("#decisionProfileFieldAddedRules").append('<tr class="rule-row" id="decision_rule_' + ruleIndex + '">' + '<td><select name="rules[' + ruleIndex + '].chainOperator" class="rule-field">' + '<option value="' + Def.constants.chainOperatorAnd + '">' + t("workflow.defaults.and") + "</option>" + '<option value="' + Def.constants.chainOperatorOr + '">' + t("workflow.defaults.or") + "</option>" + "</select></td>" + '<td><select name="rules[' + ruleIndex + '].parenthesisOpened" class="parentheses-opened rule-field">' + '<option value="0">&nbsp</option>' + '<option value="1">(</option>' + "</select></td>" + '<td><select name="rules[' + ruleIndex + '].primaryOperator" class="decision-rule-operator rule-field" data-action="decision-rule-operator-change">' + options + "</select></td>" + valueElement + '<td><select name="rules[' + ruleIndex + '].parenthesisClosed" class="parenthesis-closed rule-field">' + '<option value="0">&nbsp</option>' + '<option value="1">)</option>' + "</select></td>" + '<td><a class="mailing_delete delete-rule btn btn-regular btn-alert" href="#" data-action="decision-editor-rule-remove" data-rule-index="' + ruleIndex + '"><i class="icon icon-minus-circle"></i></a></td>' + "</tr>");
                this.addRuleProperties($("#decision_rule_" + ruleIndex + " .primary-value"), ruleIndex);
                AGN.runAll($form.find("#decisionProfileFieldAddedRules"));
            },
            createGenderSelect: function() {
                var options = Utils.mapAsOptionsHtml(Def.constants.genderOptions);
                return '<td><select class="primary-value form-control">' + options + "</select></td>";
            },
            createIsOperatorSelect: function() {
                return '<td><select class="primary-value null-select form-control">' + '<option value="NULL">NULL</option>' + '<option value="NOT_NULL">NOT NULL</option>' + "</select></td>";
            },
            createSimpleRuleValueField: function(ruleIndex) {
                return '<td><input name="rules[' + ruleIndex + '].primaryValue" type="text" class="primary-value rule-field form-control"/></td>';
            },
            createSimpleNewRuleValueField: function() {
                return '<td><input id="decision_newRule_primaryValue" type="text" class="primary-value form-control"/></td>';
            },
            addRuleProperties: function($element, ruleIndex) {
                $element.filter("select, input").attr("name", "rules[" + ruleIndex + "].primaryValue").addClass("rule-field");
            },
            addNewRuleProperties: function($element) {
                $element.filter("select, input").attr("id", "decision_newRule_primaryValue");
            },
            updateVisibility: function() {
                this.onTypeChanged();
                this.onDecisionReactionChanged();
                this.onCriteriaChanged();
            },
            hideDecisionFormDiv: function(id) {
                $('form[name="decisionForm"] #' + id).css("display", "none");
            },
            showDecisionFormDiv: function(id) {
                $('form[name="decisionForm"] #' + id).css("display", "block");
            },
            updateVisibilityOfRuleMailingReceived: function() {
                var decisionType = $('form[name="decisionForm"] input[name="decisionType"]:checked').val();
                if (decisionType == Def.constants.decisionTypeAutoOptimization) {
                    this.hideDecisionFormDiv("ruleMailingReceivedWrapper");
                } else if (decisionType == Def.constants.decisionTypeDecision) {
                    var decisionCriteria = $('form[name="decisionForm"] select[name="decisionCriteria"]').val();
                    if (decisionCriteria == Def.constants.decisionReaction) {
                        this.hideDecisionFormDiv("ruleMailingReceivedWrapper");
                    } else if (decisionCriteria == Def.constants.decisionProfileField) {
                        this.hideDecisionFormDiv("ruleMailingReceivedWrapper");
                        var localShowDecisionFormDiv = this.showDecisionFormDiv;
                        EditorsHelper.forEachPreviousNode(function(node) {
                            if (Def.NODE_TYPES_MAILING.includes(node.getType())) {
                                var data = node.getData();
                                profileFieldMailingId = data.mailingId;
                                localShowDecisionFormDiv("ruleMailingReceivedWrapper");
                                return false;
                            }
                        });
                    }
                }
            },
            dateAsUTC: function(date) {
                if (date) {
                    return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
                } else {
                    return null;
                }
            },
            checkPresentNodeOfType: function(types) {
                return EditorsHelper.getNodesByTypes(types).length > 0;
            }
        });
        controller.addAction({
            click: "decision-editor-mailing-sort-shortname"
        }, function() {
            decisionMailingSelector.onMailingSortClick("shortname");
        });
        controller.addAction({
            click: "decision-editor-mailing-sort-date"
        }, function() {
            decisionMailingSelector.onMailingSortClick("date");
        });
        controller.addAction({
            change: "decision-editor-mailing-select"
        }, function() {
            nodeEditor.onMailingSelectChange(this.el.val());
        });
        controller.addAction({
            change: "decision-rule-operator-change"
        }, function() {
            nodeEditor.onRuleOperatorChanged(this.el);
        });
        controller.addAction({
            click: "decision-editor-rule-remove"
        }, function() {
            nodeEditor.removeRuleRow(this.el.data("rule-index"));
        });
        controller.addAction({
            click: "decision-editor-rule-add"
        }, function() {
            nodeEditor.addRule();
        });
        controller.addAction({
            change: "decision-editor-type-change"
        }, function() {
            nodeEditor.onTypeChanged();
        });
        controller.addAction({
            change: "decision-editor-criteria-change"
        }, function() {
            nodeEditor.onCriteriaChanged();
        });
        controller.addAction({
            change: "decision-editor-reaction-change"
        }, function() {
            nodeEditor.onDecisionReactionChanged();
        });
        controller.addAction({
            click: "decision-editor-save"
        }, function() {
            nodeEditor.validateEditor();
        });
        controller.addAction({
            change: "decision-editor-profile-field-change"
        }, function() {
            nodeEditor.onProfileFieldChanged();
        });
    });
    this.addDomInitializer("mailing-editor-initializer", function() {
        var mailingData = this.config;
        var mailingEditorBase = new MailingEditorHelper(mailingData, submitWorkflowForm);
        var nodeEditor = EditorsHelper.registerEditor("mailing", {
            formName: "mailingForm",
            safeToSave: true,
            getTitle: function() {
                return t("workflow.defaults.mailing");
            },
            fillEditor: function(node) {
                var $form = $('form[name="' + this.formName + '"]');
                var data = node.getData();
                $form.submit(false);
                $form.get(0).reset();
                EditorsHelper.fillFormFromObject(this.formName, data, "");
                mailingEditorBase.fillEditorBase(node);
                $("#mailing-editor .editor-error-messages").css("display", "none");
            },
            createNewMailing: function() {
                mailingEditorBase.createNewMailing(Def.constants.forwardMailingCreate);
            },
            editMailing: function() {
                mailingEditorBase.editMailing(Def.constants.forwardMailingEdit);
            },
            copyMailing: function() {
                mailingEditorBase.copyMailing(Def.constants.forwardMailingCopy);
            },
            saveEditor: function() {
                mailingEditorBase.setNodeFields();
                mailingEditorBase.disableInputs();
                return EditorsHelper.formToObject(this.formName);
            },
            saveWithCheckStatus: function() {
                var isNotSent = mailingEditorBase.showSecurityQuestion();
                if (isNotSent) {
                    EditorsHelper.saveCurrentEditorWithUndo(false, mailingEditorBase);
                }
            }
        });
        controller.addAction({
            click: "mailing-editor-save"
        }, function() {
            mailingEditorBase.validateEditor(nodeEditor.saveWithCheckStatus);
        });
        controller.addAction({
            click: "mailing-editor-base-close"
        }, function() {
            mailingEditorBase.closeOneMailinglistWarningDialog();
        });
        controller.addAction({
            click: "mailing-editor-base-accept"
        }, function() {
            mailingEditorBase.acceptOneMailinglistPerCampaign();
        });
        controller.addAction({
            click: "mailing-editor-base-sort-shortname"
        }, function() {
            mailingEditorBase.onMailingSortClick("shortname", "shortname");
        });
        controller.addAction({
            click: "mailing-editor-base-sort-data"
        }, function() {
            var config = Utils.getConfigData(this.el);
            mailingEditorBase.onMailingSortClick("shortname", config.sortByDate);
        });
        controller.addAction({
            change: "mailing-editor-base-status-change"
        }, function() {
            mailingEditorBase.onMailingsStatusChange(this.el.val());
        });
        controller.addAction({
            change: "mailing-editor-base-select-change"
        }, function() {
            mailingEditorBase.onMailingSelectChange(this.el.val());
        });
        controller.addAction({
            click: "mailing-editor-base-secure-cancel"
        }, function() {
            mailingEditorBase.cancelSecurityDialog();
        });
        controller.addAction({
            click: "mailing-editor-base-toggle-settings"
        }, function() {
            var config = Utils.getConfigData(this.el);
            mailingEditorBase.toggleSendSettings(config.editorId);
        });
    });
    this.addDomInitializer("followup-mailing-editor-initializer", function() {
        var baseMailingData = this.config.baseMailingData;
        var followupMailingData = this.config.followupMailingData;
        baseMailingData.$dropdown = $("#followup-m-editor");
        var baseMailingEditorBase = new MailingEditorHelper(baseMailingData, submitWorkflowForm);
        var followupMailingEditorBase = new MailingEditorHelper(followupMailingData, submitWorkflowForm);
        baseMailingEditorBase.selectedFollowUpMailingId = 0;
        baseMailingEditorBase.findPreviousMailingIds = function() {
            var previousMailingIds = [];
            EditorsHelper.forEachPreviousNode(function(node) {
                var type = node.getType();
                if (Def.NODE_TYPES_MAILING.includes(type) && Def.NODE_TYPE_FOLLOWUP_MAILING != type) {
                    previousMailingIds.push(node.getId());
                }
            });
            return previousMailingIds;
        };
        baseMailingEditorBase.getMailingsByWorkStatus = function(status, sort, order, selectedMailValue) {
            var mailingEditorBase = this;
            var $mailingsList = $(this.formNameJId + " " + this.selectNameJId);
            var previousMailingIds = _.uniq(this.findPreviousMailingIds()).toString();
            $mailingsList.attr("readonly", "readonly");
            $.ajax({
                type: "POST",
                url: AGN.url("/workflow/getMailingsByWorkStatus.action"),
                data: {
                    mailingTypes: this.mailingTypesForLoading.join(","),
                    status: status,
                    sort: sort,
                    order: order,
                    mailingId: this.selectedFollowUpMailingId,
                    parentMailingId: $(this.formNameJId + " " + this.selectNameJId).val(),
                    mailingStatus: "W",
                    takeMailsForPeriod: true,
                    mailingsInCampaign: previousMailingIds
                },
                success: function(data) {
                    $mailingsList.html("");
                    $mailingsList.append('<option value="0">' + t("workflow.defaults.no_mailing") + "</option>");
                    for (var i = 0; i < data.length; i++) {
                        var obj = data[i];
                        var mailingFontColor = "";
                        var selected = "";
                        if (obj.WORK_STATUS == "mailing.status.sent" || obj.WORK_STATUS == "mailing.status.norecipients") {
                            mailingFontColor = "style='color: #808080;'";
                        }
                        if (selectedMailValue == obj.MAILING_ID) {
                            selected = "selected";
                        }
                        $mailingsList.append("<option " + mailingFontColor + " value='" + obj.MAILING_ID + "' status='" + obj.WORK_STATUS + "' senddate='" + obj.SENDDATE + "' " + selected + ">" + obj.SHORTNAME + "</option>");
                    }
                    $mailingsList.removeAttr("readonly");
                    mailingEditorBase.mailingsStatus = status;
                    mailingEditorBase.mailingsSort = sort;
                    mailingEditorBase.mailingsOrder = order;
                    $mailingsList.val(mailingEditorBase.mailingId);
                    EditorsHelper.initSelectWithValueOrChooseFirst($mailingsList, mailingEditorBase.mailingId);
                }
            });
        };
        followupMailingEditorBase.onMailingSelectChange = function(val) {
            baseMailingEditorBase.selectedFollowUpMailingId = val;
            this.setSelectMailingOptions(val);
        };
        var nodeEditor = EditorsHelper.registerEditor("followup_mailing", {
            formName: "followupMailingForm",
            safeToSave: false,
            getTitle: function() {
                return t("workflow.mailing.followup");
            },
            fillEditor: function(node) {
                var $form = $('form[name="' + this.formName + '"]');
                var $messages = $("#followup_mailing-editor .editor-error-messages");
                followupMailingEditorBase.fillEditorBase(node);
                baseMailingEditorBase.fillEditorBase(node);
                $form.submit(false);
                $form.get(0).reset();
                EditorsHelper.fillFormFromObject(this.formName, node.getData(), "");
                if (followupMailingData.disableFollowup == "true") {
                    $messages.html(t("error.workflow.followupPermission"));
                    $messages.css("display", "block");
                    baseMailingEditorBase.disableInputs();
                } else {
                    $messages.css("display", "none");
                }
            },
            createNewMailing: function() {
                var data = baseMailingEditorBase.node.getData();
                data.baseMailingId = baseMailingEditorBase.getSelectedMailingOption().val();
                data.decisionCriterion = baseMailingEditorBase.getSelectedDecisionOption().val();
                followupMailingEditorBase.createNewMailing(Def.constants.forwardMailingCreate);
            },
            editMailing: function() {
                var data = baseMailingEditorBase.node.getData();
                data.baseMailingId = baseMailingEditorBase.getSelectedMailingOption().val();
                data.decisionCriterion = baseMailingEditorBase.getSelectedDecisionOption().val();
                followupMailingEditorBase.editMailing(Def.constants.forwardMailingEdit);
            },
            copyMailing: function() {
                var data = baseMailingEditorBase.node.getData();
                data.baseMailingId = baseMailingEditorBase.getSelectedMailingOption().val();
                data.decisionCriterion = baseMailingEditorBase.getSelectedDecisionOption().val();
                followupMailingEditorBase.copyMailing(Def.constants.forwardMailingCopy);
            },
            saveEditor: function() {
                baseMailingEditorBase.disableInputs();
                followupMailingEditorBase.disableInputs();
                this.setNodeFields();
                return EditorsHelper.formToObject(this.formName);
            },
            saveWithCheckStatus: function() {
                var isNotSent = followupMailingEditorBase.showSecurityQuestion();
                if (isNotSent) {
                    EditorsHelper.saveCurrentEditorWithUndo(false, followupMailingEditorBase);
                }
            },
            validateEditor: function(save) {
                var baseMailingSelector = $(baseMailingEditorBase.formNameJId + " " + baseMailingEditorBase.selectNameJId);
                var followupMailingSelector = $(followupMailingEditorBase.formNameJId + " " + followupMailingEditorBase.selectNameJId);
                if (baseMailingSelector.val() > 0 && followupMailingSelector.val() > 0) {
                    if (save) {
                        save();
                    } else {
                        EditorsHelper.saveCurrentEditorWithUndo();
                    }
                } else {
                    var $message = $("#followup_mailing-editor").find(".editor-error-messages");
                    $message.html(t("error.workflow.noMailing"));
                    $message.css("display", "block");
                }
            },
            setNodeFields: function() {
                baseMailingEditorBase.node.setFilled(parseInt(baseMailingEditorBase.mailingId, 10) > 0 && parseInt(followupMailingEditorBase.mailingId, 10) > 0);
            }
        });
        controller.addAction({
            click: "followup-mailing-editor-base-sort-shortname"
        }, function() {
            followupMailingEditorBase.onMailingSortClick("shortname", "shortname");
        });
        controller.addAction({
            click: "followup-mailing-editor-base-sort-data"
        }, function() {
            var config = Utils.getConfigData(this.el);
            followupMailingEditorBase.onMailingSortClick("shortname", config.sortByDate);
        });
        controller.addAction({
            change: "followup-mailing-editor-base-status-change"
        }, function() {
            followupMailingEditorBase.onMailingsStatusChange(this.el.val());
        });
        controller.addAction({
            change: "followup-mailing-editor-base-select-change"
        }, function() {
            followupMailingEditorBase.onMailingSelectChange(this.el.val());
        });
        controller.addAction({
            click: "followup-base-mailing-editor-base-sort-shortname"
        }, function() {
            baseMailingEditorBase.onMailingSortClick("shortname", "shortname");
        });
        controller.addAction({
            click: "followup-base-mailing-editor-base-sort-data"
        }, function() {
            var config = Utils.getConfigData(this.el);
            baseMailingEditorBase.onMailingSortClick("shortname", config.sortByDate);
        });
        controller.addAction({
            change: "followup-base-mailing-editor-base-status-change"
        }, function() {
            baseMailingEditorBase.onMailingsStatusChange(this.el.val());
        });
        controller.addAction({
            change: "followup-base-mailing-editor-base-select-change"
        }, function() {
            baseMailingEditorBase.onMailingSelectChange(this.el.val());
        });
        controller.addAction({
            click: "followup-base-mailing-editor-base-secure-cancel"
        }, function() {
            followupMailingEditorBase.cancelSecurityDialog();
        });
        controller.addAction({
            click: "followup-mailing-editor-base-secure-cancel"
        }, function() {
            followupMailingEditorBase.cancelSecurityDialog();
        });
        controller.addAction({
            click: "followup-mailing-editor-save"
        }, function() {
            nodeEditor.validateEditor(nodeEditor.saveWithCheckStatus);
        });
    });
    this.addDomInitializer("mailing_mediatype_sms-editor-initializer", function() {
        const mailingData = this.config;
        const smsMailingEditorBase = new MailingEditorHelper(mailingData, submitWorkflowForm);
        const nodeEditor = EditorsHelper.registerEditor("mailing_mediatype_sms", {
            formName: "smsMailingForm",
            safeToSave: false,
            getTitle: function() {
                return t("workflow.mailing.mediatype_sms");
            },
            fillEditor: function(node) {
                const $form = $('form[name="' + this.formName + '"]');
                $form.submit(false);
                $form.get(0).reset();
                EditorsHelper.fillFormFromObject(this.formName, node.getData(), "");
                smsMailingEditorBase.fillEditorBase(node);
                $("#mailing_mediatype_sms-editor .editor-error-messages").css("display", "none");
            },
            createNewMailing: function() {
                smsMailingEditorBase.createNewMailing(Def.constants.forwardMailingCreate);
            },
            editMailing: function() {
                smsMailingEditorBase.editMailing(Def.constants.forwardMailingEdit);
            },
            saveEditor: function() {
                smsMailingEditorBase.setNodeFields();
                smsMailingEditorBase.disableInputs();
                return EditorsHelper.formToObject(this.formName);
            },
            saveWithCheckStatus: function() {
                const isNotSent = smsMailingEditorBase.showSecurityQuestion();
                if (isNotSent) {
                    EditorsHelper.saveCurrentEditorWithUndo(false, smsMailingEditorBase);
                }
            },
            copyMailing: function() {
                smsMailingEditorBase.copyMailing(Def.constants.forwardMailingCopy);
            }
        });
        controller.addAction({
            click: "sms-mailing-editor-save"
        }, function() {
            smsMailingEditorBase.validateEditor(nodeEditor.saveWithCheckStatus);
        });
        controller.addAction({
            click: "action-mailing-editor-base-sort-shortname"
        }, function() {
            smsMailingEditorBase.onMailingSortClick("shortname", "shortname");
        });
        controller.addAction({
            click: "action-mailing-editor-base-sort-data"
        }, function() {
            const config = Utils.getConfigData(this.el);
            smsMailingEditorBase.onMailingSortClick("shortname", config.sortByDate);
        });
        controller.addAction({
            change: "action-mailing-editor-base-status-change"
        }, function() {
            smsMailingEditorBase.onMailingsStatusChange(this.el.val());
        });
        controller.addAction({
            change: "action-mailing-editor-base-select-change"
        }, function() {
            smsMailingEditorBase.onMailingSelectChange(this.el.val());
        });
        controller.addAction({
            click: "action-mailing-editor-base-secure-cancel"
        }, function() {
            smsMailingEditorBase.cancelSecurityDialog();
        });
    });
    this.addDomInitializer("mailing_mediatype_post-editor-initializer", function() {
        const mailingData = this.config;
        const postMailingEditorBase = new MailingEditorHelper(mailingData, submitWorkflowForm);
        const nodeEditor = EditorsHelper.registerEditor("mailing_mediatype_post", {
            formName: "postMailingForm",
            safeToSave: false,
            getTitle: function() {
                return t("workflow.mailing.mediatype_post");
            },
            fillEditor: function(node) {
                const $form = $('form[name="' + this.formName + '"]');
                $form.submit(false);
                $form.get(0).reset();
                EditorsHelper.fillFormFromObject(this.formName, node.getData(), "");
                postMailingEditorBase.fillEditorBase(node);
                $("#mailing_mediatype_post-editor .editor-error-messages").css("display", "none");
            },
            createNewMailing: function() {
                postMailingEditorBase.createNewMailing(Def.constants.forwardMailingCreate);
            },
            editMailing: function() {
                postMailingEditorBase.editMailing(Def.constants.forwardMailingEdit);
            },
            saveEditor: function() {
                postMailingEditorBase.setNodeFields();
                postMailingEditorBase.disableInputs();
                return EditorsHelper.formToObject(this.formName);
            },
            saveWithCheckStatus: function() {
                const isNotSent = postMailingEditorBase.showSecurityQuestion();
                if (isNotSent) {
                    EditorsHelper.saveCurrentEditorWithUndo(false, postMailingEditorBase);
                }
            },
            copyMailing: function() {
                postMailingEditorBase.copyMailing(Def.constants.forwardMailingCopy);
            }
        });
        controller.addAction({
            click: "post-mailing-editor-save"
        }, function() {
            postMailingEditorBase.validateEditor(nodeEditor.saveWithCheckStatus);
        });
        controller.addAction({
            click: "action-mailing-editor-base-sort-shortname"
        }, function() {
            postMailingEditorBase.onMailingSortClick("shortname", "shortname");
        });
        controller.addAction({
            click: "action-mailing-editor-base-sort-data"
        }, function() {
            const config = Utils.getConfigData(this.el);
            postMailingEditorBase.onMailingSortClick("shortname", config.sortByDate);
        });
        controller.addAction({
            change: "action-mailing-editor-base-status-change"
        }, function() {
            postMailingEditorBase.onMailingsStatusChange(this.el.val());
        });
        controller.addAction({
            change: "action-mailing-editor-base-select-change"
        }, function() {
            postMailingEditorBase.onMailingSelectChange(this.el.val());
        });
        controller.addAction({
            click: "action-mailing-editor-base-secure-cancel"
        }, function() {
            postMailingEditorBase.cancelSecurityDialog();
        });
    });
    this.addDomInitializer("action-mailing-editor-initializer", function() {
        var actionMailingData = this.config;
        var actionbasedMailingEditorBase = new MailingEditorHelper(actionMailingData, submitWorkflowForm);
        var nodeEditor = EditorsHelper.registerEditor("actionbased_mailing", {
            formName: "actionbasedMailingForm",
            safeToSave: false,
            getTitle: function() {
                return t("workflow.mailing.action_based");
            },
            fillEditor: function(node) {
                var $form = $('form[name="' + this.formName + '"]');
                $form.submit(false);
                $form.get(0).reset();
                EditorsHelper.fillFormFromObject(this.formName, node.getData(), "");
                actionbasedMailingEditorBase.fillEditorBase(node);
                $("#actionbased_mailing-editor .editor-error-messages").css("display", "none");
            },
            createNewMailing: function() {
                actionbasedMailingEditorBase.createNewMailing(Def.constants.forwardMailingCreate);
            },
            editMailing: function() {
                actionbasedMailingEditorBase.editMailing(Def.constants.forwardMailingEdit);
            },
            saveEditor: function() {
                actionbasedMailingEditorBase.setNodeFields();
                actionbasedMailingEditorBase.disableInputs();
                return EditorsHelper.formToObject(this.formName);
            },
            saveWithCheckStatus: function() {
                var isNotSent = actionbasedMailingEditorBase.showSecurityQuestion();
                if (isNotSent) {
                    EditorsHelper.saveCurrentEditorWithUndo(false, actionbasedMailingEditorBase);
                }
            },
            copyMailing: function() {
                actionbasedMailingEditorBase.copyMailing(Def.constants.forwardMailingCopy);
            }
        });
        controller.addAction({
            click: "action-mailing-editor-save"
        }, function() {
            actionbasedMailingEditorBase.validateEditor(nodeEditor.saveWithCheckStatus);
        });
        controller.addAction({
            click: "action-mailing-editor-base-sort-shortname"
        }, function() {
            actionbasedMailingEditorBase.onMailingSortClick("shortname", "shortname");
        });
        controller.addAction({
            click: "action-mailing-editor-base-sort-data"
        }, function() {
            var config = Utils.getConfigData(this.el);
            actionbasedMailingEditorBase.onMailingSortClick("shortname", config.sortByDate);
        });
        controller.addAction({
            change: "action-mailing-editor-base-status-change"
        }, function() {
            actionbasedMailingEditorBase.onMailingsStatusChange(this.el.val());
        });
        controller.addAction({
            change: "action-mailing-editor-base-select-change"
        }, function() {
            actionbasedMailingEditorBase.onMailingSelectChange(this.el.val());
        });
        controller.addAction({
            click: "action-mailing-editor-base-secure-cancel"
        }, function() {
            actionbasedMailingEditorBase.cancelSecurityDialog();
        });
    });
    this.addDomInitializer("date-mailing-initializer", function() {
        var dateMailingData = this.config;
        var datebasedMailingEditorBase = new MailingEditorHelper(dateMailingData, submitWorkflowForm);
        var nodeEditor = EditorsHelper.registerEditor("datebased_mailing", {
            formName: "datebasedMailingForm",
            safeToSave: false,
            getTitle: function() {
                return t("workflow.mailing.date_based");
            },
            fillEditor: function(node) {
                var $form = $('form[name="' + this.formName + '"]');
                $form.submit(false);
                $form.get(0).reset();
                EditorsHelper.fillFormFromObject(this.formName, node.getData(), "");
                datebasedMailingEditorBase.fillEditorBase(node);
                $("#datebased_mailing-editor .editor-error-messages").css("display", "none");
            },
            saveEditor: function() {
                datebasedMailingEditorBase.setNodeFields();
                datebasedMailingEditorBase.disableInputs();
                return EditorsHelper.formToObject(this.formName);
            },
            createNewMailing: function() {
                datebasedMailingEditorBase.createNewMailing(Def.constants.forwardMailingCreate);
            },
            editMailing: function() {
                datebasedMailingEditorBase.editMailing(Def.constants.forwardMailingEdit);
            },
            saveWithCheckStatus: function() {
                var isNotSent = datebasedMailingEditorBase.showSecurityQuestion();
                if (isNotSent) {
                    EditorsHelper.saveCurrentEditorWithUndo(false, datebasedMailingEditorBase);
                }
            },
            copyMailing: function() {
                datebasedMailingEditorBase.copyMailing(Def.constants.forwardMailingCopy);
            }
        });
        controller.addAction({
            click: "date-mailing-editor-base-sort-shortname"
        }, function() {
            datebasedMailingEditorBase.onMailingSortClick("shortname", "shortname");
        });
        controller.addAction({
            click: "date-mailing-editor-base-sort-data"
        }, function() {
            var config = Utils.getConfigData(this.el);
            datebasedMailingEditorBase.onMailingSortClick("shortname", config.sortByDate);
        });
        controller.addAction({
            change: "date-mailing-editor-base-status-change"
        }, function() {
            datebasedMailingEditorBase.onMailingsStatusChange(this.el.val());
        });
        controller.addAction({
            change: "date-mailing-editor-base-select-change"
        }, function() {
            datebasedMailingEditorBase.onMailingSelectChange(this.el.val());
        });
        controller.addAction({
            click: "date-mailing-editor-base-secure-cancel"
        }, function() {
            datebasedMailingEditorBase.cancelSecurityDialog();
        });
        controller.addAction({
            click: "date-mailing-editor-save"
        }, function() {
            datebasedMailingEditorBase.validateEditor(nodeEditor.saveWithCheckStatus);
        });
    });
    this.addAction({
        click: "mailing-editor-copy"
    }, function() {
        EditorsHelper.getCurrentEditor().copyMailing();
    });
    this.addAction({
        click: "mailing-editor-new"
    }, function() {
        EditorsHelper.getCurrentEditor().createNewMailing();
    });
    this.addAction({
        click: "mailing-editor-edit"
    }, function() {
        EditorsHelper.getCurrentEditor().editMailing();
    });
    this.addAction({
        click: "editor-save-current"
    }, function() {
        EditorsHelper.saveCurrentEditorWithUndo();
    });
    this.addAction({
        click: "editor-cancel"
    }, function() {
        EditorsHelper.cancelEditor();
    });
    this.addAction({
        click: "chain-mode"
    }, function() {
        if (editor.isChainMode() || editor.connectSelected()) {
            editor.setChainModeEnabled(false);
        } else {
            editor.setChainModeEnabled(true);
        }
        $(this.el).toggleClass("button-selected", editor.isChainMode());
    });
    this.addAction({
        click: "delete-selected"
    }, function() {
        editor.deleteSelected();
    });
    this.addAction({
        click: "align-all"
    }, function() {
        editor.alignAll();
    });
    this.addAction({
        click: "zoom-in"
    }, function() {
        var slider = $("#slider").slider("instance");
        slider.value(slider.value() + Def.ZOOM_STEP);
        editor.setZoom(slider.value());
    });
    this.addAction({
        click: "zoom-out"
    }, function() {
        var slider = $("#slider").slider("instance");
        slider.value(slider.value() - Def.ZOOM_STEP);
        editor.setZoom(slider.value());
    });
    this.addAction({
        click: "reset-zoom"
    }, function() {
        editor.setZoom(Def.DEFAULT_ZOOM);
        $("#slider").slider("value", Def.DEFAULT_ZOOM);
    });
    this.addAction({
        change: "show-grid"
    }, function() {
        editor.toggleGrid();
    });
    this.addAction({
        click: "workflow-save"
    }, function() {
        saveWorkflowFormData(true, {});
    });
    this.addAction({
        click: "workflow-copy"
    }, function() {
        var workflowId = Def.workflowId;
        var someNonEmptyNode = editor.getNodes().some(function(node) {
            return node.isFilled();
        });
        Dialogs.confirmCopy(someNonEmptyNode).done(function(response) {
            window.location.href = AGN.url("/workflow/copy.action" + "?workflowId=" + workflowId + "&isWithContent=" + (response == true));
            return false;
        });
    });
    this.addAction({
        change: "workflow-view-change-status"
    }, function() {
        if ($("#workflow_active").is(":checked")) {
            $("#workflow-status").val(Def.constants.statusActive);
        } else {
            $("#workflow-status").val(Def.constants.statusInactive);
        }
    });
    this.addAction({
        click: "evaluate-statistic"
    }, function() {
        const $iframe = $("#statistic-iframe");
        $iframe.removeClass("hidden");
        $iframe.attr("src", Def.statisticUrl);
    });
    this.addAction({
        click: "undo"
    }, function() {
        editor.undo();
    });
    this.addAction({
        click: "create-workflow-enlarged-editor-modal"
    }, function() {
        editor.enlargeEditor(function() {
            submitWorkflowForm(true);
        });
    });
    this.addAction({
        click: "workflow-generate-pdf"
    }, function() {
        var isNewWorkflow = Def.workflowId <= 0 || !Def.shortname;
        var hasUnsavedChanges = editor.hasUnsavedChanges();
        if (isNewWorkflow || hasUnsavedChanges) {
            var message = "";
            if (isNewWorkflow) {
                message = t("workflow.pdf.save_new_campaign");
            } else if (hasUnsavedChanges) {
                message = t("workflow.pdf.save_modified_campaign");
            }
            Dialogs.confirmSaveBeforePdfGenerating(function() {
                submitWorkflowForm(true);
            }, message);
        } else {
            window.location.href = AGN.url("/workflow/" + Def.workflowId + "/generatePDF.action");
            AGN.Lib.Loader.hide();
        }
    });
    this.addAction({
        click: "workflow-dry-run"
    }, function() {
        var isStartTesting = false;
        var newStatus = Def.constants.statusOpen;
        if (Def.constants.initialWorkflowStatus != Def.constants.statusTesting) {
            isStartTesting = true;
            newStatus = Def.constants.statusTesting;
        }
        Dialogs.confirmTestingStartStop(isStartTesting).done(function() {
            var activationCheckbox = $("#workflow_active");
            activationCheckbox.prop("disabled", true);
            saveWorkflowFormData(true, {
                status: newStatus
            });
        });
    });
    this.addAction({
        click: "workflow-pause"
    }, function() {
        saveWorkflowFormData(true, {
            status: Def.constants.statusPaused
        });
    });
    this.addAction({
        click: "workflow-unpause"
    }, function() {
        unpause(true, {
            status: Def.constants.statusActive
        });
    });
    this.addAction({
        click: "workflow-activate"
    }, function() {
        activate(true, {
            status: Def.constants.statusActive
        });
    });
    this.addAction({
        click: "workflow-deactivate"
    }, function() {
        deactivate(true, {
            status: Def.constants.statusInactive
        });
    });
    $(window).on("resize viewportChanged", function() {
        if (editor) {
            editor.updateMinimap();
        }
    });
    $(document).on("keydown", function(e) {
        if (e.target && !$(e.target).is("input, textarea")) {
            switch (e.keyCode) {
              case Def.KEY_SPACE:
                editor.setPanningEnabled(true);
                break;

              case Def.KEY_SHIFT:
                editor.setMultiConnectionEnabled(true);
                break;

              case Def.KEY_CTRL:
                editor.setMouseWheelZoomEnabled(true);
                break;
            }
        }
    });
    $(document).on("keyup", function(e) {
        if (e.target && !$(e.target).is("input, textarea")) {
            switch (e.keyCode) {
              case Def.KEY_DELETE:
                editor.deleteSelected();
                break;

              case Def.KEY_SPACE:
                editor.setPanningEnabled(false);
                break;

              case Def.KEY_SHIFT:
                editor.setMultiConnectionEnabled(false);
                break;

              case Def.KEY_ENTER:
                editor.editIcon();
                break;

              case Def.KEY_CTRL:
                editor.setMouseWheelZoomEnabled(false);
                break;
            }
        }
    });
    function submitWorkflowForm(validate, options) {
        var isActiveChecked = $("#workflow_active").is(":checked");
        var initialWorkflowStatus = Def.constants.initialWorkflowStatus;
        var inactivating = initialWorkflowStatus === Def.constants.statusActive && !isActiveChecked;
        var activating = initialWorkflowStatus !== Def.constants.statusActive && isActiveChecked;
        if (inactivating || !Utils.checkActivation(true)) {
            if (activating) {
                activate(validate, options);
            } else if (inactivating) {
                deactivate(validate, options);
            } else {
                saveWorkflowFormData(validate, options);
            }
        }
    }
    function activate(validate, options) {
        Dialogs.Activation(function() {
            editor.getNodesByTypes([ Def.NODE_TYPE_START ]).filter(isStartNodeDateInPast).forEach(adjustStartDate);
            saveWorkflowFormData(validate, options);
        }, getMailingNames().join("<br/>"));
    }
    function isStartNodeDateInPast(startNode) {
        const startDate = _.clone(startNode.data.date);
        startDate.setHours(startNode.data.hour);
        startDate.setMinutes(startNode.data.minute);
        startDate.setSeconds(0);
        return startDate <= new Date();
    }
    function adjustStartDate(startNode) {
        const currentAdminTime = $.ajax({
            url: AGN.url("/workflow/getCurrentAdminTime.action"),
            async: false
        }).responseJSON || {};
        const hour = currentAdminTime.hour;
        const minute = currentAdminTime.minute;
        if (!hour || !minute) {
            return;
        }
        startNode.data.date = new Date();
        const startDate = startNode.data.date;
        startDate.setHours(parseInt(hour, 10));
        startDate.setMinutes(parseInt(minute, 10));
        startDate.setSeconds(startDate.getSeconds() > 55 ? startDate.getSeconds() + 120 : startDate.getSeconds() + 60);
        startNode.data.hour = startDate.getHours();
        startNode.data.minute = startDate.getMinutes();
        editor.updateNodeTitle(startNode, true);
        AGN.Lib.Form.get($("form#workflowForm")).setValueOnce("startTimeAdjusted", true);
    }
    function unpause(validate, options) {
        Dialogs.Activation(function() {
            saveWorkflowFormData(validate, options);
        }, {}, true);
    }
    function deactivate(validate, options) {
        Dialogs.Deactivation(function() {
            saveWorkflowFormData(validate, options);
        });
    }
    function saveWorkflowFormData(validate, options) {
        var save = function() {
            var form = AGN.Lib.Form.get($("form#workflowForm"));
            options = $.extend({}, options);
            Object.keys(options).forEach(function(key) {
                form.setValueOnce(key, options[key]);
            });
            if (editor.isGridDisplayed()) {
                editor.toggleGrid();
            }
            form.setValueOnce("workflowSchema", editor.serializeIcons());
            form.setValueOnce("editorPositionLeft", -1);
            form.setValueOnce("editorPositionTop", -1);
            form.submit("static");
        };
        if (validate) {
            validateWorkflowBaseData().done(save);
        } else {
            save();
        }
    }
    function getMailingNames() {
        return editor.getNodesByTypes(Def.NODE_TYPES_MAILING).map(function(node) {
            return node.getTitle();
        });
    }
    function validateWorkflowBaseData() {
        var deferred = $.Deferred();
        if ($("#name").val().length < 3) {
            AGN.Lib.Messages(t("workflow.defaults.error"), t("error.workflow.shortName"), "alert");
            deferred.reject();
        } else {
            if (checkMailingTypesConvertingRequired()) {
                return Confirm.create(Template.text("mailing-types-replace-modal"));
            } else {
                deferred.resolve();
            }
        }
        return deferred.promise();
    }
    function checkMailingTypesConvertingRequired() {
        var icons = editor.getNodes();
        var startType = "UNKNOWN";
        var mailingStartTypes = {};
        for (var i = 0; i < icons.length; i++) {
            var icon = icons[i];
            if (icon.type === Def.NODE_TYPE_START && icon.filled) {
                var type = "UNKNOWN";
                switch (icon.data.startType) {
                  case Def.constants.startTypeDate:
                    type = "DATE";
                    break;

                  case Def.constants.startTypeEvent:
                    switch (icon.event) {
                      case Def.constants.startEventDate:
                        type = "RULE";
                        break;

                      case Def.constants.startEventReaction:
                        type = "REACTION";
                        break;
                    }
                    break;
                }
                if (startType !== type) {
                    if (startType === "UNKNOWN") {
                        startType = type;
                    } else {
                        return false;
                    }
                }
            }
            switch (icon.type) {
              case Def.NODE_TYPE_MAILING:
              case Def.NODE_TYPE_FOLLOWUP_MAILING:
              case Def.NODE_TYPE_MAILING_MEDIATYPE_SMS:
              case Def.NODE_TYPE_MAILING_MEDIATYPE_POST:
                mailingStartTypes["DATE"] = true;
                break;

              case Def.NODE_TYPE_ACTION_BASED_MAILING:
                mailingStartTypes["REACTION"] = true;
                break;

              case Def.NODE_TYPE_DATE_BASED_MAILING:
                mailingStartTypes["RULE"] = true;
                break;
            }
        }
        if (startType !== "UNKNOWN") {
            mailingStartTypes = Object.keys(mailingStartTypes);
            if (mailingStartTypes.length === 1) {
                if (startType !== mailingStartTypes[0]) {
                    return true;
                }
            } else {
                if (mailingStartTypes.length > 1) {
                    return true;
                }
            }
        }
        return false;
    }
    this.addDomInitializer("open-edit-icon-initializer", function($e) {
        var data = $e.json();
        var nodeId = data.nodeId;
        var elementValue = data.elementValue;
        if (nodeId) {
            var node = Node.get($("#" + nodeId));
            if (node && elementValue) {
                switch (node.type) {
                  case Def.NODE_TYPE_MAILING:
                  case Def.NODE_TYPE_ACTION_BASED_MAILING:
                  case Def.NODE_TYPE_MAILING_MEDIATYPE_SMS:
                  case Def.NODE_TYPE_MAILING_MEDIATYPE_POST:
                  case Def.NODE_TYPE_DATE_BASED_MAILING:
                  case Def.NODE_TYPE_FOLLOWUP_MAILING:
                    node.data.mailingId = elementValue;
                    break;

                  case Def.NODE_TYPE_RECIPIENT:
                    if (elementValue != "0" && $.inArray(elementValue, node.data.targets) == -1) {
                        node.data.targets.push(elementValue);
                    }
                    break;

                  case Def.NODE_TYPE_ARCHIVE:
                    node.data.campaignId = elementValue;
                    break;

                  case Def.NODE_TYPE_IMPORT:
                  case Def.NODE_TYPE_EXPORT:
                    node.data.importexportId = elementValue;
                    break;

                  default:
                    console.debug("Unknown node type");
                }
                editor.editIcon(node);
            }
        }
    });
});

AGN.Lib.Controller.new("wysiwyg-agn-tags", function() {
    var Template = AGN.Lib.Template, Select = AGN.Lib.Select, Confirm = AGN.Lib.Confirm;
    var createSelect;
    var createTextInput;
    var insertTagsHandlers = {};
    var selectTagsHandlers = {};
    insertTagsHandlers["agnFULLVIEW"] = function() {
        const $option = $("#agn-tag-name").children("option:selected");
        const name = $option.val();
        if (!name) {
            return;
        }
        if (!$("#createLinkToggle").prop("checked")) {
            return "[" + name + "]";
        }
        var linkText = $("#tagLinkText").val();
        if (!linkText) {
            linkText = "fullview";
        }
        return '<a href="[' + name + ']">' + linkText + "</a>";
    };
    insertTagsHandlers["agnWEBVIEW"] = insertTagsHandlers["agnFULLVIEW"];
    insertTagsHandlers["agnFORM"] = function() {
        var $option = $("#agn-tag-name").children("option:selected");
        var name = $option.val(), attributes = $option.data("attributes");
        if (!name) {
            return;
        }
        var createLinkChecked = $("#createLinkToggle").prop("checked") === true;
        if (createLinkChecked) {
            var linkText = $("#tagLinkText").val();
            if (!linkText) {
                var attrIndex = attributes.findIndex(function(attr) {
                    return attr.name === "name";
                });
                if (attrIndex > -1) {
                    linkText = $("#agn-tag-attribute-" + attrIndex).val();
                }
            }
            if (linkText) {
                return '<a href="[' + name + composeTagAttributes(attributes) + ']">' + linkText + "</a>";
            }
        }
        return "[" + name + composeTagAttributes(attributes) + "]";
    };
    selectTagsHandlers["agnFORM"] = function() {
        var $toggle = $("#createLinkToggle");
        if ($toggle.prop("checked") !== true) {
            $("#tagLinkParams").hide();
        }
        $toggle.on("change", function() {
            var checked = $(this).prop("checked");
            if (checked === false) {
                $("#tagLinkParams").hide();
            } else {
                $("#tagLinkParams").show();
            }
        });
    };
    selectTagsHandlers["agnFULLVIEW"] = selectTagsHandlers["agnFORM"];
    selectTagsHandlers["agnWEBVIEW"] = selectTagsHandlers["agnFULLVIEW"];
    function selectTag(name, attributes) {
        var $inputs = $("#agn-tag-attributes");
        $inputs.empty();
        if (attributes && attributes.length > 0) {
            attributes.forEach(function(attribute, index) {
                switch (attribute.type) {
                  case "SELECT":
                    $inputs.append(createSelect({
                        index: index,
                        name: attribute.name,
                        options: attribute.options
                    }));
                    break;

                  case "TEXT":
                    $inputs.append(createTextInput({
                        index: index,
                        name: attribute.name
                    }));
                    break;
                }
            });
        }
        try {
            const extendedAttributes = Template.dom(name + "-extended-attributes");
            if (extendedAttributes) {
                $inputs.append(extendedAttributes);
            }
        } catch (e) {}
        AGN.runAll($inputs);
    }
    function composeTag() {
        var $option = $("#agn-tag-name").children("option:selected");
        var name = $option.val();
        if (name) {
            return "[" + name + composeTagAttributes($option.data("attributes")) + "]";
        } else {
            return null;
        }
    }
    function composeTagAttributes(attributes) {
        var result = "";
        if (attributes && attributes.length > 0) {
            attributes.forEach(function(attribute, index) {
                var $input = $("#agn-tag-attribute-" + index);
                result += " " + attribute.name + '="' + _.escape($input.val()) + '"';
            });
        }
        return result;
    }
    this.addDomInitializer("wysiwyg-agn-tags", function() {
        createSelect = Template.prepare("agn-tag-select-attribute");
        createTextInput = Template.prepare("agn-tag-text-attribute");
        var $select = $("#agn-tag-name");
        this.config.forEach(function(tag) {
            var $option = $("<option>", {
                value: tag.name,
                text: tag.name
            });
            $select.append($option);
            $option.data("attributes", tag.attributes);
        });
        Select.get($select).selectFirstValue();
        $select.trigger("change");
    });
    this.addAction({
        change: "select-agn-tag"
    }, function() {
        var $option = this.el.children("option:selected");
        selectTag($option.val(), $option.data("attributes"));
        var tagName = $option.val(), handler = selectTagsHandlers[tagName];
        if (handler) {
            handler();
        }
    });
    this.addAction({
        click: "insert-agn-tag"
    }, function() {
        var tagName = $("#agn-tag-name").val();
        var handler = insertTagsHandlers[tagName];
        var code;
        if (handler) {
            code = handler();
        } else {
            code = composeTag();
        }
        if (code) {
            Confirm.get(this.el).positive(code);
        }
    });
});

AGN.Lib.Controller.new("wysiwyg-image-browser", function() {
    var config;
    var funcNum = getUrlParam("CKEditorFuncNum");
    var mailingId = getUrlParam("mailingID");
    this.addDomInitializer("wysiwyg-image-browser", function() {
        config = this.config;
        updateImg();
    });
    this.addAction({
        click: "submit-image"
    }, function() {
        var activeImageTab = $("li[image-tab-name].active").attr("image-tab-name");
        if (activeImageTab === "mediapool") {
            submit_mediapool_images_tab();
        } else {
            submit_other_images_tab();
        }
    });
    this.addAction({
        change: "update-image"
    }, function() {
        updateImg();
    });
    this.addAction({
        click: "close-window"
    }, function() {
        window.close();
    });
    function updateImg() {
        var imageNameValue = getOtherImgSelectVal();
        var $imgPreview = $("#other-images-tab .image-preview");
        var $noImgMessage = $("#other-images-tab .no_image_message");
        if (!imageNameValue || !imageNameValue.length) {
            $noImgMessage.show();
            $imgPreview.hide();
        } else {
            $imgPreview.attr("src", normalizeName(imageNameValue));
            $imgPreview.show();
            $noImgMessage.hide();
        }
        return 1;
    }
    function getUrlParam(paramName) {
        var reParam = new RegExp("(?:[?&]|&amp;)" + paramName + "=([^&]+)", "i");
        var match = window.location.search.match(reParam);
        return match && match.length > 1 ? match[1] : "";
    }
    function submit_other_images_tab() {
        var correctLink = normalizeName(getOtherImgSelectVal());
        window.opener.CKEDITOR.tools.callFunction(funcNum, correctLink);
        window.close();
    }
    function submit_mediapool_images_tab() {
        var selectedImgContainer = document.querySelector('[data-action="mpSelectImage"].active');
        if (selectedImgContainer) {
            var imgSrc = selectedImgContainer.querySelector("img").getAttribute("src");
            window.opener.CKEDITOR.tools.callFunction(funcNum, imgSrc);
            window.close();
        }
    }
    function normalizeName(fname) {
        if (fname.substr(0, 4).toLowerCase() !== "http") {
            return config.rdirDomain + "/image?ci=" + config.companyId + "&mi=" + mailingId + "&name=" + encodeURIComponent(fname);
        }
        return encodeURI(fname);
    }
    function getOtherImgSelectVal() {
        return $('#other-images-tab [data-action="update-image"]').val();
    }
});

AGN.Lib.Controller.new("dashboard", function() {
    var self = this;
    var newsCounters;
    var statisticConfig;
    var NEWS_DATE_URL, NEW_COUNTE_URL;
    this.addDomInitializer("dashboard-news-counters", function() {
        var config = this.config;
        NEWS_DATE_URL = config.newsDateUrl;
        NEW_COUNTE_URL = config.newsCountersUrl;
        $.ajax({
            url: NEW_COUNTE_URL
        }).done(function(data) {
            if (!!data["counters"]) {
                newsCounters = data["counters"];
                updateNewsButtonNumber();
                if (getUnreadCountSafe("MESSAGE") && !$(".modal-news").exists()) {
                    showNewsPopup();
                }
            }
        });
    });
    this.addDomInitializer("dashboard-statistics", function() {
        statisticConfig = this.config;
        if (statisticConfig.mailingId > 0) {
            updateCharts(statisticConfig.mailingId);
        }
    });
    this.addAction({
        click: "open-mailing-statistics"
    }, function() {
        if (statisticConfig.mailingId > 0) {
            AGN.Lib.Page.reload(statisticConfig.mailingStatisticsLinkPattern.replace(":mailing-id:", statisticConfig.mailingId));
        }
    });
    this.addAction({
        change: "update-template-links"
    }, function() {
        self.runInitializer("UpdateDashboardTemplateLinks");
    });
    this.addAction({
        change: "statistics-select-mailing"
    }, function() {
        statisticConfig.mailingId = this.el.val();
        updateCharts(statisticConfig.mailingId);
        return false;
    });
    function updateCharts(mailingId) {
        jQuery.ajax({
            type: "GET",
            url: statisticConfig.urls.STATISTICS,
            data: {
                mailingId: mailingId
            },
            success: function(data) {
                var rowNames;
                var rowValues;
                var sumValue;
                data = _.merge({
                    common: [ [ "no Data", "0" ] ],
                    clickers: [ [ "no Data", "0" ] ],
                    clickersPercent: [ 0 ],
                    openers: [ [ "no Data", "0" ] ],
                    openersPercent: [ 0 ]
                }, data);
                rowNames = [];
                rowValues = [];
                for (var i = 0; i < data["common"].length; i++) {
                    var value = parseInt(data["common"][i][1]);
                    rowNames.push(data["common"][i][0]);
                    rowValues.push(value);
                }
                c3.generate(AGN.Lib.DashboardStatisticsService.data.statChartData.build(rowNames, rowValues));
                rowNames = [];
                rowValues = [];
                sumValue = 0;
                for (var i = 0; i < data["clickers"].length; i++) {
                    var value = roundTo(data["clickers"][i][1] * 100, 1);
                    rowNames.push(data["clickers"][i][0]);
                    rowValues.push(value);
                    sumValue += value;
                }
                if (!isNaN(sumValue) && sumValue > 0) {
                    for (var i = 0; i < rowValues.length; i++) {
                        rowNames[i] += " " + roundTo(100 * rowValues[i] / sumValue, 1) + "%";
                    }
                }
                var clickChartTitle = roundTo(data["clickersPercent"][0] * 100, 1) + "%*";
                c3.generate(AGN.Lib.DashboardStatisticsService.data.clickChartData.build(clickChartTitle, rowNames, rowValues));
                rowNames = [];
                rowValues = [];
                sumValue = 0;
                for (var i = 0; i < data["openers"].length; i++) {
                    var value = roundTo(data["openers"][i][1] * 100, 1);
                    rowNames.push(data["openers"][i][0]);
                    rowValues.push(value);
                    sumValue += value;
                }
                if (!isNaN(sumValue) && sumValue > 0) {
                    for (var i = 0; i < rowValues.length; i++) {
                        rowNames[i] += " " + roundTo(100 * rowValues[i] / sumValue, 1) + "%";
                    }
                }
                var viewChartTitle = roundTo(data["openersPercent"][0] * 100, 1) + "%*";
                c3.generate(AGN.Lib.DashboardStatisticsService.data.viewChartData.build(viewChartTitle, rowNames, rowValues));
                AGN.Lib.CoreInitializer.run("equalizer");
            }
        });
    }
    function roundTo(number, fractionalDigits) {
        return parseFloat(number).toFixed(fractionalDigits) * 1;
    }
    this.addAction({
        click: "showNewsPopup"
    }, function() {
        showNewsPopup();
    });
    this.addAction({
        click: "chooseNewsType"
    }, function() {
        var type = this.el.parent().data("news-type");
        setNewsDate(type);
    });
    function showNewsPopup() {
        var openedNewsType = "MESSAGE";
        var newsCount = 0;
        var availableMessagesCount = getAvailableCountSafe("MESSAGE");
        if (availableMessagesCount < 1) {
            var wasChanged = false;
            for (var key in newsCounters) {
                if (newsCounters.hasOwnProperty(key)) {
                    var count = getUnreadCountSafe(key);
                    if (count > newsCount) {
                        newsCount = count;
                        openedNewsType = key;
                        wasChanged = true;
                    }
                }
            }
            if (!wasChanged) {
                for (key in newsCounters) {
                    if (newsCounters.hasOwnProperty(key)) {
                        count = getAvailableCountSafe(key);
                        if (count > newsCount) {
                            newsCount = count;
                            openedNewsType = key;
                        }
                    }
                }
            }
        }
        AGN.Lib.Modal.createFromTemplate({
            openedNewsType: openedNewsType
        }, "modal-news");
        $("#buttonNewsCounter").text("");
        $(".l-news-menu-item").each(function(index) {
            var $el = $(this);
            var unread = getUnreadCountSafe($el.data("news-type"));
            if (unread > 0) {
                $el.find(".l-news-menu-counter").text(unread);
            } else {
                $el.find(".l-news-menu-counter").html("&nbsp;");
            }
            if ($(this).hasClass("active")) {
                setNewsDate($el.data("news-type"));
            }
        });
        updateNewsButtonNumber();
    }
    function setNewsDate(type) {
        if (getUnreadCountSafe(type) > 0) {
            $("#newsCounter" + type).html("&nbsp;");
            $.ajax({
                url: NEWS_DATE_URL,
                data: {
                    type: type
                }
            });
            newsCounters[type]["unreadCount"] = 0;
            updateNewsButtonNumber();
        }
    }
    Number.isInteger = Number.isInteger || function(value) {
        return typeof value === "number" && isFinite(value) && Math.floor(value) === value;
    };
    function updateNewsButtonNumber() {
        var count = getUnreadCountSafe("NEWS");
        var buttonNewsCounter = $("#buttonNewsCounter");
        var newsCounterBox = buttonNewsCounter.parent();
        var paddingTop = "5px";
        var paddingBottom = "5px";
        var text = "";
        if (count > 0) {
            newsCounterBox.removeClass("hidden");
            paddingTop = "4px";
            paddingBottom = "4px";
            text = count;
        } else {
            newsCounterBox.addClass("hidden");
        }
        newsCounterBox.parent().css("padding-top", paddingTop);
        newsCounterBox.parent().css("padding-bottom", paddingBottom);
        buttonNewsCounter.text(text);
        return count;
    }
    function getUnreadCountSafe(type) {
        if (!!newsCounters && !!newsCounters[type] && Number.isInteger(newsCounters[type]["unreadCount"])) {
            return newsCounters[type]["unreadCount"];
        }
        return 0;
    }
    function getAvailableCountSafe(type) {
        if (!!newsCounters && !!newsCounters[type] && Number.isInteger(newsCounters[type]["availableCount"])) {
            return newsCounters[type]["availableCount"];
        }
        return 0;
    }
    this.addInitializer("UpdateDashboardTemplateLinks", function($scope) {
        if (!$scope) {
            $scope = $(document);
        }
        var $targets = $scope.find(".js-template-link"), templateID = $('[data-action="update-template-links"]').val();
        _.each($targets, function(target) {
            var $target = $(target), link = $target.attr("href");
            link = link.replace(/templateID=\d+/, "templateID=" + templateID);
            $target.attr("href", link);
        });
    });
    this.addInitializer("EndlessScroll", function($scope) {
        if (!$scope) {
            $scope = $(document);
        }
        var $endlessScroll = $scope.find(".js-endless-scroll");
        if ($endlessScroll.length < 1) {
            return;
        }
        $endlessScroll.each(function(index) {
            var currentPage = 1;
            var currentScroll = $(this);
            currentScroll.endlessScroll({
                pagesToKeep: null,
                fireOnce: true,
                fireDelay: 1e3,
                loader: "",
                insertAfter: ".js-endless-scroll .js-endless-scroll-content",
                ceaseFire: function() {
                    return currentScroll.find(".message-list-item-last").length !== 0;
                },
                callback: function() {
                    var jqhxr;
                    AGN.Lib.Loader.prevent();
                    jqhxr = $.ajax({
                        method: "GET",
                        url: currentScroll.data("url"),
                        data: {
                            page: currentPage + 1
                        }
                    });
                    currentScroll.find(".js-endless-scroll-content").append('<div class="message-list-loader"><i class="icon icon-refresh icon-spin"></i></div>');
                    jqhxr.done(function(resp) {
                        currentPage += 1;
                        currentScroll.find(".js-endless-scroll-content").append(resp);
                        currentScroll.find(".message-list-loader").remove();
                        AGN.Lib.CoreInitializer.run("icons-defs", currentScroll);
                    });
                    return jqhxr;
                }
            });
        });
    });
    this.addAction({
        click: "copy-recent-mailing"
    }, function() {
        performRecentMailingBtnAction(this, "/mailing/{mailing-id}/copy.action");
    });
    this.addAction({
        click: "edit-recent-mailing"
    }, function() {
        performRecentMailingBtnAction(this, "/mailing/{mailing-id}/settings.action");
    });
    this.addAction({
        click: "open-recent-mailing-statistic"
    }, function() {
        performRecentMailingBtnAction(this, "/statistics/mailing/{mailing-id}/view.action");
    });
    this.addAction({
        click: "delete-recent-mailing"
    }, function() {
        this.event.preventDefault();
        const $btn = $(this.el);
        $.ajax({
            url: AGN.url("/mailing/" + getRecentMailingId(this) + "/confirmDelete.action"),
            data: {
                fromPage: "dashboard"
            }
        }).done(function(resp) {
            AGN.Lib.RenderMessages($(resp));
            AGN.Lib.Confirm.create(resp).done(function(resp) {
                $btn.closest("li").remove();
                AGN.Lib.Form.get($btn).updateHtml(resp);
            });
        });
    });
    function getRecentMailingId(btn) {
        return $(btn.el).parent().data("mailing-id");
    }
    function performRecentMailingBtnAction(btn, actionUrl) {
        btn.event.preventDefault();
        const mailingId = getRecentMailingId(btn);
        AGN.Lib.Page.reload(AGN.url(actionUrl.replace("{mailing-id}", mailingId)));
    }
});

(function(f) {
    if (typeof exports === "object" && typeof module !== "undefined") {
        module.exports = f();
    } else if (typeof define === "function" && define.amd) {
        define([], f);
    } else {
        var g;
        if (typeof window !== "undefined") {
            g = window;
        } else if (typeof global !== "undefined") {
            g = global;
        } else if (typeof self !== "undefined") {
            g = self;
        } else {
            g = this;
        }
        g.interact = f();
    }
})(function() {
    var define, module, exports;
    return function e(t, n, r) {
        function s(o, u) {
            if (!n[o]) {
                if (!t[o]) {
                    var a = typeof require == "function" && require;
                    if (!u && a) return a(o, !0);
                    if (i) return i(o, !0);
                    var f = new Error("Cannot find module '" + o + "'");
                    throw f.code = "MODULE_NOT_FOUND", f;
                }
                var l = n[o] = {
                    exports: {}
                };
                t[o][0].call(l.exports, function(e) {
                    var n = t[o][1][e];
                    return s(n ? n : e);
                }, l, l.exports, e, t, n, r);
            }
            return n[o].exports;
        }
        var i = typeof require == "function" && require;
        for (var o = 0; o < r.length; o++) s(r[o]);
        return s;
    }({
        1: [ function(require, module, exports) {
            "use strict";
            if (typeof window === "undefined") {
                module.exports = function(window) {
                    require("./src/utils/window").init(window);
                    return require("./src/index");
                };
            } else {
                module.exports = require("./src/index");
            }
        }, {
            "./src/index": 19,
            "./src/utils/window": 52
        } ],
        2: [ function(require, module, exports) {
            "use strict";
            function _classCallCheck(instance, Constructor) {
                if (!(instance instanceof Constructor)) {
                    throw new TypeError("Cannot call a class as a function");
                }
            }
            var extend = require("./utils/extend.js");
            function fireUntilImmediateStopped(event, listeners) {
                for (var _i = 0; _i < listeners.length; _i++) {
                    var _ref;
                    _ref = listeners[_i];
                    var listener = _ref;
                    if (event.immediatePropagationStopped) {
                        break;
                    }
                    listener(event);
                }
            }
            var Eventable = function() {
                function Eventable(options) {
                    _classCallCheck(this, Eventable);
                    this.options = extend({}, options || {});
                }
                Eventable.prototype.fire = function fire(event) {
                    var listeners = void 0;
                    var onEvent = "on" + event.type;
                    var global = this.global;
                    if (listeners = this[event.type]) {
                        fireUntilImmediateStopped(event, listeners);
                    }
                    if (this[onEvent]) {
                        this[onEvent](event);
                    }
                    if (!event.propagationStopped && global && (listeners = global[event.type])) {
                        fireUntilImmediateStopped(event, listeners);
                    }
                };
                Eventable.prototype.on = function on(eventType, listener) {
                    if (this[eventType]) {
                        this[eventType].push(listener);
                    } else {
                        this[eventType] = [ listener ];
                    }
                };
                Eventable.prototype.off = function off(eventType, listener) {
                    var eventList = this[eventType];
                    var index = eventList ? eventList.indexOf(listener) : -1;
                    if (index !== -1) {
                        eventList.splice(index, 1);
                    }
                    if (eventList && eventList.length === 0 || !listener) {
                        this[eventType] = undefined;
                    }
                };
                return Eventable;
            }();
            module.exports = Eventable;
        }, {
            "./utils/extend.js": 41
        } ],
        3: [ function(require, module, exports) {
            "use strict";
            function _classCallCheck(instance, Constructor) {
                if (!(instance instanceof Constructor)) {
                    throw new TypeError("Cannot call a class as a function");
                }
            }
            var extend = require("./utils/extend");
            var getOriginXY = require("./utils/getOriginXY");
            var defaults = require("./defaultOptions");
            var signals = require("./utils/Signals").new();
            var InteractEvent = function() {
                function InteractEvent(interaction, event, action, phase, element, related) {
                    var preEnd = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : false;
                    _classCallCheck(this, InteractEvent);
                    var target = interaction.target;
                    var deltaSource = (target && target.options || defaults).deltaSource;
                    var origin = getOriginXY(target, element, action);
                    var starting = phase === "start";
                    var ending = phase === "end";
                    var coords = starting ? interaction.startCoords : interaction.curCoords;
                    var prevEvent = interaction.prevEvent;
                    element = element || interaction.element;
                    var page = extend({}, coords.page);
                    var client = extend({}, coords.client);
                    page.x -= origin.x;
                    page.y -= origin.y;
                    client.x -= origin.x;
                    client.y -= origin.y;
                    this.ctrlKey = event.ctrlKey;
                    this.altKey = event.altKey;
                    this.shiftKey = event.shiftKey;
                    this.metaKey = event.metaKey;
                    this.button = event.button;
                    this.buttons = event.buttons;
                    this.target = element;
                    this.currentTarget = element;
                    this.relatedTarget = related || null;
                    this.preEnd = preEnd;
                    this.type = action + (phase || "");
                    this.interaction = interaction;
                    this.interactable = target;
                    this.t0 = starting ? interaction.downTimes[interaction.downTimes.length - 1] : prevEvent.t0;
                    var signalArg = {
                        interaction: interaction,
                        event: event,
                        action: action,
                        phase: phase,
                        element: element,
                        related: related,
                        page: page,
                        client: client,
                        coords: coords,
                        starting: starting,
                        ending: ending,
                        deltaSource: deltaSource,
                        iEvent: this
                    };
                    signals.fire("set-xy", signalArg);
                    if (ending) {
                        this.pageX = prevEvent.pageX;
                        this.pageY = prevEvent.pageY;
                        this.clientX = prevEvent.clientX;
                        this.clientY = prevEvent.clientY;
                    } else {
                        this.pageX = page.x;
                        this.pageY = page.y;
                        this.clientX = client.x;
                        this.clientY = client.y;
                    }
                    this.x0 = interaction.startCoords.page.x - origin.x;
                    this.y0 = interaction.startCoords.page.y - origin.y;
                    this.clientX0 = interaction.startCoords.client.x - origin.x;
                    this.clientY0 = interaction.startCoords.client.y - origin.y;
                    signals.fire("set-delta", signalArg);
                    this.timeStamp = coords.timeStamp;
                    this.dt = interaction.pointerDelta.timeStamp;
                    this.duration = this.timeStamp - this.t0;
                    this.speed = interaction.pointerDelta[deltaSource].speed;
                    this.velocityX = interaction.pointerDelta[deltaSource].vx;
                    this.velocityY = interaction.pointerDelta[deltaSource].vy;
                    this.swipe = ending || phase === "inertiastart" ? this.getSwipe() : null;
                    signals.fire("new", signalArg);
                }
                InteractEvent.prototype.getSwipe = function getSwipe() {
                    var interaction = this.interaction;
                    if (interaction.prevEvent.speed < 600 || this.timeStamp - interaction.prevEvent.timeStamp > 150) {
                        return null;
                    }
                    var angle = 180 * Math.atan2(interaction.prevEvent.velocityY, interaction.prevEvent.velocityX) / Math.PI;
                    var overlap = 22.5;
                    if (angle < 0) {
                        angle += 360;
                    }
                    var left = 135 - overlap <= angle && angle < 225 + overlap;
                    var up = 225 - overlap <= angle && angle < 315 + overlap;
                    var right = !left && (315 - overlap <= angle || angle < 45 + overlap);
                    var down = !up && 45 - overlap <= angle && angle < 135 + overlap;
                    return {
                        up: up,
                        down: down,
                        left: left,
                        right: right,
                        angle: angle,
                        speed: interaction.prevEvent.speed,
                        velocity: {
                            x: interaction.prevEvent.velocityX,
                            y: interaction.prevEvent.velocityY
                        }
                    };
                };
                InteractEvent.prototype.preventDefault = function preventDefault() {};
                InteractEvent.prototype.stopImmediatePropagation = function stopImmediatePropagation() {
                    this.immediatePropagationStopped = this.propagationStopped = true;
                };
                InteractEvent.prototype.stopPropagation = function stopPropagation() {
                    this.propagationStopped = true;
                };
                return InteractEvent;
            }();
            signals.on("set-delta", function(_ref) {
                var iEvent = _ref.iEvent, interaction = _ref.interaction, starting = _ref.starting, deltaSource = _ref.deltaSource;
                var prevEvent = starting ? iEvent : interaction.prevEvent;
                if (deltaSource === "client") {
                    iEvent.dx = iEvent.clientX - prevEvent.clientX;
                    iEvent.dy = iEvent.clientY - prevEvent.clientY;
                } else {
                    iEvent.dx = iEvent.pageX - prevEvent.pageX;
                    iEvent.dy = iEvent.pageY - prevEvent.pageY;
                }
            });
            InteractEvent.signals = signals;
            module.exports = InteractEvent;
        }, {
            "./defaultOptions": 18,
            "./utils/Signals": 34,
            "./utils/extend": 41,
            "./utils/getOriginXY": 42
        } ],
        4: [ function(require, module, exports) {
            "use strict";
            function _classCallCheck(instance, Constructor) {
                if (!(instance instanceof Constructor)) {
                    throw new TypeError("Cannot call a class as a function");
                }
            }
            var clone = require("./utils/clone");
            var is = require("./utils/is");
            var events = require("./utils/events");
            var extend = require("./utils/extend");
            var actions = require("./actions/base");
            var scope = require("./scope");
            var Eventable = require("./Eventable");
            var defaults = require("./defaultOptions");
            var signals = require("./utils/Signals").new();
            var _require = require("./utils/domUtils"), getElementRect = _require.getElementRect, nodeContains = _require.nodeContains, trySelector = _require.trySelector, matchesSelector = _require.matchesSelector;
            var _require2 = require("./utils/window"), getWindow = _require2.getWindow;
            var _require3 = require("./utils/arr"), contains = _require3.contains;
            var _require4 = require("./utils/browser"), wheelEvent = _require4.wheelEvent;
            scope.interactables = [];
            var Interactable = function() {
                function Interactable(target, options) {
                    _classCallCheck(this, Interactable);
                    options = options || {};
                    this.target = target;
                    this.events = new Eventable();
                    this._context = options.context || scope.document;
                    this._win = getWindow(trySelector(target) ? this._context : target);
                    this._doc = this._win.document;
                    signals.fire("new", {
                        target: target,
                        options: options,
                        interactable: this,
                        win: this._win
                    });
                    scope.addDocument(this._doc, this._win);
                    scope.interactables.push(this);
                    this.set(options);
                }
                Interactable.prototype.setOnEvents = function setOnEvents(action, phases) {
                    var onAction = "on" + action;
                    if (is.function(phases.onstart)) {
                        this.events[onAction + "start"] = phases.onstart;
                    }
                    if (is.function(phases.onmove)) {
                        this.events[onAction + "move"] = phases.onmove;
                    }
                    if (is.function(phases.onend)) {
                        this.events[onAction + "end"] = phases.onend;
                    }
                    if (is.function(phases.oninertiastart)) {
                        this.events[onAction + "inertiastart"] = phases.oninertiastart;
                    }
                    return this;
                };
                Interactable.prototype.setPerAction = function setPerAction(action, options) {
                    for (var option in options) {
                        if (option in defaults[action]) {
                            if (is.object(options[option])) {
                                this.options[action][option] = clone(this.options[action][option] || {});
                                extend(this.options[action][option], options[option]);
                                if (is.object(defaults.perAction[option]) && "enabled" in defaults.perAction[option]) {
                                    this.options[action][option].enabled = options[option].enabled === false ? false : true;
                                }
                            } else if (is.bool(options[option]) && is.object(defaults.perAction[option])) {
                                this.options[action][option].enabled = options[option];
                            } else if (options[option] !== undefined) {
                                this.options[action][option] = options[option];
                            }
                        }
                    }
                };
                Interactable.prototype.getRect = function getRect(element) {
                    element = element || this.target;
                    if (is.string(this.target) && !is.element(element)) {
                        element = this._context.querySelector(this.target);
                    }
                    return getElementRect(element);
                };
                Interactable.prototype.rectChecker = function rectChecker(checker) {
                    if (is.function(checker)) {
                        this.getRect = checker;
                        return this;
                    }
                    if (checker === null) {
                        delete this.options.getRect;
                        return this;
                    }
                    return this.getRect;
                };
                Interactable.prototype._backCompatOption = function _backCompatOption(optionName, newValue) {
                    if (trySelector(newValue) || is.object(newValue)) {
                        this.options[optionName] = newValue;
                        for (var _i = 0; _i < actions.names.length; _i++) {
                            var _ref;
                            _ref = actions.names[_i];
                            var action = _ref;
                            this.options[action][optionName] = newValue;
                        }
                        return this;
                    }
                    return this.options[optionName];
                };
                Interactable.prototype.origin = function origin(newValue) {
                    return this._backCompatOption("origin", newValue);
                };
                Interactable.prototype.deltaSource = function deltaSource(newValue) {
                    if (newValue === "page" || newValue === "client") {
                        this.options.deltaSource = newValue;
                        return this;
                    }
                    return this.options.deltaSource;
                };
                Interactable.prototype.context = function context() {
                    return this._context;
                };
                Interactable.prototype.inContext = function inContext(element) {
                    return this._context === element.ownerDocument || nodeContains(this._context, element);
                };
                Interactable.prototype.fire = function fire(iEvent) {
                    this.events.fire(iEvent);
                    return this;
                };
                Interactable.prototype._onOffMultiple = function _onOffMultiple(method, eventType, listener, options) {
                    if (is.string(eventType) && eventType.search(" ") !== -1) {
                        eventType = eventType.trim().split(/ +/);
                    }
                    if (is.array(eventType)) {
                        for (var _i2 = 0; _i2 < eventType.length; _i2++) {
                            var _ref2;
                            _ref2 = eventType[_i2];
                            var type = _ref2;
                            this[method](type, listener, options);
                        }
                        return true;
                    }
                    if (is.object(eventType)) {
                        for (var prop in eventType) {
                            this[method](prop, eventType[prop], listener);
                        }
                        return true;
                    }
                };
                Interactable.prototype.on = function on(eventType, listener, options) {
                    if (this._onOffMultiple("on", eventType, listener, options)) {
                        return this;
                    }
                    if (eventType === "wheel") {
                        eventType = wheelEvent;
                    }
                    if (contains(Interactable.eventTypes, eventType)) {
                        this.events.on(eventType, listener);
                    } else if (is.string(this.target)) {
                        events.addDelegate(this.target, this._context, eventType, listener, options);
                    } else {
                        events.add(this.target, eventType, listener, options);
                    }
                    return this;
                };
                Interactable.prototype.off = function off(eventType, listener, options) {
                    if (this._onOffMultiple("off", eventType, listener, options)) {
                        return this;
                    }
                    if (eventType === "wheel") {
                        eventType = wheelEvent;
                    }
                    if (contains(Interactable.eventTypes, eventType)) {
                        this.events.off(eventType, listener);
                    } else if (is.string(this.target)) {
                        events.removeDelegate(this.target, this._context, eventType, listener, options);
                    } else {
                        events.remove(this.target, eventType, listener, options);
                    }
                    return this;
                };
                Interactable.prototype.set = function set(options) {
                    if (!is.object(options)) {
                        options = {};
                    }
                    this.options = clone(defaults.base);
                    var perActions = clone(defaults.perAction);
                    for (var actionName in actions.methodDict) {
                        var methodName = actions.methodDict[actionName];
                        this.options[actionName] = clone(defaults[actionName]);
                        this.setPerAction(actionName, perActions);
                        this[methodName](options[actionName]);
                    }
                    for (var _i3 = 0; _i3 < Interactable.settingsMethods.length; _i3++) {
                        var _ref3;
                        _ref3 = Interactable.settingsMethods[_i3];
                        var setting = _ref3;
                        this.options[setting] = defaults.base[setting];
                        if (setting in options) {
                            this[setting](options[setting]);
                        }
                    }
                    signals.fire("set", {
                        options: options,
                        interactable: this
                    });
                    return this;
                };
                Interactable.prototype.unset = function unset() {
                    events.remove(this.target, "all");
                    if (is.string(this.target)) {
                        for (var type in events.delegatedEvents) {
                            var delegated = events.delegatedEvents[type];
                            if (delegated.selectors[0] === this.target && delegated.contexts[0] === this._context) {
                                delegated.selectors.splice(0, 1);
                                delegated.contexts.splice(0, 1);
                                delegated.listeners.splice(0, 1);
                                if (!delegated.selectors.length) {
                                    delegated[type] = null;
                                }
                            }
                            events.remove(this._context, type, events.delegateListener);
                            events.remove(this._context, type, events.delegateUseCapture, true);
                        }
                    } else {
                        events.remove(this, "all");
                    }
                    signals.fire("unset", {
                        interactable: this
                    });
                    scope.interactables.splice(scope.interactables.indexOf(this), 1);
                    for (var _i4 = 0; _i4 < (scope.interactions || []).length; _i4++) {
                        var _ref4;
                        _ref4 = (scope.interactions || [])[_i4];
                        var interaction = _ref4;
                        if (interaction.target === this && interaction.interacting() && !interaction._ending) {
                            interaction.stop();
                        }
                    }
                    return scope.interact;
                };
                return Interactable;
            }();
            scope.interactables.indexOfElement = function indexOfElement(target, context) {
                context = context || scope.document;
                for (var i = 0; i < this.length; i++) {
                    var interactable = this[i];
                    if (interactable.target === target && interactable._context === context) {
                        return i;
                    }
                }
                return -1;
            };
            scope.interactables.get = function interactableGet(element, options, dontCheckInContext) {
                var ret = this[this.indexOfElement(element, options && options.context)];
                return ret && (is.string(element) || dontCheckInContext || ret.inContext(element)) ? ret : null;
            };
            scope.interactables.forEachMatch = function(element, callback) {
                for (var _i5 = 0; _i5 < this.length; _i5++) {
                    var _ref5;
                    _ref5 = this[_i5];
                    var interactable = _ref5;
                    var ret = void 0;
                    if ((is.string(interactable.target) ? is.element(element) && matchesSelector(element, interactable.target) : element === interactable.target) && interactable.inContext(element)) {
                        ret = callback(interactable);
                    }
                    if (ret !== undefined) {
                        return ret;
                    }
                }
            };
            Interactable.eventTypes = scope.eventTypes = [];
            Interactable.signals = signals;
            Interactable.settingsMethods = [ "deltaSource", "origin", "preventDefault", "rectChecker" ];
            module.exports = Interactable;
        }, {
            "./Eventable": 2,
            "./actions/base": 6,
            "./defaultOptions": 18,
            "./scope": 33,
            "./utils/Signals": 34,
            "./utils/arr": 35,
            "./utils/browser": 36,
            "./utils/clone": 37,
            "./utils/domUtils": 39,
            "./utils/events": 40,
            "./utils/extend": 41,
            "./utils/is": 46,
            "./utils/window": 52
        } ],
        5: [ function(require, module, exports) {
            "use strict";
            function _classCallCheck(instance, Constructor) {
                if (!(instance instanceof Constructor)) {
                    throw new TypeError("Cannot call a class as a function");
                }
            }
            var scope = require("./scope");
            var utils = require("./utils");
            var events = require("./utils/events");
            var browser = require("./utils/browser");
            var domObjects = require("./utils/domObjects");
            var finder = require("./utils/interactionFinder");
            var signals = require("./utils/Signals").new();
            var listeners = {};
            var methodNames = [ "pointerDown", "pointerMove", "pointerUp", "updatePointer", "removePointer" ];
            var prevTouchTime = 0;
            scope.interactions = [];
            var Interaction = function() {
                function Interaction(_ref) {
                    var pointerType = _ref.pointerType;
                    _classCallCheck(this, Interaction);
                    this.target = null;
                    this.element = null;
                    this.prepared = {
                        name: null,
                        axis: null,
                        edges: null
                    };
                    this.pointers = [];
                    this.pointerIds = [];
                    this.downTargets = [];
                    this.downTimes = [];
                    this.prevCoords = {
                        page: {
                            x: 0,
                            y: 0
                        },
                        client: {
                            x: 0,
                            y: 0
                        },
                        timeStamp: 0
                    };
                    this.curCoords = {
                        page: {
                            x: 0,
                            y: 0
                        },
                        client: {
                            x: 0,
                            y: 0
                        },
                        timeStamp: 0
                    };
                    this.startCoords = {
                        page: {
                            x: 0,
                            y: 0
                        },
                        client: {
                            x: 0,
                            y: 0
                        },
                        timeStamp: 0
                    };
                    this.pointerDelta = {
                        page: {
                            x: 0,
                            y: 0,
                            vx: 0,
                            vy: 0,
                            speed: 0
                        },
                        client: {
                            x: 0,
                            y: 0,
                            vx: 0,
                            vy: 0,
                            speed: 0
                        },
                        timeStamp: 0
                    };
                    this.downEvent = null;
                    this.downPointer = {};
                    this._eventTarget = null;
                    this._curEventTarget = null;
                    this.prevEvent = null;
                    this.pointerIsDown = false;
                    this.pointerWasMoved = false;
                    this._interacting = false;
                    this._ending = false;
                    this.pointerType = pointerType;
                    signals.fire("new", this);
                    scope.interactions.push(this);
                }
                Interaction.prototype.pointerDown = function pointerDown(pointer, event, eventTarget) {
                    var pointerIndex = this.updatePointer(pointer, event, true);
                    signals.fire("down", {
                        pointer: pointer,
                        event: event,
                        eventTarget: eventTarget,
                        pointerIndex: pointerIndex,
                        interaction: this
                    });
                };
                Interaction.prototype.start = function start(action, target, element) {
                    if (this.interacting() || !this.pointerIsDown || this.pointerIds.length < (action.name === "gesture" ? 2 : 1)) {
                        return;
                    }
                    if (scope.interactions.indexOf(this) === -1) {
                        scope.interactions.push(this);
                    }
                    utils.copyAction(this.prepared, action);
                    this.target = target;
                    this.element = element;
                    signals.fire("action-start", {
                        interaction: this,
                        event: this.downEvent
                    });
                };
                Interaction.prototype.pointerMove = function pointerMove(pointer, event, eventTarget) {
                    if (!this.simulation) {
                        this.updatePointer(pointer);
                        utils.setCoords(this.curCoords, this.pointers);
                    }
                    var duplicateMove = this.curCoords.page.x === this.prevCoords.page.x && this.curCoords.page.y === this.prevCoords.page.y && this.curCoords.client.x === this.prevCoords.client.x && this.curCoords.client.y === this.prevCoords.client.y;
                    var dx = void 0;
                    var dy = void 0;
                    if (this.pointerIsDown && !this.pointerWasMoved) {
                        dx = this.curCoords.client.x - this.startCoords.client.x;
                        dy = this.curCoords.client.y - this.startCoords.client.y;
                        this.pointerWasMoved = utils.hypot(dx, dy) > Interaction.pointerMoveTolerance;
                    }
                    var signalArg = {
                        pointer: pointer,
                        pointerIndex: this.getPointerIndex(pointer),
                        event: event,
                        eventTarget: eventTarget,
                        dx: dx,
                        dy: dy,
                        duplicate: duplicateMove,
                        interaction: this,
                        interactingBeforeMove: this.interacting()
                    };
                    if (!duplicateMove) {
                        utils.setCoordDeltas(this.pointerDelta, this.prevCoords, this.curCoords);
                    }
                    signals.fire("move", signalArg);
                    if (!duplicateMove) {
                        if (this.interacting()) {
                            this.doMove(signalArg);
                        }
                        if (this.pointerWasMoved) {
                            utils.copyCoords(this.prevCoords, this.curCoords);
                        }
                    }
                };
                Interaction.prototype.doMove = function doMove(signalArg) {
                    signalArg = utils.extend({
                        pointer: this.pointers[0],
                        event: this.prevEvent,
                        eventTarget: this._eventTarget,
                        interaction: this
                    }, signalArg || {});
                    signals.fire("before-action-move", signalArg);
                    if (!this._dontFireMove) {
                        signals.fire("action-move", signalArg);
                    }
                    this._dontFireMove = false;
                };
                Interaction.prototype.pointerUp = function pointerUp(pointer, event, eventTarget, curEventTarget) {
                    var pointerIndex = this.getPointerIndex(pointer);
                    signals.fire(/cancel$/i.test(event.type) ? "cancel" : "up", {
                        pointer: pointer,
                        pointerIndex: pointerIndex,
                        event: event,
                        eventTarget: eventTarget,
                        curEventTarget: curEventTarget,
                        interaction: this
                    });
                    if (!this.simulation) {
                        this.end(event);
                    }
                    this.pointerIsDown = false;
                    this.removePointer(pointer, event);
                };
                Interaction.prototype.end = function end(event) {
                    this._ending = true;
                    event = event || this.prevEvent;
                    if (this.interacting()) {
                        signals.fire("action-end", {
                            event: event,
                            interaction: this
                        });
                    }
                    this.stop();
                    this._ending = false;
                };
                Interaction.prototype.currentAction = function currentAction() {
                    return this._interacting ? this.prepared.name : null;
                };
                Interaction.prototype.interacting = function interacting() {
                    return this._interacting;
                };
                Interaction.prototype.stop = function stop() {
                    signals.fire("stop", {
                        interaction: this
                    });
                    if (this._interacting) {
                        signals.fire("stop-active", {
                            interaction: this
                        });
                        signals.fire("stop-" + this.prepared.name, {
                            interaction: this
                        });
                    }
                    this.target = this.element = null;
                    this._interacting = false;
                    this.prepared.name = this.prevEvent = null;
                };
                Interaction.prototype.getPointerIndex = function getPointerIndex(pointer) {
                    if (this.pointerType === "mouse" || this.pointerType === "pen") {
                        return 0;
                    }
                    return this.pointerIds.indexOf(utils.getPointerId(pointer));
                };
                Interaction.prototype.updatePointer = function updatePointer(pointer, event) {
                    var down = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : event && /(down|start)$/i.test(event.type);
                    var id = utils.getPointerId(pointer);
                    var index = this.getPointerIndex(pointer);
                    if (index === -1) {
                        index = this.pointerIds.length;
                        this.pointerIds[index] = id;
                    }
                    if (down) {
                        signals.fire("update-pointer-down", {
                            pointer: pointer,
                            event: event,
                            down: down,
                            pointerId: id,
                            pointerIndex: index,
                            interaction: this
                        });
                    }
                    this.pointers[index] = pointer;
                    return index;
                };
                Interaction.prototype.removePointer = function removePointer(pointer, event) {
                    var index = this.getPointerIndex(pointer);
                    if (index === -1) {
                        return;
                    }
                    signals.fire("remove-pointer", {
                        pointer: pointer,
                        event: event,
                        pointerIndex: index,
                        interaction: this
                    });
                    this.pointers.splice(index, 1);
                    this.pointerIds.splice(index, 1);
                    this.downTargets.splice(index, 1);
                    this.downTimes.splice(index, 1);
                };
                Interaction.prototype._updateEventTargets = function _updateEventTargets(target, currentTarget) {
                    this._eventTarget = target;
                    this._curEventTarget = currentTarget;
                };
                return Interaction;
            }();
            for (var _i = 0; _i < methodNames.length; _i++) {
                var method = methodNames[_i];
                listeners[method] = doOnInteractions(method);
            }
            function doOnInteractions(method) {
                return function(event) {
                    var pointerType = utils.getPointerType(event);
                    var _utils$getEventTarget = utils.getEventTargets(event), eventTarget = _utils$getEventTarget[0], curEventTarget = _utils$getEventTarget[1];
                    var matches = [];
                    if (browser.supportsTouch && /touch/.test(event.type)) {
                        prevTouchTime = new Date().getTime();
                        for (var _i2 = 0; _i2 < event.changedTouches.length; _i2++) {
                            var _ref2;
                            _ref2 = event.changedTouches[_i2];
                            var changedTouch = _ref2;
                            var pointer = changedTouch;
                            var interaction = finder.search(pointer, event.type, eventTarget);
                            matches.push([ pointer, interaction || new Interaction({
                                pointerType: pointerType
                            }) ]);
                        }
                    } else {
                        var invalidPointer = false;
                        if (!browser.supportsPointerEvent && /mouse/.test(event.type)) {
                            for (var i = 0; i < scope.interactions.length && !invalidPointer; i++) {
                                invalidPointer = scope.interactions[i].pointerType !== "mouse" && scope.interactions[i].pointerIsDown;
                            }
                            invalidPointer = invalidPointer || new Date().getTime() - prevTouchTime < 500 || event.timeStamp === 0;
                        }
                        if (!invalidPointer) {
                            var _interaction = finder.search(event, event.type, eventTarget);
                            if (!_interaction) {
                                _interaction = new Interaction({
                                    pointerType: pointerType
                                });
                            }
                            matches.push([ event, _interaction ]);
                        }
                    }
                    for (var _i3 = 0; _i3 < matches.length; _i3++) {
                        var _ref3 = matches[_i3];
                        var _pointer = _ref3[0];
                        var _interaction2 = _ref3[1];
                        _interaction2._updateEventTargets(eventTarget, curEventTarget);
                        _interaction2[method](_pointer, event, eventTarget, curEventTarget);
                    }
                };
            }
            function endAll(event) {
                for (var _i4 = 0; _i4 < scope.interactions.length; _i4++) {
                    var _ref4;
                    _ref4 = scope.interactions[_i4];
                    var interaction = _ref4;
                    interaction.end(event);
                    signals.fire("endall", {
                        event: event,
                        interaction: interaction
                    });
                }
            }
            var docEvents = {};
            var pEventTypes = browser.pEventTypes;
            if (domObjects.PointerEvent) {
                docEvents[pEventTypes.down] = listeners.pointerDown;
                docEvents[pEventTypes.move] = listeners.pointerMove;
                docEvents[pEventTypes.up] = listeners.pointerUp;
                docEvents[pEventTypes.cancel] = listeners.pointerUp;
            } else {
                docEvents.mousedown = listeners.pointerDown;
                docEvents.mousemove = listeners.pointerMove;
                docEvents.mouseup = listeners.pointerUp;
                docEvents.touchstart = listeners.pointerDown;
                docEvents.touchmove = listeners.pointerMove;
                docEvents.touchend = listeners.pointerUp;
                docEvents.touchcancel = listeners.pointerUp;
            }
            docEvents.blur = endAll;
            function onDocSignal(_ref5, signalName) {
                var doc = _ref5.doc;
                var eventMethod = signalName.indexOf("add") === 0 ? events.add : events.remove;
                for (var eventType in scope.delegatedEvents) {
                    eventMethod(doc, eventType, events.delegateListener);
                    eventMethod(doc, eventType, events.delegateUseCapture, true);
                }
                for (var _eventType in docEvents) {
                    eventMethod(doc, _eventType, docEvents[_eventType], browser.isIOS ? {
                        passive: false
                    } : undefined);
                }
            }
            signals.on("update-pointer-down", function(_ref6) {
                var interaction = _ref6.interaction, pointer = _ref6.pointer, pointerId = _ref6.pointerId, pointerIndex = _ref6.pointerIndex, event = _ref6.event, eventTarget = _ref6.eventTarget, down = _ref6.down;
                interaction.pointerIds[pointerIndex] = pointerId;
                interaction.pointers[pointerIndex] = pointer;
                if (down) {
                    interaction.pointerIsDown = true;
                }
                if (!interaction.interacting()) {
                    utils.setCoords(interaction.startCoords, interaction.pointers);
                    utils.copyCoords(interaction.curCoords, interaction.startCoords);
                    utils.copyCoords(interaction.prevCoords, interaction.startCoords);
                    interaction.downEvent = event;
                    interaction.downTimes[pointerIndex] = interaction.curCoords.timeStamp;
                    interaction.downTargets[pointerIndex] = eventTarget || event && utils.getEventTargets(event)[0];
                    interaction.pointerWasMoved = false;
                    utils.pointerExtend(interaction.downPointer, pointer);
                }
            });
            scope.signals.on("add-document", onDocSignal);
            scope.signals.on("remove-document", onDocSignal);
            Interaction.pointerMoveTolerance = 1;
            Interaction.doOnInteractions = doOnInteractions;
            Interaction.endAll = endAll;
            Interaction.signals = signals;
            Interaction.docEvents = docEvents;
            scope.endAllInteractions = endAll;
            module.exports = Interaction;
        }, {
            "./scope": 33,
            "./utils": 44,
            "./utils/Signals": 34,
            "./utils/browser": 36,
            "./utils/domObjects": 38,
            "./utils/events": 40,
            "./utils/interactionFinder": 45
        } ],
        6: [ function(require, module, exports) {
            "use strict";
            var Interaction = require("../Interaction");
            var InteractEvent = require("../InteractEvent");
            var actions = {
                firePrepared: firePrepared,
                names: [],
                methodDict: {}
            };
            Interaction.signals.on("action-start", function(_ref) {
                var interaction = _ref.interaction, event = _ref.event;
                interaction._interacting = true;
                firePrepared(interaction, event, "start");
            });
            Interaction.signals.on("action-move", function(_ref2) {
                var interaction = _ref2.interaction, event = _ref2.event, preEnd = _ref2.preEnd;
                firePrepared(interaction, event, "move", preEnd);
                if (!interaction.interacting()) {
                    return false;
                }
            });
            Interaction.signals.on("action-end", function(_ref3) {
                var interaction = _ref3.interaction, event = _ref3.event;
                firePrepared(interaction, event, "end");
            });
            function firePrepared(interaction, event, phase, preEnd) {
                var actionName = interaction.prepared.name;
                var newEvent = new InteractEvent(interaction, event, actionName, phase, interaction.element, null, preEnd);
                interaction.target.fire(newEvent);
                interaction.prevEvent = newEvent;
            }
            module.exports = actions;
        }, {
            "../InteractEvent": 3,
            "../Interaction": 5
        } ],
        7: [ function(require, module, exports) {
            "use strict";
            var actions = require("./base");
            var utils = require("../utils");
            var InteractEvent = require("../InteractEvent");
            var Interactable = require("../Interactable");
            var Interaction = require("../Interaction");
            var defaultOptions = require("../defaultOptions");
            var drag = {
                defaults: {
                    enabled: false,
                    mouseButtons: null,
                    origin: null,
                    snap: null,
                    restrict: null,
                    inertia: null,
                    autoScroll: null,
                    startAxis: "xy",
                    lockAxis: "xy"
                },
                checker: function checker(pointer, event, interactable) {
                    var dragOptions = interactable.options.drag;
                    return dragOptions.enabled ? {
                        name: "drag",
                        axis: dragOptions.lockAxis === "start" ? dragOptions.startAxis : dragOptions.lockAxis
                    } : null;
                },
                getCursor: function getCursor() {
                    return "move";
                }
            };
            Interaction.signals.on("before-action-move", function(_ref) {
                var interaction = _ref.interaction;
                if (interaction.prepared.name !== "drag") {
                    return;
                }
                var axis = interaction.prepared.axis;
                if (axis === "x") {
                    interaction.curCoords.page.y = interaction.startCoords.page.y;
                    interaction.curCoords.client.y = interaction.startCoords.client.y;
                    interaction.pointerDelta.page.speed = Math.abs(interaction.pointerDelta.page.vx);
                    interaction.pointerDelta.client.speed = Math.abs(interaction.pointerDelta.client.vx);
                    interaction.pointerDelta.client.vy = 0;
                    interaction.pointerDelta.page.vy = 0;
                } else if (axis === "y") {
                    interaction.curCoords.page.x = interaction.startCoords.page.x;
                    interaction.curCoords.client.x = interaction.startCoords.client.x;
                    interaction.pointerDelta.page.speed = Math.abs(interaction.pointerDelta.page.vy);
                    interaction.pointerDelta.client.speed = Math.abs(interaction.pointerDelta.client.vy);
                    interaction.pointerDelta.client.vx = 0;
                    interaction.pointerDelta.page.vx = 0;
                }
            });
            InteractEvent.signals.on("new", function(_ref2) {
                var iEvent = _ref2.iEvent, interaction = _ref2.interaction;
                if (iEvent.type !== "dragmove") {
                    return;
                }
                var axis = interaction.prepared.axis;
                if (axis === "x") {
                    iEvent.pageY = interaction.startCoords.page.y;
                    iEvent.clientY = interaction.startCoords.client.y;
                    iEvent.dy = 0;
                } else if (axis === "y") {
                    iEvent.pageX = interaction.startCoords.page.x;
                    iEvent.clientX = interaction.startCoords.client.x;
                    iEvent.dx = 0;
                }
            });
            Interactable.prototype.draggable = function(options) {
                if (utils.is.object(options)) {
                    this.options.drag.enabled = options.enabled === false ? false : true;
                    this.setPerAction("drag", options);
                    this.setOnEvents("drag", options);
                    if (/^(xy|x|y|start)$/.test(options.lockAxis)) {
                        this.options.drag.lockAxis = options.lockAxis;
                    }
                    if (/^(xy|x|y)$/.test(options.startAxis)) {
                        this.options.drag.startAxis = options.startAxis;
                    }
                    return this;
                }
                if (utils.is.bool(options)) {
                    this.options.drag.enabled = options;
                    if (!options) {
                        this.ondragstart = this.ondragstart = this.ondragend = null;
                    }
                    return this;
                }
                return this.options.drag;
            };
            actions.drag = drag;
            actions.names.push("drag");
            utils.merge(Interactable.eventTypes, [ "dragstart", "dragmove", "draginertiastart", "draginertiaresume", "dragend" ]);
            actions.methodDict.drag = "draggable";
            defaultOptions.drag = drag.defaults;
            module.exports = drag;
        }, {
            "../InteractEvent": 3,
            "../Interactable": 4,
            "../Interaction": 5,
            "../defaultOptions": 18,
            "../utils": 44,
            "./base": 6
        } ],
        8: [ function(require, module, exports) {
            "use strict";
            var actions = require("./base");
            var utils = require("../utils");
            var scope = require("../scope");
            var interact = require("../interact");
            var InteractEvent = require("../InteractEvent");
            var Interactable = require("../Interactable");
            var Interaction = require("../Interaction");
            var defaultOptions = require("../defaultOptions");
            var drop = {
                defaults: {
                    enabled: false,
                    accept: null,
                    overlap: "pointer"
                }
            };
            var dynamicDrop = false;
            Interaction.signals.on("action-start", function(_ref) {
                var interaction = _ref.interaction, event = _ref.event;
                if (interaction.prepared.name !== "drag") {
                    return;
                }
                interaction.activeDrops.dropzones = [];
                interaction.activeDrops.elements = [];
                interaction.activeDrops.rects = [];
                interaction.dropEvents = null;
                if (!interaction.dynamicDrop) {
                    setActiveDrops(interaction.activeDrops, interaction.element);
                }
                var dragEvent = interaction.prevEvent;
                var dropEvents = getDropEvents(interaction, event, dragEvent);
                if (dropEvents.activate) {
                    fireActiveDrops(interaction.activeDrops, dropEvents.activate);
                }
            });
            InteractEvent.signals.on("new", function(_ref2) {
                var interaction = _ref2.interaction, iEvent = _ref2.iEvent, event = _ref2.event;
                if (iEvent.type !== "dragmove" && iEvent.type !== "dragend") {
                    return;
                }
                var draggableElement = interaction.element;
                var dragEvent = iEvent;
                var dropResult = getDrop(dragEvent, event, draggableElement);
                interaction.dropTarget = dropResult.dropzone;
                interaction.dropElement = dropResult.element;
                interaction.dropEvents = getDropEvents(interaction, event, dragEvent);
            });
            Interaction.signals.on("action-move", function(_ref3) {
                var interaction = _ref3.interaction;
                if (interaction.prepared.name !== "drag") {
                    return;
                }
                fireDropEvents(interaction, interaction.dropEvents);
            });
            Interaction.signals.on("action-end", function(_ref4) {
                var interaction = _ref4.interaction;
                if (interaction.prepared.name === "drag") {
                    fireDropEvents(interaction, interaction.dropEvents);
                }
            });
            Interaction.signals.on("stop-drag", function(_ref5) {
                var interaction = _ref5.interaction;
                interaction.activeDrops = {
                    dropzones: null,
                    elements: null,
                    rects: null
                };
                interaction.dropEvents = null;
            });
            function collectDrops(activeDrops, element) {
                var drops = [];
                var elements = [];
                for (var _i = 0; _i < scope.interactables.length; _i++) {
                    var _ref6;
                    _ref6 = scope.interactables[_i];
                    var current = _ref6;
                    if (!current.options.drop.enabled) {
                        continue;
                    }
                    var accept = current.options.drop.accept;
                    if (utils.is.element(accept) && accept !== element || utils.is.string(accept) && !utils.matchesSelector(element, accept)) {
                        continue;
                    }
                    var dropElements = utils.is.string(current.target) ? current._context.querySelectorAll(current.target) : [ current.target ];
                    for (var _i2 = 0; _i2 < dropElements.length; _i2++) {
                        var _ref7;
                        _ref7 = dropElements[_i2];
                        var currentElement = _ref7;
                        if (currentElement !== element) {
                            drops.push(current);
                            elements.push(currentElement);
                        }
                    }
                }
                return {
                    elements: elements,
                    dropzones: drops
                };
            }
            function fireActiveDrops(activeDrops, event) {
                var prevElement = void 0;
                for (var i = 0; i < activeDrops.dropzones.length; i++) {
                    var current = activeDrops.dropzones[i];
                    var currentElement = activeDrops.elements[i];
                    if (currentElement !== prevElement) {
                        event.target = currentElement;
                        current.fire(event);
                    }
                    prevElement = currentElement;
                }
            }
            function setActiveDrops(activeDrops, dragElement) {
                var possibleDrops = collectDrops(activeDrops, dragElement);
                activeDrops.dropzones = possibleDrops.dropzones;
                activeDrops.elements = possibleDrops.elements;
                activeDrops.rects = [];
                for (var i = 0; i < activeDrops.dropzones.length; i++) {
                    activeDrops.rects[i] = activeDrops.dropzones[i].getRect(activeDrops.elements[i]);
                }
            }
            function getDrop(dragEvent, event, dragElement) {
                var interaction = dragEvent.interaction;
                var validDrops = [];
                if (dynamicDrop) {
                    setActiveDrops(interaction.activeDrops, dragElement);
                }
                for (var j = 0; j < interaction.activeDrops.dropzones.length; j++) {
                    var current = interaction.activeDrops.dropzones[j];
                    var currentElement = interaction.activeDrops.elements[j];
                    var rect = interaction.activeDrops.rects[j];
                    validDrops.push(current.dropCheck(dragEvent, event, interaction.target, dragElement, currentElement, rect) ? currentElement : null);
                }
                var dropIndex = utils.indexOfDeepestElement(validDrops);
                return {
                    dropzone: interaction.activeDrops.dropzones[dropIndex] || null,
                    element: interaction.activeDrops.elements[dropIndex] || null
                };
            }
            function getDropEvents(interaction, pointerEvent, dragEvent) {
                var dropEvents = {
                    enter: null,
                    leave: null,
                    activate: null,
                    deactivate: null,
                    move: null,
                    drop: null
                };
                var tmpl = {
                    dragEvent: dragEvent,
                    interaction: interaction,
                    target: interaction.dropElement,
                    dropzone: interaction.dropTarget,
                    relatedTarget: dragEvent.target,
                    draggable: dragEvent.interactable,
                    timeStamp: dragEvent.timeStamp
                };
                if (interaction.dropElement !== interaction.prevDropElement) {
                    if (interaction.prevDropTarget) {
                        dropEvents.leave = utils.extend({
                            type: "dragleave"
                        }, tmpl);
                        dragEvent.dragLeave = dropEvents.leave.target = interaction.prevDropElement;
                        dragEvent.prevDropzone = dropEvents.leave.dropzone = interaction.prevDropTarget;
                    }
                    if (interaction.dropTarget) {
                        dropEvents.enter = {
                            dragEvent: dragEvent,
                            interaction: interaction,
                            target: interaction.dropElement,
                            dropzone: interaction.dropTarget,
                            relatedTarget: dragEvent.target,
                            draggable: dragEvent.interactable,
                            timeStamp: dragEvent.timeStamp,
                            type: "dragenter"
                        };
                        dragEvent.dragEnter = interaction.dropElement;
                        dragEvent.dropzone = interaction.dropTarget;
                    }
                }
                if (dragEvent.type === "dragend" && interaction.dropTarget) {
                    dropEvents.drop = utils.extend({
                        type: "drop"
                    }, tmpl);
                    dragEvent.dropzone = interaction.dropTarget;
                    dragEvent.relatedTarget = interaction.dropElement;
                }
                if (dragEvent.type === "dragstart") {
                    dropEvents.activate = utils.extend({
                        type: "dropactivate"
                    }, tmpl);
                    dropEvents.activate.target = null;
                    dropEvents.activate.dropzone = null;
                }
                if (dragEvent.type === "dragend") {
                    dropEvents.deactivate = utils.extend({
                        type: "dropdeactivate"
                    }, tmpl);
                    dropEvents.deactivate.target = null;
                    dropEvents.deactivate.dropzone = null;
                }
                if (dragEvent.type === "dragmove" && interaction.dropTarget) {
                    dropEvents.move = utils.extend({
                        dragmove: dragEvent,
                        type: "dropmove"
                    }, tmpl);
                    dragEvent.dropzone = interaction.dropTarget;
                }
                return dropEvents;
            }
            function fireDropEvents(interaction, dropEvents) {
                var activeDrops = interaction.activeDrops, prevDropTarget = interaction.prevDropTarget, dropTarget = interaction.dropTarget, dropElement = interaction.dropElement;
                if (dropEvents.leave) {
                    prevDropTarget.fire(dropEvents.leave);
                }
                if (dropEvents.move) {
                    dropTarget.fire(dropEvents.move);
                }
                if (dropEvents.enter) {
                    dropTarget.fire(dropEvents.enter);
                }
                if (dropEvents.drop) {
                    dropTarget.fire(dropEvents.drop);
                }
                if (dropEvents.deactivate) {
                    fireActiveDrops(activeDrops, dropEvents.deactivate);
                }
                interaction.prevDropTarget = dropTarget;
                interaction.prevDropElement = dropElement;
            }
            Interactable.prototype.dropzone = function(options) {
                if (utils.is.object(options)) {
                    this.options.drop.enabled = options.enabled === false ? false : true;
                    if (utils.is.function(options.ondrop)) {
                        this.events.ondrop = options.ondrop;
                    }
                    if (utils.is.function(options.ondropactivate)) {
                        this.events.ondropactivate = options.ondropactivate;
                    }
                    if (utils.is.function(options.ondropdeactivate)) {
                        this.events.ondropdeactivate = options.ondropdeactivate;
                    }
                    if (utils.is.function(options.ondragenter)) {
                        this.events.ondragenter = options.ondragenter;
                    }
                    if (utils.is.function(options.ondragleave)) {
                        this.events.ondragleave = options.ondragleave;
                    }
                    if (utils.is.function(options.ondropmove)) {
                        this.events.ondropmove = options.ondropmove;
                    }
                    if (/^(pointer|center)$/.test(options.overlap)) {
                        this.options.drop.overlap = options.overlap;
                    } else if (utils.is.number(options.overlap)) {
                        this.options.drop.overlap = Math.max(Math.min(1, options.overlap), 0);
                    }
                    if ("accept" in options) {
                        this.options.drop.accept = options.accept;
                    }
                    if ("checker" in options) {
                        this.options.drop.checker = options.checker;
                    }
                    return this;
                }
                if (utils.is.bool(options)) {
                    this.options.drop.enabled = options;
                    if (!options) {
                        this.ondragenter = this.ondragleave = this.ondrop = this.ondropactivate = this.ondropdeactivate = null;
                    }
                    return this;
                }
                return this.options.drop;
            };
            Interactable.prototype.dropCheck = function(dragEvent, event, draggable, draggableElement, dropElement, rect) {
                var dropped = false;
                if (!(rect = rect || this.getRect(dropElement))) {
                    return this.options.drop.checker ? this.options.drop.checker(dragEvent, event, dropped, this, dropElement, draggable, draggableElement) : false;
                }
                var dropOverlap = this.options.drop.overlap;
                if (dropOverlap === "pointer") {
                    var origin = utils.getOriginXY(draggable, draggableElement, "drag");
                    var page = utils.getPageXY(dragEvent);
                    page.x += origin.x;
                    page.y += origin.y;
                    var horizontal = page.x > rect.left && page.x < rect.right;
                    var vertical = page.y > rect.top && page.y < rect.bottom;
                    dropped = horizontal && vertical;
                }
                var dragRect = draggable.getRect(draggableElement);
                if (dragRect && dropOverlap === "center") {
                    var cx = dragRect.left + dragRect.width / 2;
                    var cy = dragRect.top + dragRect.height / 2;
                    dropped = cx >= rect.left && cx <= rect.right && cy >= rect.top && cy <= rect.bottom;
                }
                if (dragRect && utils.is.number(dropOverlap)) {
                    var overlapArea = Math.max(0, Math.min(rect.right, dragRect.right) - Math.max(rect.left, dragRect.left)) * Math.max(0, Math.min(rect.bottom, dragRect.bottom) - Math.max(rect.top, dragRect.top));
                    var overlapRatio = overlapArea / (dragRect.width * dragRect.height);
                    dropped = overlapRatio >= dropOverlap;
                }
                if (this.options.drop.checker) {
                    dropped = this.options.drop.checker(dragEvent, event, dropped, this, dropElement, draggable, draggableElement);
                }
                return dropped;
            };
            Interactable.signals.on("unset", function(_ref8) {
                var interactable = _ref8.interactable;
                interactable.dropzone(false);
            });
            Interactable.settingsMethods.push("dropChecker");
            Interaction.signals.on("new", function(interaction) {
                interaction.dropTarget = null;
                interaction.dropElement = null;
                interaction.prevDropTarget = null;
                interaction.prevDropElement = null;
                interaction.dropEvents = null;
                interaction.activeDrops = {
                    dropzones: [],
                    elements: [],
                    rects: []
                };
            });
            Interaction.signals.on("stop", function(_ref9) {
                var interaction = _ref9.interaction;
                interaction.dropTarget = interaction.dropElement = interaction.prevDropTarget = interaction.prevDropElement = null;
            });
            interact.dynamicDrop = function(newValue) {
                if (utils.is.bool(newValue)) {
                    dynamicDrop = newValue;
                    return interact;
                }
                return dynamicDrop;
            };
            utils.merge(Interactable.eventTypes, [ "dragenter", "dragleave", "dropactivate", "dropdeactivate", "dropmove", "drop" ]);
            actions.methodDict.drop = "dropzone";
            defaultOptions.drop = drop.defaults;
            module.exports = drop;
        }, {
            "../InteractEvent": 3,
            "../Interactable": 4,
            "../Interaction": 5,
            "../defaultOptions": 18,
            "../interact": 21,
            "../scope": 33,
            "../utils": 44,
            "./base": 6
        } ],
        9: [ function(require, module, exports) {
            "use strict";
            var actions = require("./base");
            var utils = require("../utils");
            var InteractEvent = require("../InteractEvent");
            var Interactable = require("../Interactable");
            var Interaction = require("../Interaction");
            var defaultOptions = require("../defaultOptions");
            var gesture = {
                defaults: {
                    enabled: false,
                    origin: null,
                    restrict: null
                },
                checker: function checker(pointer, event, interactable, element, interaction) {
                    if (interaction.pointerIds.length >= 2) {
                        return {
                            name: "gesture"
                        };
                    }
                    return null;
                },
                getCursor: function getCursor() {
                    return "";
                }
            };
            InteractEvent.signals.on("new", function(_ref) {
                var iEvent = _ref.iEvent, interaction = _ref.interaction;
                if (iEvent.type !== "gesturestart") {
                    return;
                }
                iEvent.ds = 0;
                interaction.gesture.startDistance = interaction.gesture.prevDistance = iEvent.distance;
                interaction.gesture.startAngle = interaction.gesture.prevAngle = iEvent.angle;
                interaction.gesture.scale = 1;
            });
            InteractEvent.signals.on("new", function(_ref2) {
                var iEvent = _ref2.iEvent, interaction = _ref2.interaction;
                if (iEvent.type !== "gesturemove") {
                    return;
                }
                iEvent.ds = iEvent.scale - interaction.gesture.scale;
                interaction.target.fire(iEvent);
                interaction.gesture.prevAngle = iEvent.angle;
                interaction.gesture.prevDistance = iEvent.distance;
                if (iEvent.scale !== Infinity && iEvent.scale !== null && iEvent.scale !== undefined && !isNaN(iEvent.scale)) {
                    interaction.gesture.scale = iEvent.scale;
                }
            });
            Interactable.prototype.gesturable = function(options) {
                if (utils.is.object(options)) {
                    this.options.gesture.enabled = options.enabled === false ? false : true;
                    this.setPerAction("gesture", options);
                    this.setOnEvents("gesture", options);
                    return this;
                }
                if (utils.is.bool(options)) {
                    this.options.gesture.enabled = options;
                    if (!options) {
                        this.ongesturestart = this.ongesturestart = this.ongestureend = null;
                    }
                    return this;
                }
                return this.options.gesture;
            };
            InteractEvent.signals.on("set-delta", function(_ref3) {
                var interaction = _ref3.interaction, iEvent = _ref3.iEvent, action = _ref3.action, event = _ref3.event, starting = _ref3.starting, ending = _ref3.ending, deltaSource = _ref3.deltaSource;
                if (action !== "gesture") {
                    return;
                }
                var pointers = interaction.pointers;
                iEvent.touches = [ pointers[0], pointers[1] ];
                if (starting) {
                    iEvent.distance = utils.touchDistance(pointers, deltaSource);
                    iEvent.box = utils.touchBBox(pointers);
                    iEvent.scale = 1;
                    iEvent.ds = 0;
                    iEvent.angle = utils.touchAngle(pointers, undefined, deltaSource);
                    iEvent.da = 0;
                } else if (ending || event instanceof InteractEvent) {
                    iEvent.distance = interaction.prevEvent.distance;
                    iEvent.box = interaction.prevEvent.box;
                    iEvent.scale = interaction.prevEvent.scale;
                    iEvent.ds = iEvent.scale - 1;
                    iEvent.angle = interaction.prevEvent.angle;
                    iEvent.da = iEvent.angle - interaction.gesture.startAngle;
                } else {
                    iEvent.distance = utils.touchDistance(pointers, deltaSource);
                    iEvent.box = utils.touchBBox(pointers);
                    iEvent.scale = iEvent.distance / interaction.gesture.startDistance;
                    iEvent.angle = utils.touchAngle(pointers, interaction.gesture.prevAngle, deltaSource);
                    iEvent.ds = iEvent.scale - interaction.gesture.prevScale;
                    iEvent.da = iEvent.angle - interaction.gesture.prevAngle;
                }
            });
            Interaction.signals.on("new", function(interaction) {
                interaction.gesture = {
                    start: {
                        x: 0,
                        y: 0
                    },
                    startDistance: 0,
                    prevDistance: 0,
                    distance: 0,
                    scale: 1,
                    startAngle: 0,
                    prevAngle: 0
                };
            });
            actions.gesture = gesture;
            actions.names.push("gesture");
            utils.merge(Interactable.eventTypes, [ "gesturestart", "gesturemove", "gestureend" ]);
            actions.methodDict.gesture = "gesturable";
            defaultOptions.gesture = gesture.defaults;
            module.exports = gesture;
        }, {
            "../InteractEvent": 3,
            "../Interactable": 4,
            "../Interaction": 5,
            "../defaultOptions": 18,
            "../utils": 44,
            "./base": 6
        } ],
        10: [ function(require, module, exports) {
            "use strict";
            var actions = require("./base");
            var utils = require("../utils");
            var browser = require("../utils/browser");
            var InteractEvent = require("../InteractEvent");
            var Interactable = require("../Interactable");
            var Interaction = require("../Interaction");
            var defaultOptions = require("../defaultOptions");
            var defaultMargin = browser.supportsTouch || browser.supportsPointerEvent ? 20 : 10;
            var resize = {
                defaults: {
                    enabled: false,
                    mouseButtons: null,
                    origin: null,
                    snap: null,
                    restrict: null,
                    inertia: null,
                    autoScroll: null,
                    square: false,
                    preserveAspectRatio: false,
                    axis: "xy",
                    margin: NaN,
                    edges: null,
                    invert: "none"
                },
                checker: function checker(pointer, event, interactable, element, interaction, rect) {
                    if (!rect) {
                        return null;
                    }
                    var page = utils.extend({}, interaction.curCoords.page);
                    var options = interactable.options;
                    if (options.resize.enabled) {
                        var resizeOptions = options.resize;
                        var resizeEdges = {
                            left: false,
                            right: false,
                            top: false,
                            bottom: false
                        };
                        if (utils.is.object(resizeOptions.edges)) {
                            for (var edge in resizeEdges) {
                                resizeEdges[edge] = checkResizeEdge(edge, resizeOptions.edges[edge], page, interaction._eventTarget, element, rect, resizeOptions.margin || defaultMargin);
                            }
                            resizeEdges.left = resizeEdges.left && !resizeEdges.right;
                            resizeEdges.top = resizeEdges.top && !resizeEdges.bottom;
                            if (resizeEdges.left || resizeEdges.right || resizeEdges.top || resizeEdges.bottom) {
                                return {
                                    name: "resize",
                                    edges: resizeEdges
                                };
                            }
                        } else {
                            var right = options.resize.axis !== "y" && page.x > rect.right - defaultMargin;
                            var bottom = options.resize.axis !== "x" && page.y > rect.bottom - defaultMargin;
                            if (right || bottom) {
                                return {
                                    name: "resize",
                                    axes: (right ? "x" : "") + (bottom ? "y" : "")
                                };
                            }
                        }
                    }
                    return null;
                },
                cursors: browser.isIe9 ? {
                    x: "e-resize",
                    y: "s-resize",
                    xy: "se-resize",
                    top: "n-resize",
                    left: "w-resize",
                    bottom: "s-resize",
                    right: "e-resize",
                    topleft: "se-resize",
                    bottomright: "se-resize",
                    topright: "ne-resize",
                    bottomleft: "ne-resize"
                } : {
                    x: "ew-resize",
                    y: "ns-resize",
                    xy: "nwse-resize",
                    top: "ns-resize",
                    left: "ew-resize",
                    bottom: "ns-resize",
                    right: "ew-resize",
                    topleft: "nwse-resize",
                    bottomright: "nwse-resize",
                    topright: "nesw-resize",
                    bottomleft: "nesw-resize"
                },
                getCursor: function getCursor(action) {
                    if (action.axis) {
                        return resize.cursors[action.name + action.axis];
                    } else if (action.edges) {
                        var cursorKey = "";
                        var edgeNames = [ "top", "bottom", "left", "right" ];
                        for (var i = 0; i < 4; i++) {
                            if (action.edges[edgeNames[i]]) {
                                cursorKey += edgeNames[i];
                            }
                        }
                        return resize.cursors[cursorKey];
                    }
                }
            };
            InteractEvent.signals.on("new", function(_ref) {
                var iEvent = _ref.iEvent, interaction = _ref.interaction;
                if (iEvent.type !== "resizestart" || !interaction.prepared.edges) {
                    return;
                }
                var startRect = interaction.target.getRect(interaction.element);
                var resizeOptions = interaction.target.options.resize;
                if (resizeOptions.square || resizeOptions.preserveAspectRatio) {
                    var linkedEdges = utils.extend({}, interaction.prepared.edges);
                    linkedEdges.top = linkedEdges.top || linkedEdges.left && !linkedEdges.bottom;
                    linkedEdges.left = linkedEdges.left || linkedEdges.top && !linkedEdges.right;
                    linkedEdges.bottom = linkedEdges.bottom || linkedEdges.right && !linkedEdges.top;
                    linkedEdges.right = linkedEdges.right || linkedEdges.bottom && !linkedEdges.left;
                    interaction.prepared._linkedEdges = linkedEdges;
                } else {
                    interaction.prepared._linkedEdges = null;
                }
                if (resizeOptions.preserveAspectRatio) {
                    interaction.resizeStartAspectRatio = startRect.width / startRect.height;
                }
                interaction.resizeRects = {
                    start: startRect,
                    current: utils.extend({}, startRect),
                    inverted: utils.extend({}, startRect),
                    previous: utils.extend({}, startRect),
                    delta: {
                        left: 0,
                        right: 0,
                        width: 0,
                        top: 0,
                        bottom: 0,
                        height: 0
                    }
                };
                iEvent.rect = interaction.resizeRects.inverted;
                iEvent.deltaRect = interaction.resizeRects.delta;
            });
            InteractEvent.signals.on("new", function(_ref2) {
                var iEvent = _ref2.iEvent, phase = _ref2.phase, interaction = _ref2.interaction;
                if (phase !== "move" || !interaction.prepared.edges) {
                    return;
                }
                var resizeOptions = interaction.target.options.resize;
                var invert = resizeOptions.invert;
                var invertible = invert === "reposition" || invert === "negate";
                var edges = interaction.prepared.edges;
                var start = interaction.resizeRects.start;
                var current = interaction.resizeRects.current;
                var inverted = interaction.resizeRects.inverted;
                var delta = interaction.resizeRects.delta;
                var previous = utils.extend(interaction.resizeRects.previous, inverted);
                var originalEdges = edges;
                var dx = iEvent.dx;
                var dy = iEvent.dy;
                if (resizeOptions.preserveAspectRatio || resizeOptions.square) {
                    var startAspectRatio = resizeOptions.preserveAspectRatio ? interaction.resizeStartAspectRatio : 1;
                    edges = interaction.prepared._linkedEdges;
                    if (originalEdges.left && originalEdges.bottom || originalEdges.right && originalEdges.top) {
                        dy = -dx / startAspectRatio;
                    } else if (originalEdges.left || originalEdges.right) {
                        dy = dx / startAspectRatio;
                    } else if (originalEdges.top || originalEdges.bottom) {
                        dx = dy * startAspectRatio;
                    }
                }
                if (edges.top) {
                    current.top += dy;
                }
                if (edges.bottom) {
                    current.bottom += dy;
                }
                if (edges.left) {
                    current.left += dx;
                }
                if (edges.right) {
                    current.right += dx;
                }
                if (invertible) {
                    utils.extend(inverted, current);
                    if (invert === "reposition") {
                        var swap = void 0;
                        if (inverted.top > inverted.bottom) {
                            swap = inverted.top;
                            inverted.top = inverted.bottom;
                            inverted.bottom = swap;
                        }
                        if (inverted.left > inverted.right) {
                            swap = inverted.left;
                            inverted.left = inverted.right;
                            inverted.right = swap;
                        }
                    }
                } else {
                    inverted.top = Math.min(current.top, start.bottom);
                    inverted.bottom = Math.max(current.bottom, start.top);
                    inverted.left = Math.min(current.left, start.right);
                    inverted.right = Math.max(current.right, start.left);
                }
                inverted.width = inverted.right - inverted.left;
                inverted.height = inverted.bottom - inverted.top;
                for (var edge in inverted) {
                    delta[edge] = inverted[edge] - previous[edge];
                }
                iEvent.edges = interaction.prepared.edges;
                iEvent.rect = inverted;
                iEvent.deltaRect = delta;
            });
            Interactable.prototype.resizable = function(options) {
                if (utils.is.object(options)) {
                    this.options.resize.enabled = options.enabled === false ? false : true;
                    this.setPerAction("resize", options);
                    this.setOnEvents("resize", options);
                    if (/^x$|^y$|^xy$/.test(options.axis)) {
                        this.options.resize.axis = options.axis;
                    } else if (options.axis === null) {
                        this.options.resize.axis = defaultOptions.resize.axis;
                    }
                    if (utils.is.bool(options.preserveAspectRatio)) {
                        this.options.resize.preserveAspectRatio = options.preserveAspectRatio;
                    } else if (utils.is.bool(options.square)) {
                        this.options.resize.square = options.square;
                    }
                    return this;
                }
                if (utils.is.bool(options)) {
                    this.options.resize.enabled = options;
                    if (!options) {
                        this.onresizestart = this.onresizestart = this.onresizeend = null;
                    }
                    return this;
                }
                return this.options.resize;
            };
            function checkResizeEdge(name, value, page, element, interactableElement, rect, margin) {
                if (!value) {
                    return false;
                }
                if (value === true) {
                    var width = utils.is.number(rect.width) ? rect.width : rect.right - rect.left;
                    var height = utils.is.number(rect.height) ? rect.height : rect.bottom - rect.top;
                    if (width < 0) {
                        if (name === "left") {
                            name = "right";
                        } else if (name === "right") {
                            name = "left";
                        }
                    }
                    if (height < 0) {
                        if (name === "top") {
                            name = "bottom";
                        } else if (name === "bottom") {
                            name = "top";
                        }
                    }
                    if (name === "left") {
                        return page.x < (width >= 0 ? rect.left : rect.right) + margin;
                    }
                    if (name === "top") {
                        return page.y < (height >= 0 ? rect.top : rect.bottom) + margin;
                    }
                    if (name === "right") {
                        return page.x > (width >= 0 ? rect.right : rect.left) - margin;
                    }
                    if (name === "bottom") {
                        return page.y > (height >= 0 ? rect.bottom : rect.top) - margin;
                    }
                }
                if (!utils.is.element(element)) {
                    return false;
                }
                return utils.is.element(value) ? value === element : utils.matchesUpTo(element, value, interactableElement);
            }
            Interaction.signals.on("new", function(interaction) {
                interaction.resizeAxes = "xy";
            });
            InteractEvent.signals.on("set-delta", function(_ref3) {
                var interaction = _ref3.interaction, iEvent = _ref3.iEvent, action = _ref3.action;
                if (action !== "resize" || !interaction.resizeAxes) {
                    return;
                }
                var options = interaction.target.options;
                if (options.resize.square) {
                    if (interaction.resizeAxes === "y") {
                        iEvent.dx = iEvent.dy;
                    } else {
                        iEvent.dy = iEvent.dx;
                    }
                    iEvent.axes = "xy";
                } else {
                    iEvent.axes = interaction.resizeAxes;
                    if (interaction.resizeAxes === "x") {
                        iEvent.dy = 0;
                    } else if (interaction.resizeAxes === "y") {
                        iEvent.dx = 0;
                    }
                }
            });
            actions.resize = resize;
            actions.names.push("resize");
            utils.merge(Interactable.eventTypes, [ "resizestart", "resizemove", "resizeinertiastart", "resizeinertiaresume", "resizeend" ]);
            actions.methodDict.resize = "resizable";
            defaultOptions.resize = resize.defaults;
            module.exports = resize;
        }, {
            "../InteractEvent": 3,
            "../Interactable": 4,
            "../Interaction": 5,
            "../defaultOptions": 18,
            "../utils": 44,
            "../utils/browser": 36,
            "./base": 6
        } ],
        11: [ function(require, module, exports) {
            "use strict";
            var raf = require("./utils/raf");
            var getWindow = require("./utils/window").getWindow;
            var is = require("./utils/is");
            var domUtils = require("./utils/domUtils");
            var Interaction = require("./Interaction");
            var defaultOptions = require("./defaultOptions");
            var autoScroll = {
                defaults: {
                    enabled: false,
                    container: null,
                    margin: 60,
                    speed: 300
                },
                interaction: null,
                i: null,
                x: 0,
                y: 0,
                isScrolling: false,
                prevTime: 0,
                start: function start(interaction) {
                    autoScroll.isScrolling = true;
                    raf.cancel(autoScroll.i);
                    autoScroll.interaction = interaction;
                    autoScroll.prevTime = new Date().getTime();
                    autoScroll.i = raf.request(autoScroll.scroll);
                },
                stop: function stop() {
                    autoScroll.isScrolling = false;
                    raf.cancel(autoScroll.i);
                },
                scroll: function scroll() {
                    var options = autoScroll.interaction.target.options[autoScroll.interaction.prepared.name].autoScroll;
                    var container = options.container || getWindow(autoScroll.interaction.element);
                    var now = new Date().getTime();
                    var dt = (now - autoScroll.prevTime) / 1e3;
                    var s = options.speed * dt;
                    if (s >= 1) {
                        if (is.window(container)) {
                            container.scrollBy(autoScroll.x * s, autoScroll.y * s);
                        } else if (container) {
                            container.scrollLeft += autoScroll.x * s;
                            container.scrollTop += autoScroll.y * s;
                        }
                        autoScroll.prevTime = now;
                    }
                    if (autoScroll.isScrolling) {
                        raf.cancel(autoScroll.i);
                        autoScroll.i = raf.request(autoScroll.scroll);
                    }
                },
                check: function check(interactable, actionName) {
                    var options = interactable.options;
                    return options[actionName].autoScroll && options[actionName].autoScroll.enabled;
                },
                onInteractionMove: function onInteractionMove(_ref) {
                    var interaction = _ref.interaction, pointer = _ref.pointer;
                    if (!(interaction.interacting() && autoScroll.check(interaction.target, interaction.prepared.name))) {
                        return;
                    }
                    if (interaction.simulation) {
                        autoScroll.x = autoScroll.y = 0;
                        return;
                    }
                    var top = void 0;
                    var right = void 0;
                    var bottom = void 0;
                    var left = void 0;
                    var options = interaction.target.options[interaction.prepared.name].autoScroll;
                    var container = options.container || getWindow(interaction.element);
                    if (is.window(container)) {
                        left = pointer.clientX < autoScroll.margin;
                        top = pointer.clientY < autoScroll.margin;
                        right = pointer.clientX > container.innerWidth - autoScroll.margin;
                        bottom = pointer.clientY > container.innerHeight - autoScroll.margin;
                    } else {
                        var rect = domUtils.getElementClientRect(container);
                        left = pointer.clientX < rect.left + autoScroll.margin;
                        top = pointer.clientY < rect.top + autoScroll.margin;
                        right = pointer.clientX > rect.right - autoScroll.margin;
                        bottom = pointer.clientY > rect.bottom - autoScroll.margin;
                    }
                    autoScroll.x = right ? 1 : left ? -1 : 0;
                    autoScroll.y = bottom ? 1 : top ? -1 : 0;
                    if (!autoScroll.isScrolling) {
                        autoScroll.margin = options.margin;
                        autoScroll.speed = options.speed;
                        autoScroll.start(interaction);
                    }
                }
            };
            Interaction.signals.on("stop-active", function() {
                autoScroll.stop();
            });
            Interaction.signals.on("action-move", autoScroll.onInteractionMove);
            defaultOptions.perAction.autoScroll = autoScroll.defaults;
            module.exports = autoScroll;
        }, {
            "./Interaction": 5,
            "./defaultOptions": 18,
            "./utils/domUtils": 39,
            "./utils/is": 46,
            "./utils/raf": 50,
            "./utils/window": 52
        } ],
        12: [ function(require, module, exports) {
            "use strict";
            var Interactable = require("../Interactable");
            var actions = require("../actions/base");
            var is = require("../utils/is");
            var domUtils = require("../utils/domUtils");
            var _require = require("../utils"), warnOnce = _require.warnOnce;
            Interactable.prototype.getAction = function(pointer, event, interaction, element) {
                var action = this.defaultActionChecker(pointer, event, interaction, element);
                if (this.options.actionChecker) {
                    return this.options.actionChecker(pointer, event, action, this, element, interaction);
                }
                return action;
            };
            Interactable.prototype.ignoreFrom = warnOnce(function(newValue) {
                return this._backCompatOption("ignoreFrom", newValue);
            }, "Interactable.ignoreForm() has been deprecated. Use Interactble.draggable({ignoreFrom: newValue}).");
            Interactable.prototype.allowFrom = warnOnce(function(newValue) {
                return this._backCompatOption("allowFrom", newValue);
            }, "Interactable.allowForm() has been deprecated. Use Interactble.draggable({allowFrom: newValue}).");
            Interactable.prototype.testIgnore = function(ignoreFrom, interactableElement, element) {
                if (!ignoreFrom || !is.element(element)) {
                    return false;
                }
                if (is.string(ignoreFrom)) {
                    return domUtils.matchesUpTo(element, ignoreFrom, interactableElement);
                } else if (is.element(ignoreFrom)) {
                    return domUtils.nodeContains(ignoreFrom, element);
                }
                return false;
            };
            Interactable.prototype.testAllow = function(allowFrom, interactableElement, element) {
                if (!allowFrom) {
                    return true;
                }
                if (!is.element(element)) {
                    return false;
                }
                if (is.string(allowFrom)) {
                    return domUtils.matchesUpTo(element, allowFrom, interactableElement);
                } else if (is.element(allowFrom)) {
                    return domUtils.nodeContains(allowFrom, element);
                }
                return false;
            };
            Interactable.prototype.testIgnoreAllow = function(options, interactableElement, eventTarget) {
                return !this.testIgnore(options.ignoreFrom, interactableElement, eventTarget) && this.testAllow(options.allowFrom, interactableElement, eventTarget);
            };
            Interactable.prototype.actionChecker = function(checker) {
                if (is.function(checker)) {
                    this.options.actionChecker = checker;
                    return this;
                }
                if (checker === null) {
                    delete this.options.actionChecker;
                    return this;
                }
                return this.options.actionChecker;
            };
            Interactable.prototype.styleCursor = function(newValue) {
                if (is.bool(newValue)) {
                    this.options.styleCursor = newValue;
                    return this;
                }
                if (newValue === null) {
                    delete this.options.styleCursor;
                    return this;
                }
                return this.options.styleCursor;
            };
            Interactable.prototype.defaultActionChecker = function(pointer, event, interaction, element) {
                var rect = this.getRect(element);
                var buttons = event.buttons || {
                    0: 1,
                    1: 4,
                    3: 8,
                    4: 16
                }[event.button];
                var action = null;
                for (var _i = 0; _i < actions.names.length; _i++) {
                    var _ref;
                    _ref = actions.names[_i];
                    var actionName = _ref;
                    if (interaction.pointerIsDown && /mouse|pointer/.test(interaction.pointerType) && (buttons & this.options[actionName].mouseButtons) === 0) {
                        continue;
                    }
                    action = actions[actionName].checker(pointer, event, this, element, interaction, rect);
                    if (action) {
                        return action;
                    }
                }
            };
        }, {
            "../Interactable": 4,
            "../actions/base": 6,
            "../utils": 44,
            "../utils/domUtils": 39,
            "../utils/is": 46
        } ],
        13: [ function(require, module, exports) {
            "use strict";
            var interact = require("../interact");
            var Interactable = require("../Interactable");
            var Interaction = require("../Interaction");
            var actions = require("../actions/base");
            var defaultOptions = require("../defaultOptions");
            var scope = require("../scope");
            var utils = require("../utils");
            var signals = require("../utils/Signals").new();
            require("./InteractableMethods");
            var autoStart = {
                signals: signals,
                withinInteractionLimit: withinInteractionLimit,
                maxInteractions: Infinity,
                defaults: {
                    perAction: {
                        manualStart: false,
                        max: Infinity,
                        maxPerElement: 1,
                        allowFrom: null,
                        ignoreFrom: null,
                        mouseButtons: 1
                    }
                },
                setActionDefaults: function setActionDefaults(action) {
                    utils.extend(action.defaults, autoStart.defaults.perAction);
                },
                validateAction: validateAction
            };
            Interaction.signals.on("down", function(_ref) {
                var interaction = _ref.interaction, pointer = _ref.pointer, event = _ref.event, eventTarget = _ref.eventTarget;
                if (interaction.interacting()) {
                    return;
                }
                var actionInfo = getActionInfo(interaction, pointer, event, eventTarget);
                prepare(interaction, actionInfo);
            });
            Interaction.signals.on("move", function(_ref2) {
                var interaction = _ref2.interaction, pointer = _ref2.pointer, event = _ref2.event, eventTarget = _ref2.eventTarget;
                if (interaction.pointerType !== "mouse" || interaction.pointerIsDown || interaction.interacting()) {
                    return;
                }
                var actionInfo = getActionInfo(interaction, pointer, event, eventTarget);
                prepare(interaction, actionInfo);
            });
            Interaction.signals.on("move", function(arg) {
                var interaction = arg.interaction, event = arg.event;
                if (!interaction.pointerIsDown || interaction.interacting() || !interaction.pointerWasMoved || !interaction.prepared.name) {
                    return;
                }
                signals.fire("before-start", arg);
                var target = interaction.target;
                if (interaction.prepared.name && target) {
                    if (target.options[interaction.prepared.name].manualStart || !withinInteractionLimit(target, interaction.element, interaction.prepared)) {
                        interaction.stop(event);
                    } else {
                        interaction.start(interaction.prepared, target, interaction.element);
                    }
                }
            });
            function validateAction(action, interactable, element, eventTarget) {
                if (utils.is.object(action) && interactable.testIgnoreAllow(interactable.options[action.name], element, eventTarget) && interactable.options[action.name].enabled && withinInteractionLimit(interactable, element, action)) {
                    return action;
                }
                return null;
            }
            function validateSelector(interaction, pointer, event, matches, matchElements, eventTarget) {
                for (var i = 0, len = matches.length; i < len; i++) {
                    var match = matches[i];
                    var matchElement = matchElements[i];
                    var action = validateAction(match.getAction(pointer, event, interaction, matchElement), match, matchElement, eventTarget);
                    if (action) {
                        return {
                            action: action,
                            target: match,
                            element: matchElement
                        };
                    }
                }
                return {};
            }
            function getActionInfo(interaction, pointer, event, eventTarget) {
                var matches = [];
                var matchElements = [];
                var element = eventTarget;
                function pushMatches(interactable) {
                    matches.push(interactable);
                    matchElements.push(element);
                }
                while (utils.is.element(element)) {
                    matches = [];
                    matchElements = [];
                    scope.interactables.forEachMatch(element, pushMatches);
                    var actionInfo = validateSelector(interaction, pointer, event, matches, matchElements, eventTarget);
                    if (actionInfo.action && !actionInfo.target.options[actionInfo.action.name].manualStart) {
                        return actionInfo;
                    }
                    element = utils.parentNode(element);
                }
                return {};
            }
            function prepare(interaction, _ref3) {
                var action = _ref3.action, target = _ref3.target, element = _ref3.element;
                action = action || {};
                if (interaction.target && interaction.target.options.styleCursor) {
                    interaction.target._doc.documentElement.style.cursor = "";
                }
                interaction.target = target;
                interaction.element = element;
                utils.copyAction(interaction.prepared, action);
                if (target && target.options.styleCursor) {
                    var cursor = action ? actions[action.name].getCursor(action) : "";
                    interaction.target._doc.documentElement.style.cursor = cursor;
                }
                signals.fire("prepared", {
                    interaction: interaction
                });
            }
            Interaction.signals.on("stop", function(_ref4) {
                var interaction = _ref4.interaction;
                var target = interaction.target;
                if (target && target.options.styleCursor) {
                    target._doc.documentElement.style.cursor = "";
                }
            });
            function withinInteractionLimit(interactable, element, action) {
                var options = interactable.options;
                var maxActions = options[action.name].max;
                var maxPerElement = options[action.name].maxPerElement;
                var activeInteractions = 0;
                var targetCount = 0;
                var targetElementCount = 0;
                if (!(maxActions && maxPerElement && autoStart.maxInteractions)) {
                    return;
                }
                for (var _i = 0; _i < scope.interactions.length; _i++) {
                    var _ref5;
                    _ref5 = scope.interactions[_i];
                    var interaction = _ref5;
                    var otherAction = interaction.prepared.name;
                    if (!interaction.interacting()) {
                        continue;
                    }
                    activeInteractions++;
                    if (activeInteractions >= autoStart.maxInteractions) {
                        return false;
                    }
                    if (interaction.target !== interactable) {
                        continue;
                    }
                    targetCount += otherAction === action.name | 0;
                    if (targetCount >= maxActions) {
                        return false;
                    }
                    if (interaction.element === element) {
                        targetElementCount++;
                        if (otherAction !== action.name || targetElementCount >= maxPerElement) {
                            return false;
                        }
                    }
                }
                return autoStart.maxInteractions > 0;
            }
            interact.maxInteractions = function(newValue) {
                if (utils.is.number(newValue)) {
                    autoStart.maxInteractions = newValue;
                    return interact;
                }
                return autoStart.maxInteractions;
            };
            Interactable.settingsMethods.push("styleCursor");
            Interactable.settingsMethods.push("actionChecker");
            Interactable.settingsMethods.push("ignoreFrom");
            Interactable.settingsMethods.push("allowFrom");
            defaultOptions.base.actionChecker = null;
            defaultOptions.base.styleCursor = true;
            utils.extend(defaultOptions.perAction, autoStart.defaults.perAction);
            module.exports = autoStart;
        }, {
            "../Interactable": 4,
            "../Interaction": 5,
            "../actions/base": 6,
            "../defaultOptions": 18,
            "../interact": 21,
            "../scope": 33,
            "../utils": 44,
            "../utils/Signals": 34,
            "./InteractableMethods": 12
        } ],
        14: [ function(require, module, exports) {
            "use strict";
            var autoStart = require("./base");
            var scope = require("../scope");
            var is = require("../utils/is");
            var _require = require("../utils/domUtils"), parentNode = _require.parentNode;
            autoStart.setActionDefaults(require("../actions/drag"));
            autoStart.signals.on("before-start", function(_ref) {
                var interaction = _ref.interaction, eventTarget = _ref.eventTarget, dx = _ref.dx, dy = _ref.dy;
                if (interaction.prepared.name !== "drag") {
                    return;
                }
                var absX = Math.abs(dx);
                var absY = Math.abs(dy);
                var targetOptions = interaction.target.options.drag;
                var startAxis = targetOptions.startAxis;
                var currentAxis = absX > absY ? "x" : absX < absY ? "y" : "xy";
                interaction.prepared.axis = targetOptions.lockAxis === "start" ? currentAxis[0] : targetOptions.lockAxis;
                if (currentAxis !== "xy" && startAxis !== "xy" && startAxis !== currentAxis) {
                    interaction.prepared.name = null;
                    var element = eventTarget;
                    var getDraggable = function getDraggable(interactable) {
                        if (interactable === interaction.target) {
                            return;
                        }
                        var options = interaction.target.options.drag;
                        if (!options.manualStart && interactable.testIgnoreAllow(options, element, eventTarget)) {
                            var action = interactable.getAction(interaction.downPointer, interaction.downEvent, interaction, element);
                            if (action && action.name === "drag" && checkStartAxis(currentAxis, interactable) && autoStart.validateAction(action, interactable, element, eventTarget)) {
                                return interactable;
                            }
                        }
                    };
                    while (is.element(element)) {
                        var interactable = scope.interactables.forEachMatch(element, getDraggable);
                        if (interactable) {
                            interaction.prepared.name = "drag";
                            interaction.target = interactable;
                            interaction.element = element;
                            break;
                        }
                        element = parentNode(element);
                    }
                }
            });
            function checkStartAxis(startAxis, interactable) {
                if (!interactable) {
                    return false;
                }
                var thisAxis = interactable.options.drag.startAxis;
                return startAxis === "xy" || thisAxis === "xy" || thisAxis === startAxis;
            }
        }, {
            "../actions/drag": 7,
            "../scope": 33,
            "../utils/domUtils": 39,
            "../utils/is": 46,
            "./base": 13
        } ],
        15: [ function(require, module, exports) {
            "use strict";
            require("./base").setActionDefaults(require("../actions/gesture"));
        }, {
            "../actions/gesture": 9,
            "./base": 13
        } ],
        16: [ function(require, module, exports) {
            "use strict";
            var autoStart = require("./base");
            var Interaction = require("../Interaction");
            autoStart.defaults.perAction.hold = 0;
            autoStart.defaults.perAction.delay = 0;
            Interaction.signals.on("new", function(interaction) {
                interaction.autoStartHoldTimer = null;
            });
            autoStart.signals.on("prepared", function(_ref) {
                var interaction = _ref.interaction;
                var hold = getHoldDuration(interaction);
                if (hold > 0) {
                    interaction.autoStartHoldTimer = setTimeout(function() {
                        interaction.start(interaction.prepared, interaction.target, interaction.element);
                    }, hold);
                }
            });
            Interaction.signals.on("move", function(_ref2) {
                var interaction = _ref2.interaction, duplicate = _ref2.duplicate;
                if (interaction.pointerWasMoved && !duplicate) {
                    clearTimeout(interaction.autoStartHoldTimer);
                }
            });
            autoStart.signals.on("before-start", function(_ref3) {
                var interaction = _ref3.interaction;
                var hold = getHoldDuration(interaction);
                if (hold > 0) {
                    interaction.prepared.name = null;
                }
            });
            function getHoldDuration(interaction) {
                var actionName = interaction.prepared && interaction.prepared.name;
                if (!actionName) {
                    return null;
                }
                var options = interaction.target.options;
                return options[actionName].hold || options[actionName].delay;
            }
            module.exports = {
                getHoldDuration: getHoldDuration
            };
        }, {
            "../Interaction": 5,
            "./base": 13
        } ],
        17: [ function(require, module, exports) {
            "use strict";
            require("./base").setActionDefaults(require("../actions/resize"));
        }, {
            "../actions/resize": 10,
            "./base": 13
        } ],
        18: [ function(require, module, exports) {
            "use strict";
            module.exports = {
                base: {
                    accept: null,
                    preventDefault: "auto",
                    deltaSource: "page"
                },
                perAction: {
                    origin: {
                        x: 0,
                        y: 0
                    },
                    inertia: {
                        enabled: false,
                        resistance: 10,
                        minSpeed: 100,
                        endSpeed: 10,
                        allowResume: true,
                        smoothEndDuration: 300
                    }
                }
            };
        }, {} ],
        19: [ function(require, module, exports) {
            "use strict";
            require("./inertia");
            require("./modifiers/snap");
            require("./modifiers/restrict");
            require("./pointerEvents/base");
            require("./pointerEvents/holdRepeat");
            require("./pointerEvents/interactableTargets");
            require("./autoStart/hold");
            require("./actions/gesture");
            require("./actions/resize");
            require("./actions/drag");
            require("./actions/drop");
            require("./modifiers/snapSize");
            require("./modifiers/restrictEdges");
            require("./modifiers/restrictSize");
            require("./autoStart/gesture");
            require("./autoStart/resize");
            require("./autoStart/drag");
            require("./interactablePreventDefault.js");
            require("./autoScroll");
            module.exports = require("./interact");
        }, {
            "./actions/drag": 7,
            "./actions/drop": 8,
            "./actions/gesture": 9,
            "./actions/resize": 10,
            "./autoScroll": 11,
            "./autoStart/drag": 14,
            "./autoStart/gesture": 15,
            "./autoStart/hold": 16,
            "./autoStart/resize": 17,
            "./inertia": 20,
            "./interact": 21,
            "./interactablePreventDefault.js": 22,
            "./modifiers/restrict": 24,
            "./modifiers/restrictEdges": 25,
            "./modifiers/restrictSize": 26,
            "./modifiers/snap": 27,
            "./modifiers/snapSize": 28,
            "./pointerEvents/base": 30,
            "./pointerEvents/holdRepeat": 31,
            "./pointerEvents/interactableTargets": 32
        } ],
        20: [ function(require, module, exports) {
            "use strict";
            var InteractEvent = require("./InteractEvent");
            var Interaction = require("./Interaction");
            var modifiers = require("./modifiers/base");
            var utils = require("./utils");
            var animationFrame = require("./utils/raf");
            Interaction.signals.on("new", function(interaction) {
                interaction.inertiaStatus = {
                    active: false,
                    smoothEnd: false,
                    allowResume: false,
                    startEvent: null,
                    upCoords: {},
                    xe: 0,
                    ye: 0,
                    sx: 0,
                    sy: 0,
                    t0: 0,
                    vx0: 0,
                    vys: 0,
                    duration: 0,
                    lambda_v0: 0,
                    one_ve_v0: 0,
                    i: null
                };
                interaction.boundInertiaFrame = function() {
                    return inertiaFrame.apply(interaction);
                };
                interaction.boundSmoothEndFrame = function() {
                    return smoothEndFrame.apply(interaction);
                };
            });
            Interaction.signals.on("down", function(_ref) {
                var interaction = _ref.interaction, event = _ref.event, pointer = _ref.pointer, eventTarget = _ref.eventTarget;
                var status = interaction.inertiaStatus;
                if (status.active) {
                    var element = eventTarget;
                    while (utils.is.element(element)) {
                        if (element === interaction.element) {
                            animationFrame.cancel(status.i);
                            status.active = false;
                            interaction.simulation = null;
                            interaction.updatePointer(pointer);
                            utils.setCoords(interaction.curCoords, interaction.pointers);
                            var signalArg = {
                                interaction: interaction
                            };
                            Interaction.signals.fire("before-action-move", signalArg);
                            Interaction.signals.fire("action-resume", signalArg);
                            var resumeEvent = new InteractEvent(interaction, event, interaction.prepared.name, "inertiaresume", interaction.element);
                            interaction.target.fire(resumeEvent);
                            interaction.prevEvent = resumeEvent;
                            modifiers.resetStatuses(interaction.modifierStatuses);
                            utils.copyCoords(interaction.prevCoords, interaction.curCoords);
                            break;
                        }
                        element = utils.parentNode(element);
                    }
                }
            });
            Interaction.signals.on("up", function(_ref2) {
                var interaction = _ref2.interaction, event = _ref2.event;
                var status = interaction.inertiaStatus;
                if (!interaction.interacting() || status.active) {
                    return;
                }
                var target = interaction.target;
                var options = target && target.options;
                var inertiaOptions = options && interaction.prepared.name && options[interaction.prepared.name].inertia;
                var now = new Date().getTime();
                var statuses = {};
                var page = utils.extend({}, interaction.curCoords.page);
                var pointerSpeed = interaction.pointerDelta.client.speed;
                var smoothEnd = false;
                var modifierResult = void 0;
                var inertiaPossible = inertiaOptions && inertiaOptions.enabled && interaction.prepared.name !== "gesture" && event !== status.startEvent;
                var inertia = inertiaPossible && now - interaction.curCoords.timeStamp < 50 && pointerSpeed > inertiaOptions.minSpeed && pointerSpeed > inertiaOptions.endSpeed;
                var modifierArg = {
                    interaction: interaction,
                    pageCoords: page,
                    statuses: statuses,
                    preEnd: true,
                    requireEndOnly: true
                };
                if (inertiaPossible && !inertia) {
                    modifiers.resetStatuses(statuses);
                    modifierResult = modifiers.setAll(modifierArg);
                    if (modifierResult.shouldMove && modifierResult.locked) {
                        smoothEnd = true;
                    }
                }
                if (!(inertia || smoothEnd)) {
                    return;
                }
                utils.copyCoords(status.upCoords, interaction.curCoords);
                interaction.pointers[0] = status.startEvent = new InteractEvent(interaction, event, interaction.prepared.name, "inertiastart", interaction.element);
                status.t0 = now;
                status.active = true;
                status.allowResume = inertiaOptions.allowResume;
                interaction.simulation = status;
                target.fire(status.startEvent);
                if (inertia) {
                    status.vx0 = interaction.pointerDelta.client.vx;
                    status.vy0 = interaction.pointerDelta.client.vy;
                    status.v0 = pointerSpeed;
                    calcInertia(interaction, status);
                    utils.extend(page, interaction.curCoords.page);
                    page.x += status.xe;
                    page.y += status.ye;
                    modifiers.resetStatuses(statuses);
                    modifierResult = modifiers.setAll(modifierArg);
                    status.modifiedXe += modifierResult.dx;
                    status.modifiedYe += modifierResult.dy;
                    status.i = animationFrame.request(interaction.boundInertiaFrame);
                } else {
                    status.smoothEnd = true;
                    status.xe = modifierResult.dx;
                    status.ye = modifierResult.dy;
                    status.sx = status.sy = 0;
                    status.i = animationFrame.request(interaction.boundSmoothEndFrame);
                }
            });
            Interaction.signals.on("stop-active", function(_ref3) {
                var interaction = _ref3.interaction;
                var status = interaction.inertiaStatus;
                if (status.active) {
                    animationFrame.cancel(status.i);
                    status.active = false;
                    interaction.simulation = null;
                }
            });
            function calcInertia(interaction, status) {
                var inertiaOptions = interaction.target.options[interaction.prepared.name].inertia;
                var lambda = inertiaOptions.resistance;
                var inertiaDur = -Math.log(inertiaOptions.endSpeed / status.v0) / lambda;
                status.x0 = interaction.prevEvent.pageX;
                status.y0 = interaction.prevEvent.pageY;
                status.t0 = status.startEvent.timeStamp / 1e3;
                status.sx = status.sy = 0;
                status.modifiedXe = status.xe = (status.vx0 - inertiaDur) / lambda;
                status.modifiedYe = status.ye = (status.vy0 - inertiaDur) / lambda;
                status.te = inertiaDur;
                status.lambda_v0 = lambda / status.v0;
                status.one_ve_v0 = 1 - inertiaOptions.endSpeed / status.v0;
            }
            function inertiaFrame() {
                updateInertiaCoords(this);
                utils.setCoordDeltas(this.pointerDelta, this.prevCoords, this.curCoords);
                var status = this.inertiaStatus;
                var options = this.target.options[this.prepared.name].inertia;
                var lambda = options.resistance;
                var t = new Date().getTime() / 1e3 - status.t0;
                if (t < status.te) {
                    var progress = 1 - (Math.exp(-lambda * t) - status.lambda_v0) / status.one_ve_v0;
                    if (status.modifiedXe === status.xe && status.modifiedYe === status.ye) {
                        status.sx = status.xe * progress;
                        status.sy = status.ye * progress;
                    } else {
                        var quadPoint = utils.getQuadraticCurvePoint(0, 0, status.xe, status.ye, status.modifiedXe, status.modifiedYe, progress);
                        status.sx = quadPoint.x;
                        status.sy = quadPoint.y;
                    }
                    this.doMove();
                    status.i = animationFrame.request(this.boundInertiaFrame);
                } else {
                    status.sx = status.modifiedXe;
                    status.sy = status.modifiedYe;
                    this.doMove();
                    this.end(status.startEvent);
                    status.active = false;
                    this.simulation = null;
                }
                utils.copyCoords(this.prevCoords, this.curCoords);
            }
            function smoothEndFrame() {
                updateInertiaCoords(this);
                var status = this.inertiaStatus;
                var t = new Date().getTime() - status.t0;
                var duration = this.target.options[this.prepared.name].inertia.smoothEndDuration;
                if (t < duration) {
                    status.sx = utils.easeOutQuad(t, 0, status.xe, duration);
                    status.sy = utils.easeOutQuad(t, 0, status.ye, duration);
                    this.pointerMove(status.startEvent, status.startEvent);
                    status.i = animationFrame.request(this.boundSmoothEndFrame);
                } else {
                    status.sx = status.xe;
                    status.sy = status.ye;
                    this.pointerMove(status.startEvent, status.startEvent);
                    this.end(status.startEvent);
                    status.smoothEnd = status.active = false;
                    this.simulation = null;
                }
            }
            function updateInertiaCoords(interaction) {
                var status = interaction.inertiaStatus;
                if (!status.active) {
                    return;
                }
                var pageUp = status.upCoords.page;
                var clientUp = status.upCoords.client;
                utils.setCoords(interaction.curCoords, [ {
                    pageX: pageUp.x + status.sx,
                    pageY: pageUp.y + status.sy,
                    clientX: clientUp.x + status.sx,
                    clientY: clientUp.y + status.sy
                } ]);
            }
        }, {
            "./InteractEvent": 3,
            "./Interaction": 5,
            "./modifiers/base": 23,
            "./utils": 44,
            "./utils/raf": 50
        } ],
        21: [ function(require, module, exports) {
            "use strict";
            var browser = require("./utils/browser");
            var events = require("./utils/events");
            var utils = require("./utils");
            var scope = require("./scope");
            var Interactable = require("./Interactable");
            var Interaction = require("./Interaction");
            var globalEvents = {};
            function interact(element, options) {
                var interactable = scope.interactables.get(element, options);
                if (!interactable) {
                    interactable = new Interactable(element, options);
                    interactable.events.global = globalEvents;
                }
                return interactable;
            }
            interact.isSet = function(element, options) {
                return scope.interactables.indexOfElement(element, options && options.context) !== -1;
            };
            interact.on = function(type, listener, options) {
                if (utils.is.string(type) && type.search(" ") !== -1) {
                    type = type.trim().split(/ +/);
                }
                if (utils.is.array(type)) {
                    for (var _i = 0; _i < type.length; _i++) {
                        var _ref;
                        _ref = type[_i];
                        var eventType = _ref;
                        interact.on(eventType, listener, options);
                    }
                    return interact;
                }
                if (utils.is.object(type)) {
                    for (var prop in type) {
                        interact.on(prop, type[prop], listener);
                    }
                    return interact;
                }
                if (utils.contains(Interactable.eventTypes, type)) {
                    if (!globalEvents[type]) {
                        globalEvents[type] = [ listener ];
                    } else {
                        globalEvents[type].push(listener);
                    }
                } else {
                    events.add(scope.document, type, listener, {
                        options: options
                    });
                }
                return interact;
            };
            interact.off = function(type, listener, options) {
                if (utils.is.string(type) && type.search(" ") !== -1) {
                    type = type.trim().split(/ +/);
                }
                if (utils.is.array(type)) {
                    for (var _i2 = 0; _i2 < type.length; _i2++) {
                        var _ref2;
                        _ref2 = type[_i2];
                        var eventType = _ref2;
                        interact.off(eventType, listener, options);
                    }
                    return interact;
                }
                if (utils.is.object(type)) {
                    for (var prop in type) {
                        interact.off(prop, type[prop], listener);
                    }
                    return interact;
                }
                if (!utils.contains(Interactable.eventTypes, type)) {
                    events.remove(scope.document, type, listener, options);
                } else {
                    var index = void 0;
                    if (type in globalEvents && (index = globalEvents[type].indexOf(listener)) !== -1) {
                        globalEvents[type].splice(index, 1);
                    }
                }
                return interact;
            };
            interact.debug = function() {
                return scope;
            };
            interact.getPointerAverage = utils.pointerAverage;
            interact.getTouchBBox = utils.touchBBox;
            interact.getTouchDistance = utils.touchDistance;
            interact.getTouchAngle = utils.touchAngle;
            interact.getElementRect = utils.getElementRect;
            interact.getElementClientRect = utils.getElementClientRect;
            interact.matchesSelector = utils.matchesSelector;
            interact.closest = utils.closest;
            interact.supportsTouch = function() {
                return browser.supportsTouch;
            };
            interact.supportsPointerEvent = function() {
                return browser.supportsPointerEvent;
            };
            interact.stop = function(event) {
                for (var i = scope.interactions.length - 1; i >= 0; i--) {
                    scope.interactions[i].stop(event);
                }
                return interact;
            };
            interact.pointerMoveTolerance = function(newValue) {
                if (utils.is.number(newValue)) {
                    Interaction.pointerMoveTolerance = newValue;
                    return interact;
                }
                return Interaction.pointerMoveTolerance;
            };
            interact.addDocument = scope.addDocument;
            interact.removeDocument = scope.removeDocument;
            scope.interact = interact;
            module.exports = interact;
        }, {
            "./Interactable": 4,
            "./Interaction": 5,
            "./scope": 33,
            "./utils": 44,
            "./utils/browser": 36,
            "./utils/events": 40
        } ],
        22: [ function(require, module, exports) {
            "use strict";
            var Interactable = require("./Interactable");
            var Interaction = require("./Interaction");
            var scope = require("./scope");
            var is = require("./utils/is");
            var events = require("./utils/events");
            var browser = require("./utils/browser");
            var _require = require("./utils/domUtils"), nodeContains = _require.nodeContains, matchesSelector = _require.matchesSelector;
            Interactable.prototype.preventDefault = function(newValue) {
                if (/^(always|never|auto)$/.test(newValue)) {
                    this.options.preventDefault = newValue;
                    return this;
                }
                if (is.bool(newValue)) {
                    this.options.preventDefault = newValue ? "always" : "never";
                    return this;
                }
                return this.options.preventDefault;
            };
            Interactable.prototype.checkAndPreventDefault = function(event) {
                var setting = this.options.preventDefault;
                if (setting === "never") {
                    return;
                }
                if (setting === "always") {
                    event.preventDefault();
                    return;
                }
                if (events.supportsPassive && /^touch(start|move)$/.test(event.type) && !browser.isIOS) {
                    return;
                }
                if (/^(mouse|pointer|touch)*(down|start)/i.test(event.type)) {
                    return;
                }
                if (is.element(event.target) && matchesSelector(event.target, "input,select,textarea,[contenteditable=true],[contenteditable=true] *")) {
                    return;
                }
                event.preventDefault();
            };
            function onInteractionEvent(_ref) {
                var interaction = _ref.interaction, event = _ref.event;
                if (interaction.target) {
                    interaction.target.checkAndPreventDefault(event);
                }
            }
            var _arr = [ "down", "move", "up", "cancel" ];
            for (var _i = 0; _i < _arr.length; _i++) {
                var eventSignal = _arr[_i];
                Interaction.signals.on(eventSignal, onInteractionEvent);
            }
            Interaction.docEvents.dragstart = function preventNativeDrag(event) {
                for (var _i2 = 0; _i2 < scope.interactions.length; _i2++) {
                    var _ref2;
                    _ref2 = scope.interactions[_i2];
                    var interaction = _ref2;
                    if (interaction.element && (interaction.element === event.target || nodeContains(interaction.element, event.target))) {
                        interaction.target.checkAndPreventDefault(event);
                        return;
                    }
                }
            };
        }, {
            "./Interactable": 4,
            "./Interaction": 5,
            "./scope": 33,
            "./utils/browser": 36,
            "./utils/domUtils": 39,
            "./utils/events": 40,
            "./utils/is": 46
        } ],
        23: [ function(require, module, exports) {
            "use strict";
            var InteractEvent = require("../InteractEvent");
            var Interaction = require("../Interaction");
            var extend = require("../utils/extend");
            var modifiers = {
                names: [],
                setOffsets: function setOffsets(arg) {
                    var interaction = arg.interaction, page = arg.pageCoords;
                    var target = interaction.target, element = interaction.element, startOffset = interaction.startOffset;
                    var rect = target.getRect(element);
                    if (rect) {
                        startOffset.left = page.x - rect.left;
                        startOffset.top = page.y - rect.top;
                        startOffset.right = rect.right - page.x;
                        startOffset.bottom = rect.bottom - page.y;
                        if (!("width" in rect)) {
                            rect.width = rect.right - rect.left;
                        }
                        if (!("height" in rect)) {
                            rect.height = rect.bottom - rect.top;
                        }
                    } else {
                        startOffset.left = startOffset.top = startOffset.right = startOffset.bottom = 0;
                    }
                    arg.rect = rect;
                    arg.interactable = target;
                    arg.element = element;
                    for (var _i = 0; _i < modifiers.names.length; _i++) {
                        var _ref;
                        _ref = modifiers.names[_i];
                        var modifierName = _ref;
                        arg.options = target.options[interaction.prepared.name][modifierName];
                        if (!arg.options) {
                            continue;
                        }
                        interaction.modifierOffsets[modifierName] = modifiers[modifierName].setOffset(arg);
                    }
                },
                setAll: function setAll(arg) {
                    var interaction = arg.interaction, statuses = arg.statuses, preEnd = arg.preEnd, requireEndOnly = arg.requireEndOnly;
                    var result = {
                        dx: 0,
                        dy: 0,
                        changed: false,
                        locked: false,
                        shouldMove: true
                    };
                    arg.modifiedCoords = extend({}, arg.pageCoords);
                    for (var _i2 = 0; _i2 < modifiers.names.length; _i2++) {
                        var _ref2;
                        _ref2 = modifiers.names[_i2];
                        var modifierName = _ref2;
                        var modifier = modifiers[modifierName];
                        var options = interaction.target.options[interaction.prepared.name][modifierName];
                        if (!shouldDo(options, preEnd, requireEndOnly)) {
                            continue;
                        }
                        arg.status = arg.status = statuses[modifierName];
                        arg.options = options;
                        arg.offset = arg.interaction.modifierOffsets[modifierName];
                        modifier.set(arg);
                        if (arg.status.locked) {
                            arg.modifiedCoords.x += arg.status.dx;
                            arg.modifiedCoords.y += arg.status.dy;
                            result.dx += arg.status.dx;
                            result.dy += arg.status.dy;
                            result.locked = true;
                        }
                    }
                    result.shouldMove = !arg.status || !result.locked || arg.status.changed;
                    return result;
                },
                resetStatuses: function resetStatuses(statuses) {
                    for (var _i3 = 0; _i3 < modifiers.names.length; _i3++) {
                        var _ref3;
                        _ref3 = modifiers.names[_i3];
                        var modifierName = _ref3;
                        var status = statuses[modifierName] || {};
                        status.dx = status.dy = 0;
                        status.modifiedX = status.modifiedY = NaN;
                        status.locked = false;
                        status.changed = true;
                        statuses[modifierName] = status;
                    }
                    return statuses;
                },
                start: function start(_ref4, signalName) {
                    var interaction = _ref4.interaction;
                    var arg = {
                        interaction: interaction,
                        pageCoords: (signalName === "action-resume" ? interaction.curCoords : interaction.startCoords).page,
                        startOffset: interaction.startOffset,
                        statuses: interaction.modifierStatuses,
                        preEnd: false,
                        requireEndOnly: false
                    };
                    modifiers.setOffsets(arg);
                    modifiers.resetStatuses(arg.statuses);
                    arg.pageCoords = extend({}, interaction.startCoords.page);
                    interaction.modifierResult = modifiers.setAll(arg);
                },
                beforeMove: function beforeMove(_ref5) {
                    var interaction = _ref5.interaction, preEnd = _ref5.preEnd, interactingBeforeMove = _ref5.interactingBeforeMove;
                    var modifierResult = modifiers.setAll({
                        interaction: interaction,
                        preEnd: preEnd,
                        pageCoords: interaction.curCoords.page,
                        statuses: interaction.modifierStatuses,
                        requireEndOnly: false
                    });
                    if (!modifierResult.shouldMove && interactingBeforeMove) {
                        interaction._dontFireMove = true;
                    }
                    interaction.modifierResult = modifierResult;
                },
                end: function end(_ref6) {
                    var interaction = _ref6.interaction, event = _ref6.event;
                    for (var _i4 = 0; _i4 < modifiers.names.length; _i4++) {
                        var _ref7;
                        _ref7 = modifiers.names[_i4];
                        var modifierName = _ref7;
                        var options = interaction.target.options[interaction.prepared.name][modifierName];
                        if (shouldDo(options, true, true)) {
                            interaction.doMove({
                                event: event,
                                preEnd: true
                            });
                            break;
                        }
                    }
                },
                setXY: function setXY(arg) {
                    var iEvent = arg.iEvent, interaction = arg.interaction;
                    var modifierArg = extend({}, arg);
                    for (var i = 0; i < modifiers.names.length; i++) {
                        var modifierName = modifiers.names[i];
                        modifierArg.options = interaction.target.options[interaction.prepared.name][modifierName];
                        if (!modifierArg.options) {
                            continue;
                        }
                        var modifier = modifiers[modifierName];
                        modifierArg.status = interaction.modifierStatuses[modifierName];
                        iEvent[modifierName] = modifier.modifyCoords(modifierArg);
                    }
                }
            };
            Interaction.signals.on("new", function(interaction) {
                interaction.startOffset = {
                    left: 0,
                    right: 0,
                    top: 0,
                    bottom: 0
                };
                interaction.modifierOffsets = {};
                interaction.modifierStatuses = modifiers.resetStatuses({});
                interaction.modifierResult = null;
            });
            Interaction.signals.on("action-start", modifiers.start);
            Interaction.signals.on("action-resume", modifiers.start);
            Interaction.signals.on("before-action-move", modifiers.beforeMove);
            Interaction.signals.on("action-end", modifiers.end);
            InteractEvent.signals.on("set-xy", modifiers.setXY);
            function shouldDo(options, preEnd, requireEndOnly) {
                return options && options.enabled && (preEnd || !options.endOnly) && (!requireEndOnly || options.endOnly);
            }
            module.exports = modifiers;
        }, {
            "../InteractEvent": 3,
            "../Interaction": 5,
            "../utils/extend": 41
        } ],
        24: [ function(require, module, exports) {
            "use strict";
            var modifiers = require("./base");
            var utils = require("../utils");
            var defaultOptions = require("../defaultOptions");
            var restrict = {
                defaults: {
                    enabled: false,
                    endOnly: false,
                    restriction: null,
                    elementRect: null
                },
                setOffset: function setOffset(_ref) {
                    var rect = _ref.rect, startOffset = _ref.startOffset, options = _ref.options;
                    var elementRect = options && options.elementRect;
                    var offset = {};
                    if (rect && elementRect) {
                        offset.left = startOffset.left - rect.width * elementRect.left;
                        offset.top = startOffset.top - rect.height * elementRect.top;
                        offset.right = startOffset.right - rect.width * (1 - elementRect.right);
                        offset.bottom = startOffset.bottom - rect.height * (1 - elementRect.bottom);
                    } else {
                        offset.left = offset.top = offset.right = offset.bottom = 0;
                    }
                    return offset;
                },
                set: function set(_ref2) {
                    var modifiedCoords = _ref2.modifiedCoords, interaction = _ref2.interaction, status = _ref2.status, options = _ref2.options;
                    if (!options) {
                        return status;
                    }
                    var page = status.useStatusXY ? {
                        x: status.x,
                        y: status.y
                    } : utils.extend({}, modifiedCoords);
                    var restriction = getRestrictionRect(options.restriction, interaction, page);
                    if (!restriction) {
                        return status;
                    }
                    status.dx = 0;
                    status.dy = 0;
                    status.locked = false;
                    var rect = restriction;
                    var modifiedX = page.x;
                    var modifiedY = page.y;
                    var offset = interaction.modifierOffsets.restrict;
                    if ("x" in restriction && "y" in restriction) {
                        modifiedX = Math.max(Math.min(rect.x + rect.width - offset.right, page.x), rect.x + offset.left);
                        modifiedY = Math.max(Math.min(rect.y + rect.height - offset.bottom, page.y), rect.y + offset.top);
                    } else {
                        modifiedX = Math.max(Math.min(rect.right - offset.right, page.x), rect.left + offset.left);
                        modifiedY = Math.max(Math.min(rect.bottom - offset.bottom, page.y), rect.top + offset.top);
                    }
                    status.dx = modifiedX - page.x;
                    status.dy = modifiedY - page.y;
                    status.changed = status.modifiedX !== modifiedX || status.modifiedY !== modifiedY;
                    status.locked = !!(status.dx || status.dy);
                    status.modifiedX = modifiedX;
                    status.modifiedY = modifiedY;
                },
                modifyCoords: function modifyCoords(_ref3) {
                    var page = _ref3.page, client = _ref3.client, status = _ref3.status, phase = _ref3.phase, options = _ref3.options;
                    var elementRect = options && options.elementRect;
                    if (options && options.enabled && !(phase === "start" && elementRect && status.locked)) {
                        if (status.locked) {
                            page.x += status.dx;
                            page.y += status.dy;
                            client.x += status.dx;
                            client.y += status.dy;
                            return {
                                dx: status.dx,
                                dy: status.dy
                            };
                        }
                    }
                },
                getRestrictionRect: getRestrictionRect
            };
            function getRestrictionRect(value, interaction, page) {
                if (utils.is.function(value)) {
                    return utils.resolveRectLike(value, interaction.target, interaction.element, [ page.x, page.y, interaction ]);
                } else {
                    return utils.resolveRectLike(value, interaction.target, interaction.element);
                }
            }
            modifiers.restrict = restrict;
            modifiers.names.push("restrict");
            defaultOptions.perAction.restrict = restrict.defaults;
            module.exports = restrict;
        }, {
            "../defaultOptions": 18,
            "../utils": 44,
            "./base": 23
        } ],
        25: [ function(require, module, exports) {
            "use strict";
            var modifiers = require("./base");
            var utils = require("../utils");
            var rectUtils = require("../utils/rect");
            var defaultOptions = require("../defaultOptions");
            var resize = require("../actions/resize");
            var _require = require("./restrict"), getRestrictionRect = _require.getRestrictionRect;
            var noInner = {
                top: +Infinity,
                left: +Infinity,
                bottom: -Infinity,
                right: -Infinity
            };
            var noOuter = {
                top: -Infinity,
                left: -Infinity,
                bottom: +Infinity,
                right: +Infinity
            };
            var restrictEdges = {
                defaults: {
                    enabled: false,
                    endOnly: false,
                    min: null,
                    max: null,
                    offset: null
                },
                setOffset: function setOffset(_ref) {
                    var interaction = _ref.interaction, startOffset = _ref.startOffset, options = _ref.options;
                    if (!options) {
                        return utils.extend({}, startOffset);
                    }
                    var offset = getRestrictionRect(options.offset, interaction, interaction.startCoords.page);
                    if (offset) {
                        return {
                            top: startOffset.top + offset.y,
                            left: startOffset.left + offset.x,
                            bottom: startOffset.bottom + offset.y,
                            right: startOffset.right + offset.x
                        };
                    }
                    return startOffset;
                },
                set: function set(_ref2) {
                    var modifiedCoords = _ref2.modifiedCoords, interaction = _ref2.interaction, status = _ref2.status, offset = _ref2.offset, options = _ref2.options;
                    var edges = interaction.prepared.linkedEdges || interaction.prepared.edges;
                    if (!interaction.interacting() || !edges) {
                        return;
                    }
                    var page = status.useStatusXY ? {
                        x: status.x,
                        y: status.y
                    } : utils.extend({}, modifiedCoords);
                    var inner = rectUtils.xywhToTlbr(getRestrictionRect(options.inner, interaction, page)) || noInner;
                    var outer = rectUtils.xywhToTlbr(getRestrictionRect(options.outer, interaction, page)) || noOuter;
                    var modifiedX = page.x;
                    var modifiedY = page.y;
                    status.dx = 0;
                    status.dy = 0;
                    status.locked = false;
                    if (edges.top) {
                        modifiedY = Math.min(Math.max(outer.top + offset.top, page.y), inner.top + offset.top);
                    } else if (edges.bottom) {
                        modifiedY = Math.max(Math.min(outer.bottom - offset.bottom, page.y), inner.bottom - offset.bottom);
                    }
                    if (edges.left) {
                        modifiedX = Math.min(Math.max(outer.left + offset.left, page.x), inner.left + offset.left);
                    } else if (edges.right) {
                        modifiedX = Math.max(Math.min(outer.right - offset.right, page.x), inner.right - offset.right);
                    }
                    status.dx = modifiedX - page.x;
                    status.dy = modifiedY - page.y;
                    status.changed = status.modifiedX !== modifiedX || status.modifiedY !== modifiedY;
                    status.locked = !!(status.dx || status.dy);
                    status.modifiedX = modifiedX;
                    status.modifiedY = modifiedY;
                },
                modifyCoords: function modifyCoords(_ref3) {
                    var page = _ref3.page, client = _ref3.client, status = _ref3.status, phase = _ref3.phase, options = _ref3.options;
                    if (options && options.enabled && !(phase === "start" && status.locked)) {
                        if (status.locked) {
                            page.x += status.dx;
                            page.y += status.dy;
                            client.x += status.dx;
                            client.y += status.dy;
                            return {
                                dx: status.dx,
                                dy: status.dy
                            };
                        }
                    }
                },
                noInner: noInner,
                noOuter: noOuter,
                getRestrictionRect: getRestrictionRect
            };
            modifiers.restrictEdges = restrictEdges;
            modifiers.names.push("restrictEdges");
            defaultOptions.perAction.restrictEdges = restrictEdges.defaults;
            resize.defaults.restrictEdges = restrictEdges.defaults;
            module.exports = restrictEdges;
        }, {
            "../actions/resize": 10,
            "../defaultOptions": 18,
            "../utils": 44,
            "../utils/rect": 51,
            "./base": 23,
            "./restrict": 24
        } ],
        26: [ function(require, module, exports) {
            "use strict";
            var modifiers = require("./base");
            var restrictEdges = require("./restrictEdges");
            var utils = require("../utils");
            var rectUtils = require("../utils/rect");
            var defaultOptions = require("../defaultOptions");
            var resize = require("../actions/resize");
            var noMin = {
                width: -Infinity,
                height: -Infinity
            };
            var noMax = {
                width: +Infinity,
                height: +Infinity
            };
            var restrictSize = {
                defaults: {
                    enabled: false,
                    endOnly: false,
                    min: null,
                    max: null
                },
                setOffset: function setOffset(_ref) {
                    var interaction = _ref.interaction;
                    return interaction.startOffset;
                },
                set: function set(arg) {
                    var interaction = arg.interaction, options = arg.options;
                    var edges = interaction.prepared.linkedEdges || interaction.prepared.edges;
                    if (!interaction.interacting() || !edges) {
                        return;
                    }
                    var rect = rectUtils.xywhToTlbr(interaction.resizeRects.inverted);
                    var minSize = rectUtils.tlbrToXywh(restrictEdges.getRestrictionRect(options.min, interaction)) || noMin;
                    var maxSize = rectUtils.tlbrToXywh(restrictEdges.getRestrictionRect(options.max, interaction)) || noMax;
                    arg.options = {
                        enabled: options.enabled,
                        endOnly: options.endOnly,
                        inner: utils.extend({}, restrictEdges.noInner),
                        outer: utils.extend({}, restrictEdges.noOuter)
                    };
                    if (edges.top) {
                        arg.options.inner.top = rect.bottom - minSize.height;
                        arg.options.outer.top = rect.bottom - maxSize.height;
                    } else if (edges.bottom) {
                        arg.options.inner.bottom = rect.top + minSize.height;
                        arg.options.outer.bottom = rect.top + maxSize.height;
                    }
                    if (edges.left) {
                        arg.options.inner.left = rect.right - minSize.width;
                        arg.options.outer.left = rect.right - maxSize.width;
                    } else if (edges.right) {
                        arg.options.inner.right = rect.left + minSize.width;
                        arg.options.outer.right = rect.left + maxSize.width;
                    }
                    restrictEdges.set(arg);
                },
                modifyCoords: restrictEdges.modifyCoords
            };
            modifiers.restrictSize = restrictSize;
            modifiers.names.push("restrictSize");
            defaultOptions.perAction.restrictSize = restrictSize.defaults;
            resize.defaults.restrictSize = restrictSize.defaults;
            module.exports = restrictSize;
        }, {
            "../actions/resize": 10,
            "../defaultOptions": 18,
            "../utils": 44,
            "../utils/rect": 51,
            "./base": 23,
            "./restrictEdges": 25
        } ],
        27: [ function(require, module, exports) {
            "use strict";
            var modifiers = require("./base");
            var interact = require("../interact");
            var utils = require("../utils");
            var defaultOptions = require("../defaultOptions");
            var snap = {
                defaults: {
                    enabled: false,
                    endOnly: false,
                    range: Infinity,
                    targets: null,
                    offsets: null,
                    relativePoints: null
                },
                setOffset: function setOffset(_ref) {
                    var interaction = _ref.interaction, interactable = _ref.interactable, element = _ref.element, rect = _ref.rect, startOffset = _ref.startOffset, options = _ref.options;
                    var offsets = [];
                    var optionsOrigin = utils.rectToXY(utils.resolveRectLike(options.origin));
                    var origin = optionsOrigin || utils.getOriginXY(interactable, element, interaction.prepared.name);
                    options = options || interactable.options[interaction.prepared.name].snap || {};
                    var snapOffset = void 0;
                    if (options.offset === "startCoords") {
                        snapOffset = {
                            x: interaction.startCoords.page.x - origin.x,
                            y: interaction.startCoords.page.y - origin.y
                        };
                    } else {
                        var offsetRect = utils.resolveRectLike(options.offset, interactable, element, [ interaction ]);
                        snapOffset = utils.rectToXY(offsetRect) || {
                            x: 0,
                            y: 0
                        };
                    }
                    if (rect && options.relativePoints && options.relativePoints.length) {
                        for (var _i = 0; _i < options.relativePoints.length; _i++) {
                            var _ref3;
                            _ref3 = options.relativePoints[_i];
                            var _ref2 = _ref3;
                            var relativeX = _ref2.x;
                            var relativeY = _ref2.y;
                            offsets.push({
                                x: startOffset.left - rect.width * relativeX + snapOffset.x,
                                y: startOffset.top - rect.height * relativeY + snapOffset.y
                            });
                        }
                    } else {
                        offsets.push(snapOffset);
                    }
                    return offsets;
                },
                set: function set(_ref4) {
                    var interaction = _ref4.interaction, modifiedCoords = _ref4.modifiedCoords, status = _ref4.status, options = _ref4.options, offsets = _ref4.offset;
                    var targets = [];
                    var target = void 0;
                    var page = void 0;
                    var i = void 0;
                    if (status.useStatusXY) {
                        page = {
                            x: status.x,
                            y: status.y
                        };
                    } else {
                        var origin = utils.getOriginXY(interaction.target, interaction.element, interaction.prepared.name);
                        page = utils.extend({}, modifiedCoords);
                        page.x -= origin.x;
                        page.y -= origin.y;
                    }
                    status.realX = page.x;
                    status.realY = page.y;
                    var len = options.targets ? options.targets.length : 0;
                    for (var _i2 = 0; _i2 < offsets.length; _i2++) {
                        var _ref6;
                        _ref6 = offsets[_i2];
                        var _ref5 = _ref6;
                        var offsetX = _ref5.x;
                        var offsetY = _ref5.y;
                        var relativeX = page.x - offsetX;
                        var relativeY = page.y - offsetY;
                        for (var _i3 = 0; _i3 < (options.targets || []).length; _i3++) {
                            var _ref7;
                            _ref7 = (options.targets || [])[_i3];
                            var snapTarget = _ref7;
                            if (utils.is.function(snapTarget)) {
                                target = snapTarget(relativeX, relativeY, interaction);
                            } else {
                                target = snapTarget;
                            }
                            if (!target) {
                                continue;
                            }
                            targets.push({
                                x: utils.is.number(target.x) ? target.x + offsetX : relativeX,
                                y: utils.is.number(target.y) ? target.y + offsetY : relativeY,
                                range: utils.is.number(target.range) ? target.range : options.range
                            });
                        }
                    }
                    var closest = {
                        target: null,
                        inRange: false,
                        distance: 0,
                        range: 0,
                        dx: 0,
                        dy: 0
                    };
                    for (i = 0, len = targets.length; i < len; i++) {
                        target = targets[i];
                        var range = target.range;
                        var dx = target.x - page.x;
                        var dy = target.y - page.y;
                        var distance = utils.hypot(dx, dy);
                        var inRange = distance <= range;
                        if (range === Infinity && closest.inRange && closest.range !== Infinity) {
                            inRange = false;
                        }
                        if (!closest.target || (inRange ? closest.inRange && range !== Infinity ? distance / range < closest.distance / closest.range : range === Infinity && closest.range !== Infinity || distance < closest.distance : !closest.inRange && distance < closest.distance)) {
                            closest.target = target;
                            closest.distance = distance;
                            closest.range = range;
                            closest.inRange = inRange;
                            closest.dx = dx;
                            closest.dy = dy;
                            status.range = range;
                        }
                    }
                    var snapChanged = void 0;
                    if (closest.target) {
                        snapChanged = status.modifiedX !== closest.target.x || status.modifiedY !== closest.target.y;
                        status.modifiedX = closest.target.x;
                        status.modifiedY = closest.target.y;
                    } else {
                        snapChanged = true;
                        status.modifiedX = NaN;
                        status.modifiedY = NaN;
                    }
                    status.dx = closest.dx;
                    status.dy = closest.dy;
                    status.changed = snapChanged || closest.inRange && !status.locked;
                    status.locked = closest.inRange;
                },
                modifyCoords: function modifyCoords(_ref8) {
                    var page = _ref8.page, client = _ref8.client, status = _ref8.status, phase = _ref8.phase, options = _ref8.options;
                    var relativePoints = options && options.relativePoints;
                    if (options && options.enabled && !(phase === "start" && relativePoints && relativePoints.length)) {
                        if (status.locked) {
                            page.x += status.dx;
                            page.y += status.dy;
                            client.x += status.dx;
                            client.y += status.dy;
                        }
                        return {
                            range: status.range,
                            locked: status.locked,
                            x: status.modifiedX,
                            y: status.modifiedY,
                            realX: status.realX,
                            realY: status.realY,
                            dx: status.dx,
                            dy: status.dy
                        };
                    }
                }
            };
            interact.createSnapGrid = function(grid) {
                return function(x, y) {
                    var limits = grid.limits || {
                        left: -Infinity,
                        right: Infinity,
                        top: -Infinity,
                        bottom: Infinity
                    };
                    var offsetX = 0;
                    var offsetY = 0;
                    if (utils.is.object(grid.offset)) {
                        offsetX = grid.offset.x;
                        offsetY = grid.offset.y;
                    }
                    var gridx = Math.round((x - offsetX) / grid.x);
                    var gridy = Math.round((y - offsetY) / grid.y);
                    var newX = Math.max(limits.left, Math.min(limits.right, gridx * grid.x + offsetX));
                    var newY = Math.max(limits.top, Math.min(limits.bottom, gridy * grid.y + offsetY));
                    return {
                        x: newX,
                        y: newY,
                        range: grid.range
                    };
                };
            };
            modifiers.snap = snap;
            modifiers.names.push("snap");
            defaultOptions.perAction.snap = snap.defaults;
            module.exports = snap;
        }, {
            "../defaultOptions": 18,
            "../interact": 21,
            "../utils": 44,
            "./base": 23
        } ],
        28: [ function(require, module, exports) {
            "use strict";
            var modifiers = require("./base");
            var snap = require("./snap");
            var defaultOptions = require("../defaultOptions");
            var resize = require("../actions/resize");
            var utils = require("../utils/");
            var snapSize = {
                defaults: {
                    enabled: false,
                    endOnly: false,
                    range: Infinity,
                    targets: null,
                    offsets: null
                },
                setOffset: function setOffset(arg) {
                    var interaction = arg.interaction, options = arg.options;
                    var edges = interaction.prepared.edges;
                    if (!edges) {
                        return;
                    }
                    arg.options = {
                        relativePoints: [ {
                            x: edges.left ? 0 : 1,
                            y: edges.top ? 0 : 1
                        } ],
                        origin: {
                            x: 0,
                            y: 0
                        },
                        offset: "self",
                        range: options.range
                    };
                    var offsets = snap.setOffset(arg);
                    arg.options = options;
                    return offsets;
                },
                set: function set(arg) {
                    var interaction = arg.interaction, options = arg.options, offset = arg.offset, modifiedCoords = arg.modifiedCoords;
                    var page = utils.extend({}, modifiedCoords);
                    var relativeX = page.x - offset[0].x;
                    var relativeY = page.y - offset[0].y;
                    arg.options = utils.extend({}, options);
                    arg.options.targets = [];
                    for (var _i = 0; _i < (options.targets || []).length; _i++) {
                        var _ref;
                        _ref = (options.targets || [])[_i];
                        var snapTarget = _ref;
                        var target = void 0;
                        if (utils.is.function(snapTarget)) {
                            target = snapTarget(relativeX, relativeY, interaction);
                        } else {
                            target = snapTarget;
                        }
                        if (!target) {
                            continue;
                        }
                        if ("width" in target && "height" in target) {
                            target.x = target.width;
                            target.y = target.height;
                        }
                        arg.options.targets.push(target);
                    }
                    snap.set(arg);
                },
                modifyCoords: function modifyCoords(arg) {
                    var options = arg.options;
                    arg.options = utils.extend({}, options);
                    arg.options.enabled = options.enabled;
                    arg.options.relativePoints = [ null ];
                    snap.modifyCoords(arg);
                }
            };
            modifiers.snapSize = snapSize;
            modifiers.names.push("snapSize");
            defaultOptions.perAction.snapSize = snapSize.defaults;
            resize.defaults.snapSize = snapSize.defaults;
            module.exports = snapSize;
        }, {
            "../actions/resize": 10,
            "../defaultOptions": 18,
            "../utils/": 44,
            "./base": 23,
            "./snap": 27
        } ],
        29: [ function(require, module, exports) {
            "use strict";
            function _classCallCheck(instance, Constructor) {
                if (!(instance instanceof Constructor)) {
                    throw new TypeError("Cannot call a class as a function");
                }
            }
            var pointerUtils = require("../utils/pointerUtils");
            module.exports = function() {
                function PointerEvent(type, pointer, event, eventTarget, interaction) {
                    _classCallCheck(this, PointerEvent);
                    pointerUtils.pointerExtend(this, event);
                    if (event !== pointer) {
                        pointerUtils.pointerExtend(this, pointer);
                    }
                    this.interaction = interaction;
                    this.timeStamp = new Date().getTime();
                    this.originalEvent = event;
                    this.type = type;
                    this.pointerId = pointerUtils.getPointerId(pointer);
                    this.pointerType = pointerUtils.getPointerType(pointer);
                    this.target = eventTarget;
                    this.currentTarget = null;
                    if (type === "tap") {
                        var pointerIndex = interaction.getPointerIndex(pointer);
                        this.dt = this.timeStamp - interaction.downTimes[pointerIndex];
                        var interval = this.timeStamp - interaction.tapTime;
                        this.double = !!(interaction.prevTap && interaction.prevTap.type !== "doubletap" && interaction.prevTap.target === this.target && interval < 500);
                    } else if (type === "doubletap") {
                        this.dt = pointer.timeStamp - interaction.tapTime;
                    }
                }
                PointerEvent.prototype.subtractOrigin = function subtractOrigin(_ref) {
                    var originX = _ref.x, originY = _ref.y;
                    this.pageX -= originX;
                    this.pageY -= originY;
                    this.clientX -= originX;
                    this.clientY -= originY;
                    return this;
                };
                PointerEvent.prototype.addOrigin = function addOrigin(_ref2) {
                    var originX = _ref2.x, originY = _ref2.y;
                    this.pageX += originX;
                    this.pageY += originY;
                    this.clientX += originX;
                    this.clientY += originY;
                    return this;
                };
                PointerEvent.prototype.preventDefault = function preventDefault() {
                    this.originalEvent.preventDefault();
                };
                PointerEvent.prototype.stopPropagation = function stopPropagation() {
                    this.propagationStopped = true;
                };
                PointerEvent.prototype.stopImmediatePropagation = function stopImmediatePropagation() {
                    this.immediatePropagationStopped = this.propagationStopped = true;
                };
                return PointerEvent;
            }();
        }, {
            "../utils/pointerUtils": 49
        } ],
        30: [ function(require, module, exports) {
            "use strict";
            var PointerEvent = require("./PointerEvent");
            var Interaction = require("../Interaction");
            var utils = require("../utils");
            var defaults = require("../defaultOptions");
            var signals = require("../utils/Signals").new();
            var simpleSignals = [ "down", "up", "cancel" ];
            var simpleEvents = [ "down", "up", "cancel" ];
            var pointerEvents = {
                PointerEvent: PointerEvent,
                fire: fire,
                collectEventTargets: collectEventTargets,
                signals: signals,
                defaults: {
                    holdDuration: 600,
                    ignoreFrom: null,
                    allowFrom: null,
                    origin: {
                        x: 0,
                        y: 0
                    }
                },
                types: [ "down", "move", "up", "cancel", "tap", "doubletap", "hold" ]
            };
            function fire(arg) {
                var interaction = arg.interaction, pointer = arg.pointer, event = arg.event, eventTarget = arg.eventTarget, _arg$type = arg.type, type = _arg$type === undefined ? arg.pointerEvent.type : _arg$type, _arg$targets = arg.targets, targets = _arg$targets === undefined ? collectEventTargets(arg) : _arg$targets, _arg$pointerEvent = arg.pointerEvent, pointerEvent = _arg$pointerEvent === undefined ? new PointerEvent(type, pointer, event, eventTarget, interaction) : _arg$pointerEvent;
                var signalArg = {
                    interaction: interaction,
                    pointer: pointer,
                    event: event,
                    eventTarget: eventTarget,
                    targets: targets,
                    type: type,
                    pointerEvent: pointerEvent
                };
                for (var i = 0; i < targets.length; i++) {
                    var target = targets[i];
                    for (var prop in target.props || {}) {
                        pointerEvent[prop] = target.props[prop];
                    }
                    var origin = utils.getOriginXY(target.eventable, target.element);
                    pointerEvent.subtractOrigin(origin);
                    pointerEvent.eventable = target.eventable;
                    pointerEvent.currentTarget = target.element;
                    target.eventable.fire(pointerEvent);
                    pointerEvent.addOrigin(origin);
                    if (pointerEvent.immediatePropagationStopped || pointerEvent.propagationStopped && i + 1 < targets.length && targets[i + 1].element !== pointerEvent.currentTarget) {
                        break;
                    }
                }
                signals.fire("fired", signalArg);
                if (type === "tap") {
                    var prevTap = pointerEvent.double ? fire({
                        interaction: interaction,
                        pointer: pointer,
                        event: event,
                        eventTarget: eventTarget,
                        type: "doubletap"
                    }) : pointerEvent;
                    interaction.prevTap = prevTap;
                    interaction.tapTime = prevTap.timeStamp;
                }
                return pointerEvent;
            }
            function collectEventTargets(_ref) {
                var interaction = _ref.interaction, pointer = _ref.pointer, event = _ref.event, eventTarget = _ref.eventTarget, type = _ref.type;
                var pointerIndex = interaction.getPointerIndex(pointer);
                if (type === "tap" && (interaction.pointerWasMoved || !(interaction.downTargets[pointerIndex] && interaction.downTargets[pointerIndex] === eventTarget))) {
                    return [];
                }
                var path = utils.getPath(eventTarget);
                var signalArg = {
                    interaction: interaction,
                    pointer: pointer,
                    event: event,
                    eventTarget: eventTarget,
                    type: type,
                    path: path,
                    targets: [],
                    element: null
                };
                for (var _i = 0; _i < path.length; _i++) {
                    var _ref2;
                    _ref2 = path[_i];
                    var element = _ref2;
                    signalArg.element = element;
                    signals.fire("collect-targets", signalArg);
                }
                if (type === "hold") {
                    signalArg.targets = signalArg.targets.filter(function(target) {
                        return target.eventable.options.holdDuration === interaction.holdTimers[pointerIndex].duration;
                    });
                }
                return signalArg.targets;
            }
            Interaction.signals.on("update-pointer-down", function(_ref3) {
                var interaction = _ref3.interaction, pointerIndex = _ref3.pointerIndex;
                interaction.holdTimers[pointerIndex] = {
                    duration: Infinity,
                    timeout: null
                };
            });
            Interaction.signals.on("remove-pointer", function(_ref4) {
                var interaction = _ref4.interaction, pointerIndex = _ref4.pointerIndex;
                interaction.holdTimers.splice(pointerIndex, 1);
            });
            Interaction.signals.on("move", function(_ref5) {
                var interaction = _ref5.interaction, pointer = _ref5.pointer, event = _ref5.event, eventTarget = _ref5.eventTarget, duplicateMove = _ref5.duplicateMove;
                var pointerIndex = interaction.getPointerIndex(pointer);
                if (!duplicateMove && (!interaction.pointerIsDown || interaction.pointerWasMoved)) {
                    if (interaction.pointerIsDown) {
                        clearTimeout(interaction.holdTimers[pointerIndex].timeout);
                    }
                    fire({
                        interaction: interaction,
                        pointer: pointer,
                        event: event,
                        eventTarget: eventTarget,
                        type: "move"
                    });
                }
            });
            Interaction.signals.on("down", function(_ref6) {
                var interaction = _ref6.interaction, pointer = _ref6.pointer, event = _ref6.event, eventTarget = _ref6.eventTarget, pointerIndex = _ref6.pointerIndex;
                var timer = interaction.holdTimers[pointerIndex];
                var path = utils.getPath(eventTarget);
                var signalArg = {
                    interaction: interaction,
                    pointer: pointer,
                    event: event,
                    eventTarget: eventTarget,
                    type: "hold",
                    targets: [],
                    path: path,
                    element: null
                };
                for (var _i2 = 0; _i2 < path.length; _i2++) {
                    var _ref7;
                    _ref7 = path[_i2];
                    var element = _ref7;
                    signalArg.element = element;
                    signals.fire("collect-targets", signalArg);
                }
                if (!signalArg.targets.length) {
                    return;
                }
                var minDuration = Infinity;
                for (var _i3 = 0; _i3 < signalArg.targets.length; _i3++) {
                    var _ref8;
                    _ref8 = signalArg.targets[_i3];
                    var target = _ref8;
                    var holdDuration = target.eventable.options.holdDuration;
                    if (holdDuration < minDuration) {
                        minDuration = holdDuration;
                    }
                }
                timer.duration = minDuration;
                timer.timeout = setTimeout(function() {
                    fire({
                        interaction: interaction,
                        eventTarget: eventTarget,
                        pointer: pointer,
                        event: event,
                        type: "hold"
                    });
                }, minDuration);
            });
            Interaction.signals.on("up", function(_ref9) {
                var interaction = _ref9.interaction, pointer = _ref9.pointer, event = _ref9.event, eventTarget = _ref9.eventTarget;
                if (!interaction.pointerWasMoved) {
                    fire({
                        interaction: interaction,
                        eventTarget: eventTarget,
                        pointer: pointer,
                        event: event,
                        type: "tap"
                    });
                }
            });
            var _arr = [ "up", "cancel" ];
            for (var _i4 = 0; _i4 < _arr.length; _i4++) {
                var signalName = _arr[_i4];
                Interaction.signals.on(signalName, function(_ref11) {
                    var interaction = _ref11.interaction, pointerIndex = _ref11.pointerIndex;
                    if (interaction.holdTimers[pointerIndex]) {
                        clearTimeout(interaction.holdTimers[pointerIndex].timeout);
                    }
                });
            }
            function createSignalListener(type) {
                return function(_ref10) {
                    var interaction = _ref10.interaction, pointer = _ref10.pointer, event = _ref10.event, eventTarget = _ref10.eventTarget;
                    fire({
                        interaction: interaction,
                        eventTarget: eventTarget,
                        pointer: pointer,
                        event: event,
                        type: type
                    });
                };
            }
            for (var i = 0; i < simpleSignals.length; i++) {
                Interaction.signals.on(simpleSignals[i], createSignalListener(simpleEvents[i]));
            }
            Interaction.signals.on("new", function(interaction) {
                interaction.prevTap = null;
                interaction.tapTime = 0;
                interaction.holdTimers = [];
            });
            defaults.pointerEvents = pointerEvents.defaults;
            module.exports = pointerEvents;
        }, {
            "../Interaction": 5,
            "../defaultOptions": 18,
            "../utils": 44,
            "../utils/Signals": 34,
            "./PointerEvent": 29
        } ],
        31: [ function(require, module, exports) {
            "use strict";
            var pointerEvents = require("./base");
            var Interaction = require("../Interaction");
            pointerEvents.signals.on("new", onNew);
            pointerEvents.signals.on("fired", onFired);
            var _arr = [ "move", "up", "cancel", "endall" ];
            for (var _i = 0; _i < _arr.length; _i++) {
                var signal = _arr[_i];
                Interaction.signals.on(signal, endHoldRepeat);
            }
            function onNew(_ref) {
                var pointerEvent = _ref.pointerEvent;
                if (pointerEvent.type !== "hold") {
                    return;
                }
                pointerEvent.count = (pointerEvent.count || 0) + 1;
            }
            function onFired(_ref2) {
                var interaction = _ref2.interaction, pointerEvent = _ref2.pointerEvent, eventTarget = _ref2.eventTarget, targets = _ref2.targets;
                if (pointerEvent.type !== "hold" || !targets.length) {
                    return;
                }
                var interval = targets[0].eventable.options.holdRepeatInterval;
                if (interval <= 0) {
                    return;
                }
                interaction.holdIntervalHandle = setTimeout(function() {
                    pointerEvents.fire({
                        interaction: interaction,
                        eventTarget: eventTarget,
                        type: "hold",
                        pointer: pointerEvent,
                        event: pointerEvent
                    });
                }, interval);
            }
            function endHoldRepeat(_ref3) {
                var interaction = _ref3.interaction;
                if (interaction.holdIntervalHandle) {
                    clearInterval(interaction.holdIntervalHandle);
                    interaction.holdIntervalHandle = null;
                }
            }
            pointerEvents.defaults.holdRepeatInterval = 0;
            pointerEvents.types.push("holdrepeat");
            module.exports = {
                onNew: onNew,
                onFired: onFired,
                endHoldRepeat: endHoldRepeat
            };
        }, {
            "../Interaction": 5,
            "./base": 30
        } ],
        32: [ function(require, module, exports) {
            "use strict";
            var pointerEvents = require("./base");
            var Interactable = require("../Interactable");
            var is = require("../utils/is");
            var scope = require("../scope");
            var extend = require("../utils/extend");
            var _require = require("../utils/arr"), merge = _require.merge;
            pointerEvents.signals.on("collect-targets", function(_ref) {
                var targets = _ref.targets, element = _ref.element, type = _ref.type, eventTarget = _ref.eventTarget;
                scope.interactables.forEachMatch(element, function(interactable) {
                    var eventable = interactable.events;
                    var options = eventable.options;
                    if (eventable[type] && is.element(element) && interactable.testIgnoreAllow(options, element, eventTarget)) {
                        targets.push({
                            element: element,
                            eventable: eventable,
                            props: {
                                interactable: interactable
                            }
                        });
                    }
                });
            });
            Interactable.signals.on("new", function(_ref2) {
                var interactable = _ref2.interactable;
                interactable.events.getRect = function(element) {
                    return interactable.getRect(element);
                };
            });
            Interactable.signals.on("set", function(_ref3) {
                var interactable = _ref3.interactable, options = _ref3.options;
                extend(interactable.events.options, pointerEvents.defaults);
                extend(interactable.events.options, options);
            });
            merge(Interactable.eventTypes, pointerEvents.types);
            Interactable.prototype.pointerEvents = function(options) {
                extend(this.events.options, options);
                return this;
            };
            var __backCompatOption = Interactable.prototype._backCompatOption;
            Interactable.prototype._backCompatOption = function(optionName, newValue) {
                var ret = __backCompatOption.call(this, optionName, newValue);
                if (ret === this) {
                    this.events.options[optionName] = newValue;
                }
                return ret;
            };
            Interactable.settingsMethods.push("pointerEvents");
        }, {
            "../Interactable": 4,
            "../scope": 33,
            "../utils/arr": 35,
            "../utils/extend": 41,
            "../utils/is": 46,
            "./base": 30
        } ],
        33: [ function(require, module, exports) {
            "use strict";
            var utils = require("./utils");
            var events = require("./utils/events");
            var signals = require("./utils/Signals").new();
            var _require = require("./utils/window"), getWindow = _require.getWindow;
            var scope = {
                signals: signals,
                events: events,
                utils: utils,
                document: require("./utils/domObjects").document,
                documents: [],
                addDocument: function addDocument(doc, win) {
                    if (utils.contains(scope.documents, doc)) {
                        return false;
                    }
                    win = win || getWindow(doc);
                    scope.documents.push(doc);
                    events.documents.push(doc);
                    if (doc !== scope.document) {
                        events.add(win, "unload", scope.onWindowUnload);
                    }
                    signals.fire("add-document", {
                        doc: doc,
                        win: win
                    });
                },
                removeDocument: function removeDocument(doc, win) {
                    var index = scope.documents.indexOf(doc);
                    win = win || getWindow(doc);
                    events.remove(win, "unload", scope.onWindowUnload);
                    scope.documents.splice(index, 1);
                    events.documents.splice(index, 1);
                    signals.fire("remove-document", {
                        win: win,
                        doc: doc
                    });
                },
                onWindowUnload: function onWindowUnload() {
                    scope.removeDocument(this.document, this);
                }
            };
            module.exports = scope;
        }, {
            "./utils": 44,
            "./utils/Signals": 34,
            "./utils/domObjects": 38,
            "./utils/events": 40,
            "./utils/window": 52
        } ],
        34: [ function(require, module, exports) {
            "use strict";
            function _classCallCheck(instance, Constructor) {
                if (!(instance instanceof Constructor)) {
                    throw new TypeError("Cannot call a class as a function");
                }
            }
            var Signals = function() {
                function Signals() {
                    _classCallCheck(this, Signals);
                    this.listeners = {};
                }
                Signals.prototype.on = function on(name, listener) {
                    if (!this.listeners[name]) {
                        this.listeners[name] = [ listener ];
                        return;
                    }
                    this.listeners[name].push(listener);
                };
                Signals.prototype.off = function off(name, listener) {
                    if (!this.listeners[name]) {
                        return;
                    }
                    var index = this.listeners[name].indexOf(listener);
                    if (index !== -1) {
                        this.listeners[name].splice(index, 1);
                    }
                };
                Signals.prototype.fire = function fire(name, arg) {
                    var targetListeners = this.listeners[name];
                    if (!targetListeners) {
                        return;
                    }
                    for (var _i = 0; _i < targetListeners.length; _i++) {
                        var _ref;
                        _ref = targetListeners[_i];
                        var listener = _ref;
                        if (listener(arg, name) === false) {
                            return;
                        }
                    }
                };
                return Signals;
            }();
            Signals.new = function() {
                return new Signals();
            };
            module.exports = Signals;
        }, {} ],
        35: [ function(require, module, exports) {
            "use strict";
            function contains(array, target) {
                return array.indexOf(target) !== -1;
            }
            function merge(target, source) {
                for (var _i = 0; _i < source.length; _i++) {
                    var _ref;
                    _ref = source[_i];
                    var item = _ref;
                    target.push(item);
                }
                return target;
            }
            module.exports = {
                contains: contains,
                merge: merge
            };
        }, {} ],
        36: [ function(require, module, exports) {
            "use strict";
            var _require = require("./window"), window = _require.window;
            var is = require("./is");
            var domObjects = require("./domObjects");
            var Element = domObjects.Element;
            var navigator = window.navigator;
            var browser = {
                supportsTouch: !!("ontouchstart" in window || is.function(window.DocumentTouch) && domObjects.document instanceof window.DocumentTouch),
                supportsPointerEvent: !!domObjects.PointerEvent,
                isIOS: /iP(hone|od|ad)/.test(navigator.platform),
                isIOS7: /iP(hone|od|ad)/.test(navigator.platform) && /OS 7[^\d]/.test(navigator.appVersion),
                isIe9: /MSIE 9/.test(navigator.userAgent),
                prefixedMatchesSelector: "matches" in Element.prototype ? "matches" : "webkitMatchesSelector" in Element.prototype ? "webkitMatchesSelector" : "mozMatchesSelector" in Element.prototype ? "mozMatchesSelector" : "oMatchesSelector" in Element.prototype ? "oMatchesSelector" : "msMatchesSelector",
                pEventTypes: domObjects.PointerEvent ? domObjects.PointerEvent === window.MSPointerEvent ? {
                    up: "MSPointerUp",
                    down: "MSPointerDown",
                    over: "mouseover",
                    out: "mouseout",
                    move: "MSPointerMove",
                    cancel: "MSPointerCancel"
                } : {
                    up: "pointerup",
                    down: "pointerdown",
                    over: "pointerover",
                    out: "pointerout",
                    move: "pointermove",
                    cancel: "pointercancel"
                } : null,
                wheelEvent: "onmousewheel" in domObjects.document ? "mousewheel" : "wheel"
            };
            browser.isOperaMobile = navigator.appName === "Opera" && browser.supportsTouch && navigator.userAgent.match("Presto");
            module.exports = browser;
        }, {
            "./domObjects": 38,
            "./is": 46,
            "./window": 52
        } ],
        37: [ function(require, module, exports) {
            "use strict";
            var is = require("./is");
            module.exports = function clone(source) {
                var dest = {};
                for (var prop in source) {
                    if (is.plainObject(source[prop])) {
                        dest[prop] = clone(source[prop]);
                    } else {
                        dest[prop] = source[prop];
                    }
                }
                return dest;
            };
        }, {
            "./is": 46
        } ],
        38: [ function(require, module, exports) {
            "use strict";
            var domObjects = {};
            var win = require("./window").window;
            function blank() {}
            domObjects.document = win.document;
            domObjects.DocumentFragment = win.DocumentFragment || blank;
            domObjects.SVGElement = win.SVGElement || blank;
            domObjects.SVGSVGElement = win.SVGSVGElement || blank;
            domObjects.SVGElementInstance = win.SVGElementInstance || blank;
            domObjects.Element = win.Element || blank;
            domObjects.HTMLElement = win.HTMLElement || domObjects.Element;
            domObjects.Event = win.Event;
            domObjects.Touch = win.Touch || blank;
            domObjects.PointerEvent = win.PointerEvent || win.MSPointerEvent;
            module.exports = domObjects;
        }, {
            "./window": 52
        } ],
        39: [ function(require, module, exports) {
            "use strict";
            var win = require("./window");
            var browser = require("./browser");
            var is = require("./is");
            var domObjects = require("./domObjects");
            var domUtils = {
                nodeContains: function nodeContains(parent, child) {
                    while (child) {
                        if (child === parent) {
                            return true;
                        }
                        child = child.parentNode;
                    }
                    return false;
                },
                closest: function closest(element, selector) {
                    while (is.element(element)) {
                        if (domUtils.matchesSelector(element, selector)) {
                            return element;
                        }
                        element = domUtils.parentNode(element);
                    }
                    return null;
                },
                parentNode: function parentNode(node) {
                    var parent = node.parentNode;
                    if (is.docFrag(parent)) {
                        while ((parent = parent.host) && is.docFrag(parent)) {
                            continue;
                        }
                        return parent;
                    }
                    return parent;
                },
                matchesSelector: function matchesSelector(element, selector) {
                    if (win.window !== win.realWindow) {
                        selector = selector.replace(/\/deep\//g, " ");
                    }
                    return element[browser.prefixedMatchesSelector](selector);
                },
                indexOfDeepestElement: function indexOfDeepestElement(elements) {
                    var deepestZoneParents = [];
                    var dropzoneParents = [];
                    var dropzone = void 0;
                    var deepestZone = elements[0];
                    var index = deepestZone ? 0 : -1;
                    var parent = void 0;
                    var child = void 0;
                    var i = void 0;
                    var n = void 0;
                    for (i = 1; i < elements.length; i++) {
                        dropzone = elements[i];
                        if (!dropzone || dropzone === deepestZone) {
                            continue;
                        }
                        if (!deepestZone) {
                            deepestZone = dropzone;
                            index = i;
                            continue;
                        }
                        if (dropzone.parentNode === dropzone.ownerDocument) {
                            continue;
                        } else if (deepestZone.parentNode === dropzone.ownerDocument) {
                            deepestZone = dropzone;
                            index = i;
                            continue;
                        }
                        if (!deepestZoneParents.length) {
                            parent = deepestZone;
                            while (parent.parentNode && parent.parentNode !== parent.ownerDocument) {
                                deepestZoneParents.unshift(parent);
                                parent = parent.parentNode;
                            }
                        }
                        if (deepestZone instanceof domObjects.HTMLElement && dropzone instanceof domObjects.SVGElement && !(dropzone instanceof domObjects.SVGSVGElement)) {
                            if (dropzone === deepestZone.parentNode) {
                                continue;
                            }
                            parent = dropzone.ownerSVGElement;
                        } else {
                            parent = dropzone;
                        }
                        dropzoneParents = [];
                        while (parent.parentNode !== parent.ownerDocument) {
                            dropzoneParents.unshift(parent);
                            parent = parent.parentNode;
                        }
                        n = 0;
                        while (dropzoneParents[n] && dropzoneParents[n] === deepestZoneParents[n]) {
                            n++;
                        }
                        var parents = [ dropzoneParents[n - 1], dropzoneParents[n], deepestZoneParents[n] ];
                        child = parents[0].lastChild;
                        while (child) {
                            if (child === parents[1]) {
                                deepestZone = dropzone;
                                index = i;
                                deepestZoneParents = [];
                                break;
                            } else if (child === parents[2]) {
                                break;
                            }
                            child = child.previousSibling;
                        }
                    }
                    return index;
                },
                matchesUpTo: function matchesUpTo(element, selector, limit) {
                    while (is.element(element)) {
                        if (domUtils.matchesSelector(element, selector)) {
                            return true;
                        }
                        element = domUtils.parentNode(element);
                        if (element === limit) {
                            return domUtils.matchesSelector(element, selector);
                        }
                    }
                    return false;
                },
                getActualElement: function getActualElement(element) {
                    return element instanceof domObjects.SVGElementInstance ? element.correspondingUseElement : element;
                },
                getScrollXY: function getScrollXY(relevantWindow) {
                    relevantWindow = relevantWindow || win.window;
                    return {
                        x: relevantWindow.scrollX || relevantWindow.document.documentElement.scrollLeft,
                        y: relevantWindow.scrollY || relevantWindow.document.documentElement.scrollTop
                    };
                },
                getElementClientRect: function getElementClientRect(element) {
                    var clientRect = element instanceof domObjects.SVGElement ? element.getBoundingClientRect() : element.getClientRects()[0];
                    return clientRect && {
                        left: clientRect.left,
                        right: clientRect.right,
                        top: clientRect.top,
                        bottom: clientRect.bottom,
                        width: clientRect.width || clientRect.right - clientRect.left,
                        height: clientRect.height || clientRect.bottom - clientRect.top
                    };
                },
                getElementRect: function getElementRect(element) {
                    var clientRect = domUtils.getElementClientRect(element);
                    if (!browser.isIOS7 && clientRect) {
                        var scroll = domUtils.getScrollXY(win.getWindow(element));
                        clientRect.left += scroll.x;
                        clientRect.right += scroll.x;
                        clientRect.top += scroll.y;
                        clientRect.bottom += scroll.y;
                    }
                    return clientRect;
                },
                getPath: function getPath(element) {
                    var path = [];
                    while (element) {
                        path.push(element);
                        element = domUtils.parentNode(element);
                    }
                    return path;
                },
                trySelector: function trySelector(value) {
                    if (!is.string(value)) {
                        return false;
                    }
                    domObjects.document.querySelector(value);
                    return true;
                }
            };
            module.exports = domUtils;
        }, {
            "./browser": 36,
            "./domObjects": 38,
            "./is": 46,
            "./window": 52
        } ],
        40: [ function(require, module, exports) {
            "use strict";
            var is = require("./is");
            var domUtils = require("./domUtils");
            var pointerUtils = require("./pointerUtils");
            var pExtend = require("./pointerExtend");
            var _require = require("./window"), window = _require.window;
            var _require2 = require("./arr"), contains = _require2.contains;
            var elements = [];
            var targets = [];
            var delegatedEvents = {};
            var documents = [];
            var supportsOptions = function() {
                var supported = false;
                window.document.createElement("div").addEventListener("test", null, {
                    get capture() {
                        supported = true;
                    }
                });
                return supported;
            }();
            function add(element, type, listener, optionalArg) {
                var options = getOptions(optionalArg);
                var elementIndex = elements.indexOf(element);
                var target = targets[elementIndex];
                if (!target) {
                    target = {
                        events: {},
                        typeCount: 0
                    };
                    elementIndex = elements.push(element) - 1;
                    targets.push(target);
                }
                if (!target.events[type]) {
                    target.events[type] = [];
                    target.typeCount++;
                }
                if (!contains(target.events[type], listener)) {
                    element.addEventListener(type, listener, supportsOptions ? options : !!options.capture);
                    target.events[type].push(listener);
                }
            }
            function remove(element, type, listener, optionalArg) {
                var options = getOptions(optionalArg);
                var elementIndex = elements.indexOf(element);
                var target = targets[elementIndex];
                if (!target || !target.events) {
                    return;
                }
                if (type === "all") {
                    for (type in target.events) {
                        if (target.events.hasOwnProperty(type)) {
                            remove(element, type, "all");
                        }
                    }
                    return;
                }
                if (target.events[type]) {
                    var len = target.events[type].length;
                    if (listener === "all") {
                        for (var i = 0; i < len; i++) {
                            remove(element, type, target.events[type][i], options);
                        }
                        return;
                    } else {
                        for (var _i = 0; _i < len; _i++) {
                            if (target.events[type][_i] === listener) {
                                element.removeEventListener("on" + type, listener, supportsOptions ? options : !!options.capture);
                                target.events[type].splice(_i, 1);
                                break;
                            }
                        }
                    }
                    if (target.events[type] && target.events[type].length === 0) {
                        target.events[type] = null;
                        target.typeCount--;
                    }
                }
                if (!target.typeCount) {
                    targets.splice(elementIndex, 1);
                    elements.splice(elementIndex, 1);
                }
            }
            function addDelegate(selector, context, type, listener, optionalArg) {
                var options = getOptions(optionalArg);
                if (!delegatedEvents[type]) {
                    delegatedEvents[type] = {
                        selectors: [],
                        contexts: [],
                        listeners: []
                    };
                    for (var _i2 = 0; _i2 < documents.length; _i2++) {
                        var doc = documents[_i2];
                        add(doc, type, delegateListener);
                        add(doc, type, delegateUseCapture, true);
                    }
                }
                var delegated = delegatedEvents[type];
                var index = void 0;
                for (index = delegated.selectors.length - 1; index >= 0; index--) {
                    if (delegated.selectors[index] === selector && delegated.contexts[index] === context) {
                        break;
                    }
                }
                if (index === -1) {
                    index = delegated.selectors.length;
                    delegated.selectors.push(selector);
                    delegated.contexts.push(context);
                    delegated.listeners.push([]);
                }
                delegated.listeners[index].push([ listener, !!options.capture, options.passive ]);
            }
            function removeDelegate(selector, context, type, listener, optionalArg) {
                var options = getOptions(optionalArg);
                var delegated = delegatedEvents[type];
                var matchFound = false;
                var index = void 0;
                if (!delegated) {
                    return;
                }
                for (index = delegated.selectors.length - 1; index >= 0; index--) {
                    if (delegated.selectors[index] === selector && delegated.contexts[index] === context) {
                        var listeners = delegated.listeners[index];
                        for (var i = listeners.length - 1; i >= 0; i--) {
                            var _listeners$i = listeners[i], fn = _listeners$i[0], capture = _listeners$i[1], passive = _listeners$i[2];
                            if (fn === listener && capture === !!options.capture && passive === options.passive) {
                                listeners.splice(i, 1);
                                if (!listeners.length) {
                                    delegated.selectors.splice(index, 1);
                                    delegated.contexts.splice(index, 1);
                                    delegated.listeners.splice(index, 1);
                                    remove(context, type, delegateListener);
                                    remove(context, type, delegateUseCapture, true);
                                    if (!delegated.selectors.length) {
                                        delegatedEvents[type] = null;
                                    }
                                }
                                matchFound = true;
                                break;
                            }
                        }
                        if (matchFound) {
                            break;
                        }
                    }
                }
            }
            function delegateListener(event, optionalArg) {
                var options = getOptions(optionalArg);
                var fakeEvent = {};
                var delegated = delegatedEvents[event.type];
                var _pointerUtils$getEven = pointerUtils.getEventTargets(event), eventTarget = _pointerUtils$getEven[0];
                var element = eventTarget;
                pExtend(fakeEvent, event);
                fakeEvent.originalEvent = event;
                fakeEvent.preventDefault = preventOriginalDefault;
                while (is.element(element)) {
                    for (var i = 0; i < delegated.selectors.length; i++) {
                        var selector = delegated.selectors[i];
                        var context = delegated.contexts[i];
                        if (domUtils.matchesSelector(element, selector) && domUtils.nodeContains(context, eventTarget) && domUtils.nodeContains(context, element)) {
                            var listeners = delegated.listeners[i];
                            fakeEvent.currentTarget = element;
                            for (var j = 0; j < listeners.length; j++) {
                                var _listeners$j = listeners[j], fn = _listeners$j[0], capture = _listeners$j[1], passive = _listeners$j[2];
                                if (capture === !!options.capture && passive === options.passive) {
                                    fn(fakeEvent);
                                }
                            }
                        }
                    }
                    element = domUtils.parentNode(element);
                }
            }
            function delegateUseCapture(event) {
                return delegateListener.call(this, event, true);
            }
            function preventOriginalDefault() {
                this.originalEvent.preventDefault();
            }
            function getOptions(param) {
                return is.object(param) ? param : {
                    capture: param
                };
            }
            module.exports = {
                add: add,
                remove: remove,
                addDelegate: addDelegate,
                removeDelegate: removeDelegate,
                delegateListener: delegateListener,
                delegateUseCapture: delegateUseCapture,
                delegatedEvents: delegatedEvents,
                documents: documents,
                supportsOptions: supportsOptions,
                _elements: elements,
                _targets: targets
            };
        }, {
            "./arr": 35,
            "./domUtils": 39,
            "./is": 46,
            "./pointerExtend": 48,
            "./pointerUtils": 49,
            "./window": 52
        } ],
        41: [ function(require, module, exports) {
            "use strict";
            module.exports = function extend(dest, source) {
                for (var prop in source) {
                    dest[prop] = source[prop];
                }
                return dest;
            };
        }, {} ],
        42: [ function(require, module, exports) {
            "use strict";
            var _require = require("./rect"), resolveRectLike = _require.resolveRectLike, rectToXY = _require.rectToXY;
            module.exports = function(target, element, action) {
                var actionOptions = target.options[action];
                var actionOrigin = actionOptions && actionOptions.origin;
                var origin = actionOrigin || target.options.origin;
                var originRect = resolveRectLike(origin, target, element, [ target && element ]);
                return rectToXY(originRect) || {
                    x: 0,
                    y: 0
                };
            };
        }, {
            "./rect": 51
        } ],
        43: [ function(require, module, exports) {
            "use strict";
            module.exports = function(x, y) {
                return Math.sqrt(x * x + y * y);
            };
        }, {} ],
        44: [ function(require, module, exports) {
            "use strict";
            var extend = require("./extend");
            var win = require("./window");
            var utils = {
                warnOnce: function warnOnce(method, message) {
                    var warned = false;
                    return function() {
                        if (!warned) {
                            win.window.console.warn(message);
                            warned = true;
                        }
                        return method.apply(this, arguments);
                    };
                },
                _getQBezierValue: function _getQBezierValue(t, p1, p2, p3) {
                    var iT = 1 - t;
                    return iT * iT * p1 + 2 * iT * t * p2 + t * t * p3;
                },
                getQuadraticCurvePoint: function getQuadraticCurvePoint(startX, startY, cpX, cpY, endX, endY, position) {
                    return {
                        x: utils._getQBezierValue(position, startX, cpX, endX),
                        y: utils._getQBezierValue(position, startY, cpY, endY)
                    };
                },
                easeOutQuad: function easeOutQuad(t, b, c, d) {
                    t /= d;
                    return -c * t * (t - 2) + b;
                },
                copyAction: function copyAction(dest, src) {
                    dest.name = src.name;
                    dest.axis = src.axis;
                    dest.edges = src.edges;
                    return dest;
                },
                is: require("./is"),
                extend: extend,
                hypot: require("./hypot"),
                getOriginXY: require("./getOriginXY")
            };
            extend(utils, require("./arr"));
            extend(utils, require("./domUtils"));
            extend(utils, require("./pointerUtils"));
            extend(utils, require("./rect"));
            module.exports = utils;
        }, {
            "./arr": 35,
            "./domUtils": 39,
            "./extend": 41,
            "./getOriginXY": 42,
            "./hypot": 43,
            "./is": 46,
            "./pointerUtils": 49,
            "./rect": 51,
            "./window": 52
        } ],
        45: [ function(require, module, exports) {
            "use strict";
            var scope = require("../scope");
            var utils = require("./index");
            var finder = {
                methodOrder: [ "simulationResume", "mouseOrPen", "hasPointer", "idle" ],
                search: function search(pointer, eventType, eventTarget) {
                    var pointerType = utils.getPointerType(pointer);
                    var pointerId = utils.getPointerId(pointer);
                    var details = {
                        pointer: pointer,
                        pointerId: pointerId,
                        pointerType: pointerType,
                        eventType: eventType,
                        eventTarget: eventTarget
                    };
                    for (var _i = 0; _i < finder.methodOrder.length; _i++) {
                        var _ref;
                        _ref = finder.methodOrder[_i];
                        var method = _ref;
                        var interaction = finder[method](details);
                        if (interaction) {
                            return interaction;
                        }
                    }
                },
                simulationResume: function simulationResume(_ref2) {
                    var pointerType = _ref2.pointerType, eventType = _ref2.eventType, eventTarget = _ref2.eventTarget;
                    if (!/down|start/i.test(eventType)) {
                        return null;
                    }
                    for (var _i2 = 0; _i2 < scope.interactions.length; _i2++) {
                        var _ref3;
                        _ref3 = scope.interactions[_i2];
                        var interaction = _ref3;
                        var element = eventTarget;
                        if (interaction.simulation && interaction.simulation.allowResume && interaction.pointerType === pointerType) {
                            while (element) {
                                if (element === interaction.element) {
                                    return interaction;
                                }
                                element = utils.parentNode(element);
                            }
                        }
                    }
                    return null;
                },
                mouseOrPen: function mouseOrPen(_ref4) {
                    var pointerId = _ref4.pointerId, pointerType = _ref4.pointerType, eventType = _ref4.eventType;
                    if (pointerType !== "mouse" && pointerType !== "pen") {
                        return null;
                    }
                    var firstNonActive = void 0;
                    for (var _i3 = 0; _i3 < scope.interactions.length; _i3++) {
                        var _ref5;
                        _ref5 = scope.interactions[_i3];
                        var interaction = _ref5;
                        if (interaction.pointerType === pointerType) {
                            if (interaction.simulation && !utils.contains(interaction.pointerIds, pointerId)) {
                                continue;
                            }
                            if (interaction.interacting()) {
                                return interaction;
                            } else if (!firstNonActive) {
                                firstNonActive = interaction;
                            }
                        }
                    }
                    if (firstNonActive) {
                        return firstNonActive;
                    }
                    for (var _i4 = 0; _i4 < scope.interactions.length; _i4++) {
                        var _ref6;
                        _ref6 = scope.interactions[_i4];
                        var _interaction = _ref6;
                        if (_interaction.pointerType === pointerType && !(/down/i.test(eventType) && _interaction.simulation)) {
                            return _interaction;
                        }
                    }
                    return null;
                },
                hasPointer: function hasPointer(_ref7) {
                    var pointerId = _ref7.pointerId;
                    for (var _i5 = 0; _i5 < scope.interactions.length; _i5++) {
                        var _ref8;
                        _ref8 = scope.interactions[_i5];
                        var interaction = _ref8;
                        if (utils.contains(interaction.pointerIds, pointerId)) {
                            return interaction;
                        }
                    }
                },
                idle: function idle(_ref9) {
                    var pointerType = _ref9.pointerType;
                    for (var _i6 = 0; _i6 < scope.interactions.length; _i6++) {
                        var _ref10;
                        _ref10 = scope.interactions[_i6];
                        var interaction = _ref10;
                        if (interaction.pointerIds.length === 1) {
                            var target = interaction.target;
                            if (target && !target.options.gesture.enabled) {
                                continue;
                            }
                        } else if (interaction.pointerIds.length >= 2) {
                            continue;
                        }
                        if (!interaction.interacting() && pointerType === interaction.pointerType) {
                            return interaction;
                        }
                    }
                    return null;
                }
            };
            module.exports = finder;
        }, {
            "../scope": 33,
            "./index": 44
        } ],
        46: [ function(require, module, exports) {
            "use strict";
            var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function(obj) {
                return typeof obj;
            } : function(obj) {
                return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
            };
            var win = require("./window");
            var isWindow = require("./isWindow");
            var is = {
                array: function array() {},
                window: function window(thing) {
                    return thing === win.window || isWindow(thing);
                },
                docFrag: function docFrag(thing) {
                    return is.object(thing) && thing.nodeType === 11;
                },
                object: function object(thing) {
                    return !!thing && (typeof thing === "undefined" ? "undefined" : _typeof(thing)) === "object";
                },
                function: function _function(thing) {
                    return typeof thing === "function";
                },
                number: function number(thing) {
                    return typeof thing === "number";
                },
                bool: function bool(thing) {
                    return typeof thing === "boolean";
                },
                string: function string(thing) {
                    return typeof thing === "string";
                },
                element: function element(thing) {
                    if (!thing || (typeof thing === "undefined" ? "undefined" : _typeof(thing)) !== "object") {
                        return false;
                    }
                    var _window = win.getWindow(thing) || win.window;
                    return /object|function/.test(_typeof(_window.Element)) ? thing instanceof _window.Element : thing.nodeType === 1 && typeof thing.nodeName === "string";
                },
                plainObject: function plainObject(thing) {
                    return is.object(thing) && thing.constructor.name === "Object";
                }
            };
            is.array = function(thing) {
                return is.object(thing) && typeof thing.length !== "undefined" && is.function(thing.splice);
            };
            module.exports = is;
        }, {
            "./isWindow": 47,
            "./window": 52
        } ],
        47: [ function(require, module, exports) {
            "use strict";
            module.exports = function(thing) {
                return !!(thing && thing.Window) && thing instanceof thing.Window;
            };
        }, {} ],
        48: [ function(require, module, exports) {
            "use strict";
            function pointerExtend(dest, source) {
                for (var prop in source) {
                    var prefixedPropREs = module.exports.prefixedPropREs;
                    var deprecated = false;
                    for (var vendor in prefixedPropREs) {
                        if (prop.indexOf(vendor) === 0 && prefixedPropREs[vendor].test(prop)) {
                            deprecated = true;
                            break;
                        }
                    }
                    if (!deprecated && typeof source[prop] !== "function") {
                        dest[prop] = source[prop];
                    }
                }
                return dest;
            }
            pointerExtend.prefixedPropREs = {
                webkit: /(Movement[XY]|Radius[XY]|RotationAngle|Force)$/
            };
            module.exports = pointerExtend;
        }, {} ],
        49: [ function(require, module, exports) {
            "use strict";
            var hypot = require("./hypot");
            var browser = require("./browser");
            var dom = require("./domObjects");
            var domUtils = require("./domUtils");
            var domObjects = require("./domObjects");
            var is = require("./is");
            var pointerExtend = require("./pointerExtend");
            var pointerUtils = {
                copyCoords: function copyCoords(dest, src) {
                    dest.page = dest.page || {};
                    dest.page.x = src.page.x;
                    dest.page.y = src.page.y;
                    dest.client = dest.client || {};
                    dest.client.x = src.client.x;
                    dest.client.y = src.client.y;
                    dest.timeStamp = src.timeStamp;
                },
                setCoordDeltas: function setCoordDeltas(targetObj, prev, cur) {
                    targetObj.page.x = cur.page.x - prev.page.x;
                    targetObj.page.y = cur.page.y - prev.page.y;
                    targetObj.client.x = cur.client.x - prev.client.x;
                    targetObj.client.y = cur.client.y - prev.client.y;
                    targetObj.timeStamp = cur.timeStamp - prev.timeStamp;
                    var dt = Math.max(targetObj.timeStamp / 1e3, .001);
                    targetObj.page.speed = hypot(targetObj.page.x, targetObj.page.y) / dt;
                    targetObj.page.vx = targetObj.page.x / dt;
                    targetObj.page.vy = targetObj.page.y / dt;
                    targetObj.client.speed = hypot(targetObj.client.x, targetObj.page.y) / dt;
                    targetObj.client.vx = targetObj.client.x / dt;
                    targetObj.client.vy = targetObj.client.y / dt;
                },
                isNativePointer: function isNativePointer(pointer) {
                    return pointer instanceof dom.Event || pointer instanceof dom.Touch;
                },
                getXY: function getXY(type, pointer, xy) {
                    xy = xy || {};
                    type = type || "page";
                    xy.x = pointer[type + "X"];
                    xy.y = pointer[type + "Y"];
                    return xy;
                },
                getPageXY: function getPageXY(pointer, page) {
                    page = page || {};
                    if (browser.isOperaMobile && pointerUtils.isNativePointer(pointer)) {
                        pointerUtils.getXY("screen", pointer, page);
                        page.x += window.scrollX;
                        page.y += window.scrollY;
                    } else {
                        pointerUtils.getXY("page", pointer, page);
                    }
                    return page;
                },
                getClientXY: function getClientXY(pointer, client) {
                    client = client || {};
                    if (browser.isOperaMobile && pointerUtils.isNativePointer(pointer)) {
                        pointerUtils.getXY("screen", pointer, client);
                    } else {
                        pointerUtils.getXY("client", pointer, client);
                    }
                    return client;
                },
                getPointerId: function getPointerId(pointer) {
                    return is.number(pointer.pointerId) ? pointer.pointerId : pointer.identifier;
                },
                setCoords: function setCoords(targetObj, pointers, timeStamp) {
                    var pointer = pointers.length > 1 ? pointerUtils.pointerAverage(pointers) : pointers[0];
                    var tmpXY = {};
                    pointerUtils.getPageXY(pointer, tmpXY);
                    targetObj.page.x = tmpXY.x;
                    targetObj.page.y = tmpXY.y;
                    pointerUtils.getClientXY(pointer, tmpXY);
                    targetObj.client.x = tmpXY.x;
                    targetObj.client.y = tmpXY.y;
                    targetObj.timeStamp = is.number(timeStamp) ? timeStamp : new Date().getTime();
                },
                pointerExtend: pointerExtend,
                getTouchPair: function getTouchPair(event) {
                    var touches = [];
                    if (is.array(event)) {
                        touches[0] = event[0];
                        touches[1] = event[1];
                    } else {
                        if (event.type === "touchend") {
                            if (event.touches.length === 1) {
                                touches[0] = event.touches[0];
                                touches[1] = event.changedTouches[0];
                            } else if (event.touches.length === 0) {
                                touches[0] = event.changedTouches[0];
                                touches[1] = event.changedTouches[1];
                            }
                        } else {
                            touches[0] = event.touches[0];
                            touches[1] = event.touches[1];
                        }
                    }
                    return touches;
                },
                pointerAverage: function pointerAverage(pointers) {
                    var average = {
                        pageX: 0,
                        pageY: 0,
                        clientX: 0,
                        clientY: 0,
                        screenX: 0,
                        screenY: 0
                    };
                    for (var _i = 0; _i < pointers.length; _i++) {
                        var _ref;
                        _ref = pointers[_i];
                        var pointer = _ref;
                        for (var _prop in average) {
                            average[_prop] += pointer[_prop];
                        }
                    }
                    for (var prop in average) {
                        average[prop] /= pointers.length;
                    }
                    return average;
                },
                touchBBox: function touchBBox(event) {
                    if (!event.length && !(event.touches && event.touches.length > 1)) {
                        return;
                    }
                    var touches = pointerUtils.getTouchPair(event);
                    var minX = Math.min(touches[0].pageX, touches[1].pageX);
                    var minY = Math.min(touches[0].pageY, touches[1].pageY);
                    var maxX = Math.max(touches[0].pageX, touches[1].pageX);
                    var maxY = Math.max(touches[0].pageY, touches[1].pageY);
                    return {
                        x: minX,
                        y: minY,
                        left: minX,
                        top: minY,
                        width: maxX - minX,
                        height: maxY - minY
                    };
                },
                touchDistance: function touchDistance(event, deltaSource) {
                    var sourceX = deltaSource + "X";
                    var sourceY = deltaSource + "Y";
                    var touches = pointerUtils.getTouchPair(event);
                    var dx = touches[0][sourceX] - touches[1][sourceX];
                    var dy = touches[0][sourceY] - touches[1][sourceY];
                    return hypot(dx, dy);
                },
                touchAngle: function touchAngle(event, prevAngle, deltaSource) {
                    var sourceX = deltaSource + "X";
                    var sourceY = deltaSource + "Y";
                    var touches = pointerUtils.getTouchPair(event);
                    var dx = touches[1][sourceX] - touches[0][sourceX];
                    var dy = touches[1][sourceY] - touches[0][sourceY];
                    var angle = 180 * Math.atan2(dy, dx) / Math.PI;
                    return angle;
                },
                getPointerType: function getPointerType(pointer) {
                    return is.string(pointer.pointerType) ? pointer.pointerType : is.number(pointer.pointerType) ? [ undefined, undefined, "touch", "pen", "mouse" ][pointer.pointerType] : /touch/.test(pointer.type) || pointer instanceof domObjects.Touch ? "touch" : "mouse";
                },
                getEventTargets: function getEventTargets(event) {
                    var path = is.function(event.composedPath) ? event.composedPath() : event.path;
                    return [ domUtils.getActualElement(path ? path[0] : event.target), domUtils.getActualElement(event.currentTarget) ];
                }
            };
            module.exports = pointerUtils;
        }, {
            "./browser": 36,
            "./domObjects": 38,
            "./domUtils": 39,
            "./hypot": 43,
            "./is": 46,
            "./pointerExtend": 48
        } ],
        50: [ function(require, module, exports) {
            "use strict";
            var _require = require("./window"), window = _require.window;
            var vendors = [ "ms", "moz", "webkit", "o" ];
            var lastTime = 0;
            var request = void 0;
            var cancel = void 0;
            for (var x = 0; x < vendors.length && !window.requestAnimationFrame; x++) {
                request = window[vendors[x] + "RequestAnimationFrame"];
                cancel = window[vendors[x] + "CancelAnimationFrame"] || window[vendors[x] + "CancelRequestAnimationFrame"];
            }
            if (!request) {
                request = function request(callback) {
                    var currTime = new Date().getTime();
                    var timeToCall = Math.max(0, 16 - (currTime - lastTime));
                    var id = setTimeout(function() {
                        callback(currTime + timeToCall);
                    }, timeToCall);
                    lastTime = currTime + timeToCall;
                    return id;
                };
            }
            if (!cancel) {
                cancel = function cancel(id) {
                    clearTimeout(id);
                };
            }
            module.exports = {
                request: request,
                cancel: cancel
            };
        }, {
            "./window": 52
        } ],
        51: [ function(require, module, exports) {
            "use strict";
            var extend = require("./extend");
            var is = require("./is");
            var _require = require("./domUtils"), closest = _require.closest, parentNode = _require.parentNode, getElementRect = _require.getElementRect;
            var rectUtils = {
                getStringOptionResult: function getStringOptionResult(value, interactable, element) {
                    if (!is.string(value)) {
                        return null;
                    }
                    if (value === "parent") {
                        value = parentNode(element);
                    } else if (value === "self") {
                        value = interactable.getRect(element);
                    } else {
                        value = closest(element, value);
                    }
                    return value;
                },
                resolveRectLike: function resolveRectLike(value, interactable, element, functionArgs) {
                    value = rectUtils.getStringOptionResult(value, interactable, element) || value;
                    if (is.function(value)) {
                        value = value.apply(null, functionArgs);
                    }
                    if (is.element(value)) {
                        value = getElementRect(value);
                    }
                    return value;
                },
                rectToXY: function rectToXY(rect) {
                    return rect && {
                        x: "x" in rect ? rect.x : rect.left,
                        y: "y" in rect ? rect.y : rect.top
                    };
                },
                xywhToTlbr: function xywhToTlbr(rect) {
                    if (rect && !("left" in rect && "top" in rect)) {
                        rect = extend({}, rect);
                        rect.left = rect.x || 0;
                        rect.top = rect.y || 0;
                        rect.right = rect.right || rect.left + rect.width;
                        rect.bottom = rect.bottom || rect.top + rect.height;
                    }
                    return rect;
                },
                tlbrToXywh: function tlbrToXywh(rect) {
                    if (rect && !("x" in rect && "y" in rect)) {
                        rect = extend({}, rect);
                        rect.x = rect.left || 0;
                        rect.top = rect.top || 0;
                        rect.width = rect.width || rect.right - rect.x;
                        rect.height = rect.height || rect.bottom - rect.y;
                    }
                    return rect;
                }
            };
            module.exports = rectUtils;
        }, {
            "./domUtils": 39,
            "./extend": 41,
            "./is": 46
        } ],
        52: [ function(require, module, exports) {
            "use strict";
            var win = module.exports;
            var isWindow = require("./isWindow");
            function init(window) {
                win.realWindow = window;
                var el = window.document.createTextNode("");
                if (el.ownerDocument !== window.document && typeof window.wrap === "function" && window.wrap(el) === el) {
                    window = window.wrap(window);
                }
                win.window = window;
            }
            if (typeof window === "undefined") {
                win.window = undefined;
                win.realWindow = undefined;
            } else {
                init(window);
            }
            win.getWindow = function getWindow(node) {
                if (isWindow(node)) {
                    return node;
                }
                var rootNode = node.ownerDocument || node;
                return rootNode.defaultView || rootNode.parentWindow || win.window;
            };
            win.init = init;
        }, {
            "./isWindow": 47
        } ]
    }, {}, [ 1 ])(1);
});

(function(factory) {
    "use strict";
    if (typeof define === "function" && define.amd) {
        define([ "jquery" ], function(jQuery) {
            return factory(jQuery, window);
        });
    } else if (typeof module === "object" && module.exports) {
        module.exports = factory(require("jquery"), window);
    } else {
        factory(jQuery, window);
    }
})(function(jQuery, window) {
    "use strict";
    jQuery.migrateVersion = "3.3.2";
    function compareVersions(v1, v2) {
        var i, rVersionParts = /^(\d+)\.(\d+)\.(\d+)/, v1p = rVersionParts.exec(v1) || [], v2p = rVersionParts.exec(v2) || [];
        for (i = 1; i <= 3; i++) {
            if (+v1p[i] > +v2p[i]) {
                return 1;
            }
            if (+v1p[i] < +v2p[i]) {
                return -1;
            }
        }
        return 0;
    }
    function jQueryVersionSince(version) {
        return compareVersions(jQuery.fn.jquery, version) >= 0;
    }
    (function() {
        if (!window.console || !window.console.log) {
            return;
        }
        if (!jQuery || !jQueryVersionSince("3.0.0")) {
            window.console.log("JQMIGRATE: jQuery 3.0.0+ REQUIRED");
        }
        if (jQuery.migrateWarnings) {
            window.console.log("JQMIGRATE: Migrate plugin loaded multiple times");
        }
        window.console.log("JQMIGRATE: Migrate is installed" + (jQuery.migrateMute ? "" : " with logging active") + ", version " + jQuery.migrateVersion);
    })();
    var warnedAbout = {};
    jQuery.migrateDeduplicateWarnings = true;
    jQuery.migrateWarnings = [];
    if (jQuery.migrateTrace === undefined) {
        jQuery.migrateTrace = true;
    }
    jQuery.migrateReset = function() {
        warnedAbout = {};
        jQuery.migrateWarnings.length = 0;
    };
    function migrateWarn(msg) {
        var console = window.console;
        if (!jQuery.migrateDeduplicateWarnings || !warnedAbout[msg]) {
            warnedAbout[msg] = true;
            jQuery.migrateWarnings.push(msg);
            if (console && console.warn && !jQuery.migrateMute) {
                console.warn("JQMIGRATE: " + msg);
                if (jQuery.migrateTrace && console.trace) {
                    console.trace();
                }
            }
        }
    }
    function migrateWarnProp(obj, prop, value, msg) {
        Object.defineProperty(obj, prop, {
            configurable: true,
            enumerable: true,
            get: function() {
                migrateWarn(msg);
                return value;
            },
            set: function(newValue) {
                migrateWarn(msg);
                value = newValue;
            }
        });
    }
    function migrateWarnFunc(obj, prop, newFunc, msg) {
        obj[prop] = function() {
            migrateWarn(msg);
            return newFunc.apply(this, arguments);
        };
    }
    if (window.document.compatMode === "BackCompat") {
        migrateWarn("jQuery is not compatible with Quirks Mode");
    }
    var findProp, class2type = {}, oldInit = jQuery.fn.init, oldFind = jQuery.find, rattrHashTest = /\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/, rattrHashGlob = /\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/g, rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;
    jQuery.fn.init = function(arg1) {
        var args = Array.prototype.slice.call(arguments);
        if (typeof arg1 === "string" && arg1 === "#") {
            migrateWarn("jQuery( '#' ) is not a valid selector");
            args[0] = [];
        }
        return oldInit.apply(this, args);
    };
    jQuery.fn.init.prototype = jQuery.fn;
    jQuery.find = function(selector) {
        var args = Array.prototype.slice.call(arguments);
        if (typeof selector === "string" && rattrHashTest.test(selector)) {
            try {
                window.document.querySelector(selector);
            } catch (err1) {
                selector = selector.replace(rattrHashGlob, function(_, attr, op, value) {
                    return "[" + attr + op + '"' + value + '"]';
                });
                try {
                    window.document.querySelector(selector);
                    migrateWarn("Attribute selector with '#' must be quoted: " + args[0]);
                    args[0] = selector;
                } catch (err2) {
                    migrateWarn("Attribute selector with '#' was not fixed: " + args[0]);
                }
            }
        }
        return oldFind.apply(this, args);
    };
    for (findProp in oldFind) {
        if (Object.prototype.hasOwnProperty.call(oldFind, findProp)) {
            jQuery.find[findProp] = oldFind[findProp];
        }
    }
    migrateWarnFunc(jQuery.fn, "size", function() {
        return this.length;
    }, "jQuery.fn.size() is deprecated and removed; use the .length property");
    migrateWarnFunc(jQuery, "parseJSON", function() {
        return JSON.parse.apply(null, arguments);
    }, "jQuery.parseJSON is deprecated; use JSON.parse");
    migrateWarnFunc(jQuery, "holdReady", jQuery.holdReady, "jQuery.holdReady is deprecated");
    migrateWarnFunc(jQuery, "unique", jQuery.uniqueSort, "jQuery.unique is deprecated; use jQuery.uniqueSort");
    migrateWarnProp(jQuery.expr, "filters", jQuery.expr.pseudos, "jQuery.expr.filters is deprecated; use jQuery.expr.pseudos");
    migrateWarnProp(jQuery.expr, ":", jQuery.expr.pseudos, "jQuery.expr[':'] is deprecated; use jQuery.expr.pseudos");
    if (jQueryVersionSince("3.1.1")) {
        migrateWarnFunc(jQuery, "trim", function(text) {
            return text == null ? "" : (text + "").replace(rtrim, "");
        }, "jQuery.trim is deprecated; use String.prototype.trim");
    }
    if (jQueryVersionSince("3.2.0")) {
        migrateWarnFunc(jQuery, "nodeName", function(elem, name) {
            return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
        }, "jQuery.nodeName is deprecated");
        migrateWarnFunc(jQuery, "isArray", Array.isArray, "jQuery.isArray is deprecated; use Array.isArray");
    }
    if (jQueryVersionSince("3.3.0")) {
        migrateWarnFunc(jQuery, "isNumeric", function(obj) {
            var type = typeof obj;
            return (type === "number" || type === "string") && !isNaN(obj - parseFloat(obj));
        }, "jQuery.isNumeric() is deprecated");
        jQuery.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "), function(_, name) {
            class2type["[object " + name + "]"] = name.toLowerCase();
        });
        migrateWarnFunc(jQuery, "type", function(obj) {
            if (obj == null) {
                return obj + "";
            }
            return typeof obj === "object" || typeof obj === "function" ? class2type[Object.prototype.toString.call(obj)] || "object" : typeof obj;
        }, "jQuery.type is deprecated");
        migrateWarnFunc(jQuery, "isFunction", function(obj) {
            return typeof obj === "function";
        }, "jQuery.isFunction() is deprecated");
        migrateWarnFunc(jQuery, "isWindow", function(obj) {
            return obj != null && obj === obj.window;
        }, "jQuery.isWindow() is deprecated");
    }
    if (jQuery.ajax) {
        var oldAjax = jQuery.ajax, rjsonp = /(=)\?(?=&|$)|\?\?/;
        jQuery.ajax = function() {
            var jQXHR = oldAjax.apply(this, arguments);
            if (jQXHR.promise) {
                migrateWarnFunc(jQXHR, "success", jQXHR.done, "jQXHR.success is deprecated and removed");
                migrateWarnFunc(jQXHR, "error", jQXHR.fail, "jQXHR.error is deprecated and removed");
                migrateWarnFunc(jQXHR, "complete", jQXHR.always, "jQXHR.complete is deprecated and removed");
            }
            return jQXHR;
        };
        if (!jQueryVersionSince("4.0.0")) {
            jQuery.ajaxPrefilter("+json", function(s) {
                if (s.jsonp !== false && (rjsonp.test(s.url) || typeof s.data === "string" && (s.contentType || "").indexOf("application/x-www-form-urlencoded") === 0 && rjsonp.test(s.data))) {
                    migrateWarn("JSON-to-JSONP auto-promotion is deprecated");
                }
            });
        }
    }
    var oldRemoveAttr = jQuery.fn.removeAttr, oldToggleClass = jQuery.fn.toggleClass, rmatchNonSpace = /\S+/g;
    jQuery.fn.removeAttr = function(name) {
        var self = this;
        jQuery.each(name.match(rmatchNonSpace), function(_i, attr) {
            if (jQuery.expr.match.bool.test(attr)) {
                migrateWarn("jQuery.fn.removeAttr no longer sets boolean properties: " + attr);
                self.prop(attr, false);
            }
        });
        return oldRemoveAttr.apply(this, arguments);
    };
    jQuery.fn.toggleClass = function(state) {
        if (state !== undefined && typeof state !== "boolean") {
            return oldToggleClass.apply(this, arguments);
        }
        migrateWarn("jQuery.fn.toggleClass( boolean ) is deprecated");
        return this.each(function() {
            var className = this.getAttribute && this.getAttribute("class") || "";
            if (className) {
                jQuery.data(this, "__className__", className);
            }
            if (this.setAttribute) {
                this.setAttribute("class", className || state === false ? "" : jQuery.data(this, "__className__") || "");
            }
        });
    };
    function camelCase(string) {
        return string.replace(/-([a-z])/g, function(_, letter) {
            return letter.toUpperCase();
        });
    }
    var oldFnCss, internalSwapCall = false, ralphaStart = /^[a-z]/, rautoPx = /^(?:Border(?:Top|Right|Bottom|Left)?(?:Width|)|(?:Margin|Padding)?(?:Top|Right|Bottom|Left)?|(?:Min|Max)?(?:Width|Height))$/;
    if (jQuery.swap) {
        jQuery.each([ "height", "width", "reliableMarginRight" ], function(_, name) {
            var oldHook = jQuery.cssHooks[name] && jQuery.cssHooks[name].get;
            if (oldHook) {
                jQuery.cssHooks[name].get = function() {
                    var ret;
                    internalSwapCall = true;
                    ret = oldHook.apply(this, arguments);
                    internalSwapCall = false;
                    return ret;
                };
            }
        });
    }
    jQuery.swap = function(elem, options, callback, args) {
        var ret, name, old = {};
        if (!internalSwapCall) {
            migrateWarn("jQuery.swap() is undocumented and deprecated");
        }
        for (name in options) {
            old[name] = elem.style[name];
            elem.style[name] = options[name];
        }
        ret = callback.apply(elem, args || []);
        for (name in options) {
            elem.style[name] = old[name];
        }
        return ret;
    };
    if (jQueryVersionSince("3.4.0") && typeof Proxy !== "undefined") {
        jQuery.cssProps = new Proxy(jQuery.cssProps || {}, {
            set: function() {
                migrateWarn("JQMIGRATE: jQuery.cssProps is deprecated");
                return Reflect.set.apply(this, arguments);
            }
        });
    }
    if (!jQuery.cssNumber) {
        jQuery.cssNumber = {};
    }
    function isAutoPx(prop) {
        return ralphaStart.test(prop) && rautoPx.test(prop[0].toUpperCase() + prop.slice(1));
    }
    oldFnCss = jQuery.fn.css;
    jQuery.fn.css = function(name, value) {
        var camelName, origThis = this;
        if (name && typeof name === "object" && !Array.isArray(name)) {
            jQuery.each(name, function(n, v) {
                jQuery.fn.css.call(origThis, n, v);
            });
            return this;
        }
        if (typeof value === "number") {
            camelName = camelCase(name);
            if (!isAutoPx(camelName) && !jQuery.cssNumber[camelName]) {
                migrateWarn('Number-typed values are deprecated for jQuery.fn.css( "' + name + '", value )');
            }
        }
        return oldFnCss.apply(this, arguments);
    };
    var oldData = jQuery.data;
    jQuery.data = function(elem, name, value) {
        var curData, sameKeys, key;
        if (name && typeof name === "object" && arguments.length === 2) {
            curData = jQuery.hasData(elem) && oldData.call(this, elem);
            sameKeys = {};
            for (key in name) {
                if (key !== camelCase(key)) {
                    migrateWarn("jQuery.data() always sets/gets camelCased names: " + key);
                    curData[key] = name[key];
                } else {
                    sameKeys[key] = name[key];
                }
            }
            oldData.call(this, elem, sameKeys);
            return name;
        }
        if (name && typeof name === "string" && name !== camelCase(name)) {
            curData = jQuery.hasData(elem) && oldData.call(this, elem);
            if (curData && name in curData) {
                migrateWarn("jQuery.data() always sets/gets camelCased names: " + name);
                if (arguments.length > 2) {
                    curData[name] = value;
                }
                return curData[name];
            }
        }
        return oldData.apply(this, arguments);
    };
    if (jQuery.fx) {
        var intervalValue, intervalMsg, oldTweenRun = jQuery.Tween.prototype.run, linearEasing = function(pct) {
            return pct;
        };
        jQuery.Tween.prototype.run = function() {
            if (jQuery.easing[this.easing].length > 1) {
                migrateWarn("'jQuery.easing." + this.easing.toString() + "' should use only one argument");
                jQuery.easing[this.easing] = linearEasing;
            }
            oldTweenRun.apply(this, arguments);
        };
        intervalValue = jQuery.fx.interval || 13;
        intervalMsg = "jQuery.fx.interval is deprecated";
        if (window.requestAnimationFrame) {
            Object.defineProperty(jQuery.fx, "interval", {
                configurable: true,
                enumerable: true,
                get: function() {
                    if (!window.document.hidden) {
                        migrateWarn(intervalMsg);
                    }
                    return intervalValue;
                },
                set: function(newValue) {
                    migrateWarn(intervalMsg);
                    intervalValue = newValue;
                }
            });
        }
    }
    var oldLoad = jQuery.fn.load, oldEventAdd = jQuery.event.add, originalFix = jQuery.event.fix;
    jQuery.event.props = [];
    jQuery.event.fixHooks = {};
    migrateWarnProp(jQuery.event.props, "concat", jQuery.event.props.concat, "jQuery.event.props.concat() is deprecated and removed");
    jQuery.event.fix = function(originalEvent) {
        var event, type = originalEvent.type, fixHook = this.fixHooks[type], props = jQuery.event.props;
        if (props.length) {
            migrateWarn("jQuery.event.props are deprecated and removed: " + props.join());
            while (props.length) {
                jQuery.event.addProp(props.pop());
            }
        }
        if (fixHook && !fixHook._migrated_) {
            fixHook._migrated_ = true;
            migrateWarn("jQuery.event.fixHooks are deprecated and removed: " + type);
            if ((props = fixHook.props) && props.length) {
                while (props.length) {
                    jQuery.event.addProp(props.pop());
                }
            }
        }
        event = originalFix.call(this, originalEvent);
        return fixHook && fixHook.filter ? fixHook.filter(event, originalEvent) : event;
    };
    jQuery.event.add = function(elem, types) {
        if (elem === window && types === "load" && window.document.readyState === "complete") {
            migrateWarn("jQuery(window).on('load'...) called after load event occurred");
        }
        return oldEventAdd.apply(this, arguments);
    };
    jQuery.each([ "load", "unload", "error" ], function(_, name) {
        jQuery.fn[name] = function() {
            var args = Array.prototype.slice.call(arguments, 0);
            if (name === "load" && typeof args[0] === "string") {
                return oldLoad.apply(this, args);
            }
            migrateWarn("jQuery.fn." + name + "() is deprecated");
            args.splice(0, 0, name);
            if (arguments.length) {
                return this.on.apply(this, args);
            }
            this.triggerHandler.apply(this, args);
            return this;
        };
    });
    jQuery.each(("blur focus focusin focusout resize scroll click dblclick " + "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + "change select submit keydown keypress keyup contextmenu").split(" "), function(_i, name) {
        jQuery.fn[name] = function(data, fn) {
            migrateWarn("jQuery.fn." + name + "() event shorthand is deprecated");
            return arguments.length > 0 ? this.on(name, null, data, fn) : this.trigger(name);
        };
    });
    jQuery(function() {
        jQuery(window.document).triggerHandler("ready");
    });
    jQuery.event.special.ready = {
        setup: function() {
            if (this === window.document) {
                migrateWarn("'ready' event is deprecated");
            }
        }
    };
    jQuery.fn.extend({
        bind: function(types, data, fn) {
            migrateWarn("jQuery.fn.bind() is deprecated");
            return this.on(types, null, data, fn);
        },
        unbind: function(types, fn) {
            migrateWarn("jQuery.fn.unbind() is deprecated");
            return this.off(types, null, fn);
        },
        delegate: function(selector, types, data, fn) {
            migrateWarn("jQuery.fn.delegate() is deprecated");
            return this.on(types, selector, data, fn);
        },
        undelegate: function(selector, types, fn) {
            migrateWarn("jQuery.fn.undelegate() is deprecated");
            return arguments.length === 1 ? this.off(selector, "**") : this.off(types, selector || "**", fn);
        },
        hover: function(fnOver, fnOut) {
            migrateWarn("jQuery.fn.hover() is deprecated");
            return this.on("mouseenter", fnOver).on("mouseleave", fnOut || fnOver);
        }
    });
    var rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi, origHtmlPrefilter = jQuery.htmlPrefilter, makeMarkup = function(html) {
        var doc = window.document.implementation.createHTMLDocument("");
        doc.body.innerHTML = html;
        return doc.body && doc.body.innerHTML;
    }, warnIfChanged = function(html) {
        var changed = html.replace(rxhtmlTag, "<$1></$2>");
        if (changed !== html && makeMarkup(html) !== makeMarkup(changed)) {
            migrateWarn("HTML tags must be properly nested and closed: " + html);
        }
    };
    jQuery.UNSAFE_restoreLegacyHtmlPrefilter = function() {
        jQuery.htmlPrefilter = function(html) {
            warnIfChanged(html);
            return html.replace(rxhtmlTag, "<$1></$2>");
        };
    };
    jQuery.htmlPrefilter = function(html) {
        warnIfChanged(html);
        return origHtmlPrefilter(html);
    };
    var oldOffset = jQuery.fn.offset;
    jQuery.fn.offset = function() {
        var elem = this[0];
        if (elem && (!elem.nodeType || !elem.getBoundingClientRect)) {
            migrateWarn("jQuery.fn.offset() requires a valid DOM element");
            return arguments.length ? this : undefined;
        }
        return oldOffset.apply(this, arguments);
    };
    if (jQuery.ajax) {
        var oldParam = jQuery.param;
        jQuery.param = function(data, traditional) {
            var ajaxTraditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
            if (traditional === undefined && ajaxTraditional) {
                migrateWarn("jQuery.param() no longer uses jQuery.ajaxSettings.traditional");
                traditional = ajaxTraditional;
            }
            return oldParam.call(this, data, traditional);
        };
    }
    var oldSelf = jQuery.fn.andSelf || jQuery.fn.addBack;
    jQuery.fn.andSelf = function() {
        migrateWarn("jQuery.fn.andSelf() is deprecated and removed, use jQuery.fn.addBack()");
        return oldSelf.apply(this, arguments);
    };
    if (jQuery.Deferred) {
        var oldDeferred = jQuery.Deferred, tuples = [ [ "resolve", "done", jQuery.Callbacks("once memory"), jQuery.Callbacks("once memory"), "resolved" ], [ "reject", "fail", jQuery.Callbacks("once memory"), jQuery.Callbacks("once memory"), "rejected" ], [ "notify", "progress", jQuery.Callbacks("memory"), jQuery.Callbacks("memory") ] ];
        jQuery.Deferred = function(func) {
            var deferred = oldDeferred(), promise = deferred.promise();
            deferred.pipe = promise.pipe = function() {
                var fns = arguments;
                migrateWarn("deferred.pipe() is deprecated");
                return jQuery.Deferred(function(newDefer) {
                    jQuery.each(tuples, function(i, tuple) {
                        var fn = typeof fns[i] === "function" && fns[i];
                        deferred[tuple[1]](function() {
                            var returned = fn && fn.apply(this, arguments);
                            if (returned && typeof returned.promise === "function") {
                                returned.promise().done(newDefer.resolve).fail(newDefer.reject).progress(newDefer.notify);
                            } else {
                                newDefer[tuple[0] + "With"](this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments);
                            }
                        });
                    });
                    fns = null;
                }).promise();
            };
            if (func) {
                func.call(deferred, deferred);
            }
            return deferred;
        };
        jQuery.Deferred.exceptionHook = oldDeferred.exceptionHook;
    }
    return jQuery;
});